Automating Light Switch using the ESP32 Board and MicroPython
By: Tomas Rasymas
Tags: Programming, Python, Software Development, Hardware, Automation

A story about how I escaped the boring task that I was doing twice a day by automating it!

Photo by Jaye Haych on Unsplash

A few weeks ago, I mounted outdoor lights on my house. It was a happy moment! 🥳 They added cosiness to my place and of course, made my yard lighter in the middle of the night.

But at the time, I did not think about the switch too much. I installed a simple manual switch 🤦‍♂️ It seemed like no big deal, turning lights on for the night and turning them off in the morning. But after a few weeks, I had changed my mind!

I started to think about how I could tackle this problem and I came up with a few ideas:

Buy an automated light switch, that can be programmed to turn on and off the lights by the time of the day, or maybe over WiFi or something similar. More money is spent but the effect is guaranteed but I need to reinstall the switch.

Another option is to do everything by myself. I am going to learn few new things, everything gonna cost less and I think I will not need to reinstall the switch.

Well, after a bit of thinking (few seconds) I was already Googling for a board that has a built-in WIFI module. 😅💪

As I am an enthusiast of a Python programming language, decided to do everything using MicroPython firmware. Again Googled a bit and found that the ESP32 board works great with MicroPython and what is more it has integrated WIFI! Job is done, I have my board 🎉

In an ideal world, I would install an outdoor light sensor that communicates with my board and based on sensor data I could turn lights on and off. But in reality, I thought that I will go with a simple servo connected to the board and manage the servo by some time constant. It will be MVP!

But instead of using constant time that indicates when lights gonna be on and off, I found sunrise and sunset API which returns sun rising and setting time by location and date. So decided to use this API instead of the light sensor.

Finally, I came up with the algorithm that I will try to implement!

And of course, drew the visualisation of how this invention gonna work and be mounted 🔥

The hardware

The hardware looks as simple as that 👇

Simplest possible 180 degrees servo motor and ESP32 board. Nothing fancy here!

MicroPython

To use MicroPython on the ESP32 board I need to install it first 😅 I created a script to make the installation process repeatable! Just enter the port of the board when connected to the PC and MicroPython firmware path. First, the script will erase the flash of the board, install MicroPython and copy my current lights control firmware files to the board.

Lights control firmware

OOP paradigm was used to make my lights firmware code easier maintainable and readable. I have split each class into separate files.

To access sunrise and sunset time API internet is needed, so let's start from wifi.py 👇

Algorithm of connecting to WIFI 👇

Next servo.py 👇

Methods position_on , position_off and position_default used to control servo movement. As the ESP32 board has a blue LED on it, I decided to use it for the indication (and easier debugging): when the servo is at ON position LED will illuminative and when it is at OFF — LED will be turned off.

Last — time_requests.py 👇

It is used to get sunrise and sunset time from API and to get the current time. You might think: This guy do not know that ESP32 has RTC on it, LOL! , but yes, I knew that! As the sunset and sunrise, API returns time in UTC and on the board I have my local time what is more you know such thing as daylight saving time? I decided to not implement those conversions and just find an API that returns the current time. And I found such — world time API. So from both APIs, I get responses in UTC — my life was quite easy on calculations, but I still had to implement parsing 💪

And yes, I am using connect to WIFI method before each API request just to be sure I am connected to it before I am making the requests!

The core of my firmware: main.py 👇

As you can see the flow is the same as I described earlier. The most exciting part for me — I did not use while (True) sleep() loop!

At first, I implemented it but noticed that on sleep whole board freezes, so Googled a bit and found the solution to my problem — virtual timers! Yes, it looks like MicroPython has a virtual timer. Used it — happy with the result! What is more, as the ESP32 board has a button on it, that could be accessed through MicroPython, I implemented a manual testing option! On button press logic of sunrise or sunset events is executed! And one’s more — without blocking the board! Used interrupt handler for that!

To make everything smooth I added some logic to boot.py too!

On boot I want my servo to be in the default position and try to connect to WIFI as early as possible!

Testing

Well, now as all code and logic are in place, need to try it. By manually executing sunrise and sunset events I see that it is working.

To try light on and off time calculations I faked some data and tested it. It looks like everything works just fine 🎊💪

The last step before pushing it to production — the case and mounting.

Conclusions

The hardest part for me — creating a case for my invention. Tried to adopt different boxes and cases I had at home but nothing suited. One friend volunteered and promised to create it using a 3D printer, so waiting for my case ⌛️

I put 3–4 nights of work for this gadget and I learned a lot! Is it worth such effort? Well yes, seeing your created device working, really lifts the mood 😎

I put the whole code into the Github repository — you can check it out and use it freely. ☮️

More content at plainenglish.io