If earlier they said: “Laziness is the engine of progress”, now you can slightly change the proverb “COVID and laziness are the engine of progress.” Already more than once the authors of homemade products point to the reason why they took on any project – the coronavirus and, in this regard, isolation.
The author of this homemade product was also lured to take up the job by isolation. He spent a lot of time on the balcony, and it annoyed him that every day he had to open and close the curtains. Then he decided to automate the process.
Blinds automation is a common project, but almost all the examples he has found so far have operated blinds using a chain or rotating a small pivot shaft. Its balcony curtain is large and heavy, 8 feet (2.4 m) wide and weighs 8 pounds (3.6 kg). A handle and a barbell are used to lower/raise it, and not a typical mechanism that has been automated in other projects.
The master found a powerful engine, designed a circuit and programmed a microcontroller. To control the lifting/lowering process, he installed a switch with up/down buttons and used NFC to display the position of the shade. He also connected everything to the Internet and the curtain can be controlled through voice commands Google Assistant.
Demonstration of the device can be watched on the video.
Tools and materials: – ESP32 board; – NFC PN532 module; – Servo motor; – Waterproof plastic box; – Bracket for connecting the motor to the crank; – Structural elements for mounting; – Extension wires for the servo; – 330 Ohm resistor 2 pcs; – Resistor 220 Ohm; -Resistor 1 kOhm; -Design module; -Pin connector; -Terminal block; -Waterproof buttons; -Acrylic sheet; -Power adapter; -Printing board; -Soldering accessories;
The complete code, schematic and sketch for the PCB can be downloaded here.
Step One: Servo Motor
The balcony curtain is quite heavy and this became the determining factor when choosing a motor. It was necessary to find something powerful enough to move this shade.
The master found a sufficiently powerful motor, which in combination with a servo drive is quite suitable for the task. To raise or lower the curtain, the master needs to turn the handle 60 times. The servomotor has a characteristic of 31 rpm. Those. the ascent will take about two minutes.
To connect the motor to the crank, the master purchased a bracket. Tested both directions.
Step two: engine installation
It is important to set the motor so that the lug rotates smoothly. Matching the rotation of the engine with the rotation of the crank turned out to be quite a challenge. Any mismatch between the planes of rotation of the engine and the crank can cause friction, which will damage the curtain mechanism or the engine.
On the site, the master found and ordered various brackets, brackets, etc. With the help of it, he secured the engine coaxially with the eye.
Step three : building a circuit
The wizard wanted to start small – build a circuit with two buttons that can rotate the motor in both directions. Control will be done via Arduino .
The code is pretty simple – each button is connected to a pin on the Arduino, and the code is always read from those pins to determine when the button is pressed.
void loop () & # 123; //Reading the value in the pins connected to the buttons. //Normally returns HIGH, while pressing the button it returns LOW btnUpCurr = digitalRead (PIN_UP_BTN); btnDownCurr = digitalRead (PIN_DOWN_BTN); //The UP button is pressed if (btnUpCurr == LOW & amp; & amp; btnUpPrev == HIGH) & # 123; //If the motor is already spinning - stop it if (raisingShade || loweringShade) & # 123; stopShade (); } else & # 123; raiseShade (); }} //The DOWN button is pressed if (btnDownCurr == LOW & amp; & amp; btnDownPrev == HIGH) & # 123; if (raisingShade || loweringShade) & # 123; stopShade (); } else & # 123; lowerShade (); }}}
The motor is also connected to an Arduino pin, which is controlled by an API that is part of the Arduino Servo library.
void lowerShade () & # 123; myServo.attach (PIN_SERVO); //Value smaller than 1500 will spin the motor counter-clockwise myServo.writeMicroseconds (850); loweringShade = true; raisingShade = false; } void raiseShade () & # 123; myServo.attach (PIN_SERVO); //Value larger than 1500 will spin the motor clockwise myServo.writeMicroseconds (2100); raisingShade = true; loweringShade = false; }
After testing and verifying the operation of this simple circuit, the wizard decided to switch from an Arduino board to a more compact and powerful microcontroller – ESP32.
Working with an ESP32 is very similar to working with an Arduino board in that both use the Arduino IDE and have many common libraries. ESP32 supports WiFI which will be useful at a later stage. The small size of the module is also an important factor.
Step four: assembly of the first prototype
To test the device, the wizard assembles it on a printed circuit board. It uses a 7.4V battery for power. Two buttons were also installed.
The motor can draw up to 7.4V according to its specification, so it uses a 7.4V battery that connects directly to the motor. However, for the ESP32, the voltage needs to be reduced to 5V. The master added a DC/DC buck converter that converts the 7.4V batteries to the 5V powering the ESP32.
He used the prototype for several weeks and everything worked great. It was very convenient to operate the curtains, and the motor lifted this heavy curtain without difficulty.
There was only one problem – a full battery lasted only 5 days. It's a pretty powerful battery with a lot of capacity, so he did some calculations. The motor consumes between 200 mA and 3000 mA during operation. Most of the time the ESP32 is in standby mode and consumes 50mA. Battery 6200 mAh. This means it can power a 50mA device for 124 hours (6200/50 = 124), which is just over 5 days.
After calculations, he decided that the best solution was to simply dismantle the battery. He installed the connector and plugged in a 7.5V power adapter.
Step five: support auto stop using NFC
To raise or lower the shade, you only need to press one button, but the engine is also stopped manually. Those. you need to wait and press the button again to turn off the engine. The master wanted to automate this process too.
The easiest is to measure the time it takes to fully open/close the curtain, and then write this time in the code.
Another option is to use a Hall sensor. Stick on the curtain 2 magnets, one at the top, and fix the sensor on the wall.
The master decided to try a third method – using NFC to read position markers. Using NFC, you can read the tags placed on the curtain. In this way, the degree of opening of the shade can be controlled. For example, “100% open”, “50% open”, etc.
PN532 is the most popular device for this purpose. Almost all mobile phones that support NFC use this chip, which is used for things like wireless payments or exchanging data between neighboring devices. He connected the PN532 to the main curtain controller circuit using the I2C communication protocol.
Working with the NFC PN532 module is not difficult. The wizard used the Adafruit PN532 library which has a great API to communicate with the NFC module, but there was a problem. In standby mode, you cannot use the buttons to raise or lower the shade. Then he had to make some changes.
//The DOWN button is pressed if (btnDownCurr == LOW & amp; & amp; btnDownPrev == HIGH) & # 123; if (raisingShade || loweringShade) & # 123; stopShade (); } else & # 123; lowerShade (); //Puts the NFC reader on a listening mode, a NON-BLOCKING call nfc.startPassiveTargetIDDetection (PN532_MIFARE_ISO14443A); listeningToNFC = true; }}
While waiting for NFC tags, the controller continuously monitors the value of the IRQ pin on the NFC module (yellow wire in the diagram above). When the IRQ goes from HIGH to LOW, the NFC tag/card information needs to be read.
irqCurr = digitalRead (PN532_IRQ); //If the NFC reader is currently listening and we’re notified via the //IRQ line that a card was detected if (listeningToNFC & amp; & amp; irqCurr == LOW & amp; & amp; irqPrev == HIGH) & # 123; //Read the detected NFC tag & # 39; s info success = nfc.readDetectedPassiveTargetID (uid, & amp; uidLength); if (success) & # 123; //If the tag is valid, we & # 39; ll read its ID uint32_t cardId = getCardId (uid, uidLength); if (cardId == CARDID_0_PERCENT) & # 123; if (loweringShade) & # 123; //Found the & # 34; 0% open & # 34; position tag while lowering the shade, //we can stop because the shade is now fully closed stopShade (); listeningToNFC = false; }} else if (cardId == CARDID_100_PERCENT) & # 123; //Similar implementation as above. //Stop raising the shade when the CARDID_100_PERCENT tag is detected, //since the shade is now fully open. }}} & lt; br & gt;
With these changes, the up/down buttons are always running and the engine can be stopped either by pressing any of the buttons or when the NFC reader reads the corresponding NFC tag.
Then the master fixes the marks on the curtain, and the reader next to the curtain. He used a sheet of acrylic. The acrylic was bent and fixed on the wall, and the reader was fixed on it. When moving, the curtain slides over the acrylic and the marks are aligned with the reader.
Before adding additional software features, he decided to optimize the device a little.
The first thing he did was install a waterproof junction box. I moved the circuit and the NFC module to the box. I fixed the box with the module on a plastic sheet. After that I removed the old junction box, which was installed on the wall.
Then I cut off a part of the acrylic sheet.
Step six : printed circuit board
Then the master decided to make a circuit board for the device.
He had never designed printed circuit boards before, and the experience was useful. They used EasyEDA software to design the board. Then I ordered a board on one of the resources.
Step seven : voice control
This is a change that turns the controller into a “smart controller.”
Before you can get Google Assistant to send commands to the device, you need to find a way to communicate. ESP32 supports Wi-Fi and can connect to your home router. The most common protocol for communicating with IoT and embedded devices is MQTT, a lightweight messaging protocol.
It uses a cloud service to set up MQTT. On Adafruit IO, I created an account and added a new channel for my project.
Next I updated the code.
AdafruitIO_WiFi io (IO_USERNAME, IO_KEY, WIFI_SSID, WIFI_PASS); //Adafruit IO feed for how much the shade should be open (either 0% or 100%) AdafruitIO_Feed * balconyShade = io.feed (& # 34; shade-open & # 34;); boolean connectingInProgress = false; void loop () & # 123; //Keep the connection alive, if already connected. //Times-out after 400ms to keep the microcontroller responsive. aio_status_t ioStatus = io.run (400, true); //Connect to Adafruit IO, if connected then subscribe to the feed if (ioStatus & lt; AIO_CONNECTED & amp; & amp;! ConnectingInProgress) & # 123; connectingInProgress = true; io.connect (); } else if (ioStatus & gt; = AIO_CONNECTED & amp; & amp; connectingInProgress) & # 123; connectingInProgress = false; //Subscribe to the & # 34; shade-open & # 34; feed balconyShade- & gt; onMessage (handleShadeLevelMessage); } //...} & lt; br & gt;
Communication with the cloud service is supported by the io.run () call, which is part of the main loop function. When a new message is sent to the “shade-open” channel by some other client that is also connected to the cloud service, the handleShadeLevelMessage () callback function is called.
& # 91; code & # 93; //This function is called when a new message is sent to the “shade-open” feed. void handleShadeLevelMessage (AdafruitIO_Data * data) & # 123; //Got a new message with the percent the shade should be open int percentOpen = atoi (data- & gt; value ()); //If we & # 39; re asked to open the shade to 100%, then raise it. //Open to 0% means closing/lowering the shade. if (percentOpen == 100) & # 123; raiseShade (); } else if (percentOpen == 0) & # 123; lowerShade (); } //...}
The callback function reads a new message and closes or opens the curtain accordingly.
The device is already can receive commands from the Internet using MQTT, and if we want Google Assistant to control it, we need to connect them.
IFTTT (If-this-then-that) is a tool for connecting various web services and products to each other. It already supports integrations with Google Assistance and Adafruit IO, so all you had to do was authenticate with both services and create applets for communication between them.
To control the controller, he created an applet that responds to the Google Assistant command and sends a message to the “open curtain” channel in his Adafruit IO account. For example, when he says, “Ok Google, open the balcony shade,” IFTTT will send the message “100” to the channel. The shade controller receives this message through Adafruit IO and raises the shade until it reaches the NFC tag that signals that the shade is 100% open.
Everything is ready. The master says that during the implementation of this project he learned a lot. It was possible to immediately use NFC, voice control, etc., but he decided to go from simple to difficult to acquire new skills.