Outdoor Sunblind Control Via WiFi With ESP8266 and Android App
by jurajs84 in Circuits > Arduino
520 Views, 0 Favorites, 0 Comments
Outdoor Sunblind Control Via WiFi With ESP8266 and Android App
Hi, let me introduce you to my first project on this great website.
I bought a flat with outdoor venetian blinds a couple of years ago. The blinds are equipped with electric control with simple manual buttons on the wall. I wasn't satisfied enough with this wire control, so I decided to change it.
My goal was to operate all blinds by ESP8266. Each ESP is connected to my WiFi and they are controlled by an android app. All via my local WiFi only. Buttons are connected to ESP, so manual control is still possible.
The result is the PCB with ESP8266 in a small 3d printed box and my android App. The box is very easy to install to the built-in venetian blind wire control system.
How Do It Work - Original Circuit Wiring (without ESP Box)
To move the blind up / down, you have to press and hold the up / down button. The blind counts its revolutions, so when the blind is full up / down, it automatically turns off, even if the button is still pressed.
How Do It Work - Button Control With ESP Box
The PCB with the ESP is placed between the electric motor and the switch. The ESP is operated by a signal from the switch and my app via WiFi.
To move the blind up / down, you have to press the button only for a few milliseconds. This will send a high voltage signal to the PCB input (there is a particular part of the circuit, that changes the high voltage signal to the 3V3 signal and put it to the input of ESP8266).
To stop blind, you have to press the same button.
To change a moving direction, press the second button.
Based on these signals, the ESP controls the output relay, that puts high voltage to the blind drive. Because of the short input signal, each ESP board has to have a defined time, how long the output relay is on ( it depends, on how much time the blind needs from full open to full close). In the ESP code, the time is called "upDownTime" and you have to set it for each blind. The "upDownTime" is only the minimum time for the blind, when you will define more time than the blind needs (just for sure), it doesn't matter, because as I mentioned, the blind drive counts its revolution and it stops anyway.
Wire Diagram
Downloads
PCB
Downloads
Component List
- ESP 8266 Mini D1
- 2x relay NT75 CS12 DC5V
- 2x terminal block 2 pole 250V 5mm
- 1x terminal block 3 pole 250V 5mm
- power source Hi-Link HLK-PM01 3W 100-240V AC/ 5V DC
- fuse 1A with holder 5x20mm
- 2x resistor 150k 2W
- 2x resistor 47k 0.4W
- 2x resistor 1k 0.4W
- 2x bridge rectifer DB107
- 2x zener diode 5.1V 0.5W
- 2x electrolytic capacitor 100uF/25V 6.3x11 2.5mm
- 2x optocoupler PC817C
- 2x pin header 1x8 for ESP 8266
- 2x transistor BC547B THT 0,1A, 0,625W, TO92
- 2x diode 1N4007 DO41
- 2x cable gland PG 13.5
ESP 8266 Code
The code uses the ESPAsyncWebServer.h library, which allows us to take advantage of the asynchronous network.
//--------------------------------------------------------------------------------------- //This code is for sunblide PCB with NPN transistors and buttons are operated by log 0 //The PCB is in box. //Btn UP is on D6 //--------------------------------------------------------------------------------------- #include "ESPAsyncTCP.h" #include "ESPAsyncWebServer.h" #include "ESP8266WiFi.h" #define RELAY_ON 1 #define RELAY_OFF 0 #define BTN_ON 0 //add constans due to different logic of NPN trans and buttons #define BTN_OFF 1 // your WiFi credentials const char* ssid = "xxxxxxxxx"; const char* password = "xxxxxxxxxx"; AsyncWebServer server(80); //53s for study room int upDownTime = 63000; //full close or full open time - need to set for each blind in milliseconds unsigned long startTimeUp = 0; unsigned long endTimeUp = 0; boolean timeRunningUp = false; unsigned long startTimeDown = 0; unsigned long endTimeDown = 0; boolean timeRunningDown = false; //delay constants between change of relay states #define delayInterval_1 50 //drive manufacturer recommends 300ms unsigned long time_1 = 0; //inputs, outputs const int relayPinUp = 5;//D1 const int relayPinDown = 4;//D2 const int btnDownInput = 2;//D4 const int btnUpInput = 12;//D6 int btnDownState = BTN_ON; int btnUpState = BTN_ON; int relayDownState = RELAY_OFF; int relayUpState = RELAY_OFF; int lastBtnDownState; int lastBtnUpState; int wifiInput = false; unsigned long lastDebounceTime = 0; unsigned long debounceDelay = 50; unsigned long restartTime = 0; int restartDelay = 10000; String ip = "off"; void setup() { digitalWrite(relayPinUp, RELAY_OFF); digitalWrite(relayPinDown, RELAY_OFF); pinMode(relayPinUp, OUTPUT); pinMode(relayPinDown, OUTPUT); delay(2000);//check that all relays are inactive at reset pinMode(btnDownInput, INPUT_PULLUP); pinMode(btnUpInput, INPUT_PULLUP); Serial.begin(115200); WiFi.begin(ssid, password); //turn off broadcasting WiFi AP //ESP8266 with some firmware are set to broadcast WiFi AP WiFi.mode(WIFI_STA); Serial.println(WiFi.localIP()); Serial.println(WiFi.macAddress()); server.on("/up_off", HTTP_PUT, [](AsyncWebServerRequest * request) { request -> send(200, "text/plain", WiFi.localIP().toString()); //digitalWrite(relayPinUp, RELAY_OFF); relayUpState = RELAY_OFF; wifiInput = false; }); server.on("/up_on", HTTP_PUT, [](AsyncWebServerRequest * request) { request -> send(200, "text/plain", WiFi.localIP().toString()); wifiInput = true; //digitalWrite(relayPinUp, RELAY_ON); relayUpState = RELAY_ON; time_1 = millis(); }); server.on("/down_off", HTTP_PUT, [](AsyncWebServerRequest * request) { request -> send(200, "text/plain", WiFi.localIP().toString()); //digitalWrite(relayPinDown, RELAY_OFF); relayDownState = RELAY_OFF; wifiInput = false; }); server.on("/down_on", HTTP_PUT, [](AsyncWebServerRequest * request) { request -> send(200, "text/plain", WiFi.localIP().toString()); wifiInput = true; //digitalWrite(relayPinDown, RELAY_ON); relayDownState = RELAY_ON; time_1 = millis(); }); // sends status server.on("/status", HTTP_PUT, [](AsyncWebServerRequest * request) { request -> send(200, "text/plain", WiFi.localIP().toString()); }); // gets upDownTime in milisec server.on("/get_running_time", HTTP_PUT, [](AsyncWebServerRequest * request) { request -> send(200, "text/plain", String(upDownTime)); }); // sets upDownTime in milisec server.on("/set_running_time", HTTP_PUT, [](AsyncWebServerRequest * request) { request -> send(200, "text/plain", String(upDownTime)); }); server.begin(); } void loop() { if (WiFi.status() == WL_CONNECTED) { if (ip != WiFi.localIP().toString()) { ip = WiFi.localIP().toString(); Serial.println(ip); } } //reset counting for auto-off if (relayUpState == RELAY_OFF) { timeRunningUp = false; } if (relayDownState == RELAY_OFF) { timeRunningDown = false; } btnDownClick(); btnUpClick(); //auto-off after upDownTime if (relayUpState == RELAY_ON ) { if (durationTimeUp()) { relayUpState = RELAY_OFF; } } if (relayDownState == RELAY_ON) { if (durationTimeDown()) { relayDownState = RELAY_OFF; } } } void btnDownClick() { int readingbtnDown = digitalRead(btnDownInput); // check to see if you just pressed the button // (i.e. the input went from LOW to HIGH), and you've waited long enough // since the last press to ignore any noise: // If the switch changed, due to noise or pressing: if (readingbtnDown != lastBtnDownState) { // reset the debouncing timer lastDebounceTime = millis(); } if ((millis() - lastDebounceTime) > debounceDelay) { // whatever the reading is at, it's been there for longer than the debounce // delay, so take it as the actual current state: // if the button state has changed: if (readingbtnDown != btnDownState) { btnDownState = readingbtnDown; // only toggle the button if the new button state is HIGH if (btnDownState == BTN_ON) { relayUpState = RELAY_OFF; btnUpClick(); relayDownState = !relayDownState; time_1 = millis(); } } } // set the relay with delay: if (millis() > time_1 + delayInterval_1) { // set the relay: digitalWrite(relayPinDown, relayDownState); } // save the reading. Next time through the loop, it'll be the lastButtonState: lastBtnDownState = readingbtnDown; } void btnUpClick() { int readingBtnUp = digitalRead(btnUpInput); // check to see if you just pressed the button // (i.e. the input went from LOW to HIGH), and you've waited long enough // since the last press to ignore any noise: // If the switch changed, due to noise or pressing: if (readingBtnUp != lastBtnUpState) { // reset the debouncing timer lastDebounceTime = millis(); } if ((millis() - lastDebounceTime) > debounceDelay) { // whatever the reading is at, it's been there for longer than the debounce // delay, so take it as the actual current state: // if the button state has changed: if (readingBtnUp != btnUpState) { btnUpState = readingBtnUp; // only toggle the button if the new button state is HIGH if (btnUpState == BTN_ON) { relayDownState = RELAY_OFF; btnDownClick(); relayUpState = !relayUpState; time_1 = millis(); } } } // set the relay with delay: if (millis() > time_1 + delayInterval_1) { digitalWrite(relayPinUp, relayUpState); } // save the reading. Next time through the loop, it'll be the lastButtonState: lastBtnUpState = readingBtnUp; } boolean durationTimeUp() { if (timeRunningUp == false) { startTimeUp = millis(); timeRunningUp = true; } if (timeRunningUp == true) { endTimeUp = millis(); if ((endTimeUp - startTimeUp) > upDownTime) { timeRunningUp = false; return true; } else { return false; } } } boolean durationTimeDown() { if (timeRunningDown == false) { startTimeDown = millis(); timeRunningDown = true; } if (timeRunningDown == true) { endTimeDown = millis(); if ((endTimeDown - startTimeDown) > upDownTime) { timeRunningDown = false; return true; } else { return false; } } }
Downloads
Sunblind App
All blinds can be operated by an android app. I wrote a simple app that you can download from Google App Store for free: Sunblind Control.
The app can communicate to blind ESPs only via your local WiFi. When you want to add your new blind, you have to know the IP address that was assigned by your WiFi router. The best way how to find out your IP is via Arduino IDE and Serial monitor. When you upload the code to ESP, open the serial monitor and you should see how ESP is trying to connect to your wifi (don't forget to write your WiFi credentials to the code). After a successful connection, the ESP will show its IP address.
The second way how to find out your ESP IP is via your router. When you go to the router settings, there should be some info page with all connected devices and their assigned IP addresses.
When your ESP is online, the letters are green. You can operate more blinds at once by tapping on desired blind. If your blind is still offline (letters are red), check the WiFi coverage in that area, IP address, or WiFi credentials.