Automated IKEA PS 2014
Hi All,
First of all, apologies, I am rushing this through at this time and so will return later to clean up and pad out the details but for now, here is a real quick braindump.
I pretty much fell in love with this IKEA PS 2014 lamp when I first saw it in Ikea but it simply wouldn't suite my old house but having recently moved I jumped on the chance to start this mini project.
I am not the first to do this but having been inspired by others that can be seen on YouTube I decided to make my own personal version using my very rough and ready skills.
Please be aware that I do not claim to be an electronics or microprocessor wizard, instead I love putting modular items and code together.
Anyways, the mission was to create a remote controlled Ikea lamp the core parts of this are/were:
- IKEA PS 2014 Lamp
- Microcontroller - WiFi enabled - Wemos D1 Mini in this case as it is so small and powerful.
- Linear rod assembly, stepper motor with endstops
- Remote control interface - In this case a Raspberry PI hosting a small simply WebApp to control the opening and closing of the lamp.
WeMos D1 Mini and ULA2003 Programing
WeMos D1 Mini microcontrollers can be purchased for around £5 online from eBay or similar. They are great due to their small size and reliable WiFi connectivity along with many GPIO pins 6 of which are needed for this project. 4 for the stepper controller and 2 for the endstops.
The Arduino IDE was used to program the WeMos as follows:
//declare variables for the motor pins
int motorPin1 = 14; // pin5 Blue - 28BYJ48 pin 1 int motorPin2 = 12; // pin6 Pink - 28BYJ48 pin 2 int motorPin3 = 13; // pin7 Yellow - 28BYJ48 pin 3 int motorPin4 = 15; // pin8 Orange - 28BYJ48 pin 4 // Red - 28BYJ48 pin 5 (VCC)
int motorSpeed = 1; //variable to set stepper speed
const int EndStopOpen = 5; const int EndStopClosed = 4; const int LightControl = 6; int State = 0;
// ----------------------WiFiBits---------------- #include #include #include #define USE_SERIAL Serial ESP8266WiFiMulti WiFiMulti; String WebResult = "0";
////////////////////////////////////////////////////////////////////////////// void setup() { //declare the motor pins as outputs pinMode(motorPin1, OUTPUT); pinMode(motorPin2, OUTPUT); pinMode(motorPin3, OUTPUT); pinMode(motorPin4, OUTPUT); pinMode(EndStopOpen, INPUT); pinMode(EndStopClosed, INPUT); // pinMode(LightControl, OUTPUT); Serial.begin(115200);
//-------------------WIFI SETUP----------------- for (uint8_t t = 4; t > 0; t--) { USE_SERIAL.printf("[SETUP] WAIT %d...\n", t); USE_SERIAL.flush(); delay(1000); } WiFiMulti.addAP("ENTERyourSSIDhere", "WIFIpassword");
}
////////////////////////////////////////////////////////////////////////////// void loop() {
// -------------------- READ WEBSITE STATE ------------------------ if ((WiFiMulti.run() == WL_CONNECTED)) { HTTPClient http; USE_SERIAL.print("[HTTP] begin...\n"); // http.begin("http://jcarr437.ddns.net/test.html"); //HTTP http.begin("http://jDOMAINnameHERR.net/LampControl/LampSwitchFile.html"); //HTTP USE_SERIAL.print("[HTTP] GET...\n"); // start connection and send HTTP header int httpCode = http.GET(); // httpCode will be negative on error if (httpCode > 0) { // HTTP header has been send and Server response header has been handled USE_SERIAL.printf("[HTTP] GET... code: %d\n", httpCode); // file found at server if (httpCode == HTTP_CODE_OK) { String payload = http.getString(); USE_SERIAL.println(payload); WebResult = payload; WebResult.remove(1); } } else { USE_SERIAL.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str()); } USE_SERIAL.println(WebResult);
http.end(); //---------------------------STOP LAMP------------------------------ } if (WebResult == "0") { USE_SERIAL.println("STOP"); digitalWrite(motorPin1, LOW); digitalWrite(motorPin2, LOW); digitalWrite(motorPin3, LOW); digitalWrite(motorPin4, LOW); State = 0; }
//---------------------------OPEN LAMP------------------------------ if (WebResult == "1") { State = 1; USE_SERIAL.println("Opening Lamp"); clockwise(); } //---------------------------CLOSE LAMP------------------------------ if (WebResult == "2") { State = 2; USE_SERIAL.println("Closing Lamp"); counterclockwise(); } }
// motorSpeed = 1; // clockwise();
//////////////////////////////////////////////////////////////////////////////
void counterclockwise () { while (digitalRead(EndStopClosed) != HIGH) { // 1 digitalWrite(motorPin1, HIGH); digitalWrite(motorPin2, LOW); digitalWrite(motorPin3, LOW); digitalWrite(motorPin4, LOW); delay(motorSpeed); // 2 digitalWrite(motorPin1, HIGH); digitalWrite(motorPin2, HIGH); digitalWrite(motorPin3, LOW); digitalWrite(motorPin4, LOW); delay (motorSpeed); // 3 digitalWrite(motorPin1, LOW); digitalWrite(motorPin2, HIGH); digitalWrite(motorPin3, LOW); digitalWrite(motorPin4, LOW); delay(motorSpeed); // 4 digitalWrite(motorPin1, LOW); digitalWrite(motorPin2, HIGH); digitalWrite(motorPin3, HIGH); digitalWrite(motorPin4, LOW); delay(motorSpeed); // 5 digitalWrite(motorPin1, LOW); digitalWrite(motorPin2, LOW); digitalWrite(motorPin3, HIGH); digitalWrite(motorPin4, LOW); delay(motorSpeed); // 6 digitalWrite(motorPin1, LOW); digitalWrite(motorPin2, LOW); digitalWrite(motorPin3, HIGH); digitalWrite(motorPin4, HIGH); delay (motorSpeed); // 7 digitalWrite(motorPin1, LOW); digitalWrite(motorPin2, LOW); digitalWrite(motorPin3, LOW); digitalWrite(motorPin4, HIGH); delay(motorSpeed); // 8 digitalWrite(motorPin1, HIGH); digitalWrite(motorPin2, LOW); digitalWrite(motorPin3, LOW); digitalWrite(motorPin4, HIGH); delay(motorSpeed); } digitalWrite(motorPin1, LOW); digitalWrite(motorPin2, LOW); digitalWrite(motorPin3, LOW); digitalWrite(motorPin4, LOW); }
//////////////////////////////////////////////////////////////////////////////
void clockwise() {
while (digitalRead(EndStopOpen) != HIGH) { // 1 digitalWrite(motorPin4, HIGH); digitalWrite(motorPin3, LOW); digitalWrite(motorPin2, LOW); digitalWrite(motorPin1, LOW); delay(motorSpeed); // 2 digitalWrite(motorPin4, HIGH); digitalWrite(motorPin3, HIGH); digitalWrite(motorPin2, LOW); digitalWrite(motorPin1, LOW); delay (motorSpeed); // 3 digitalWrite(motorPin4, LOW); digitalWrite(motorPin3, HIGH); digitalWrite(motorPin2, LOW); digitalWrite(motorPin1, LOW); delay(motorSpeed); // 4 digitalWrite(motorPin4, LOW); digitalWrite(motorPin3, HIGH); digitalWrite(motorPin2, HIGH); digitalWrite(motorPin1, LOW); delay(motorSpeed); // 5 digitalWrite(motorPin4, LOW); digitalWrite(motorPin3, LOW); digitalWrite(motorPin2, HIGH); digitalWrite(motorPin1, LOW); delay(motorSpeed); // 6 digitalWrite(motorPin4, LOW); digitalWrite(motorPin3, LOW); digitalWrite(motorPin2, HIGH); digitalWrite(motorPin1, HIGH); delay (motorSpeed); // 7 digitalWrite(motorPin4, LOW); digitalWrite(motorPin3, LOW); digitalWrite(motorPin2, LOW); digitalWrite(motorPin1, HIGH); delay(motorSpeed); // 8 digitalWrite(motorPin4, HIGH); digitalWrite(motorPin3, LOW); digitalWrite(motorPin2, LOW); digitalWrite(motorPin1, HIGH); delay(motorSpeed); } digitalWrite(motorPin1, LOW); digitalWrite(motorPin2, LOW); digitalWrite(motorPin3, LOW); digitalWrite(motorPin4, LOW); }
Linear Rod, Stepper Motor and EndStops
Images showing push button EndStop test rig then final mounted microswitch EndStops
Final Wiring and Pre Launch Testing
Rather scruffy looking but most of the cabling is hidden from view once the outer shell panels are installed on the lamp.
This photo was mid way through soldering the components together and cabling them together pre go live.
End Results
Images show the closed and open state of the lamp.
They sadly do not show the true warm copper light that is seen in person which looks so so nice :-)