MQTT Mood Lights With ESP32
I had been tempted for quite some time to hop onto the LED bandwagon, so I ran out and picked up an LED strip to toy with. I ended up making these mood lights. They can be controlled with MQTT, making it possible to add all sorts of smarts.
This is a good weekend project if you have nothing else going on, and want to get your hands dirty making something.
Note that the purpose of this Instructable is to document my project and share ideas with others, and not necessarily to provide solid instructions and methods. With that said, read on!
Supplies
Electronics:
- 1x ESP32 development board
- 1x 0.96" I2C OLED display
- 1x Buzzer
- 1x Barrel jack
- 1x 12V power supply (current depends on the length of your strip)
- 1x LM2596 buck converter
- 1x Common-anode RGB LED strip
- 3x IRFZ44N MOSFETs
- 3x BC547 transistors
- 3x 10kΩ resistors
- 4x 100Ω resistors
- 1x prototyping board
- 4x screw terminals
- Male and female headers
- Wire (I used single-strand)
Other hardware and tools:
- Your desired material for an enclosure (I used MDF)
- Flat, conductive material for touch contacts (I used a thin aluminum sheet)
- Saws, drills, sandpaper, etc.
- Soldering iron and friends
- Hot glue
I would strongly recommend not going for an ESP32 with a built-in OLED display, because it becomes very hard to make a well-aligned cutout in your enclosure for it.
Electronics
The schematic attached shows all the required connections, except for the touch inputs. There is also a relatively vague breadboard diagram showing how to wire up one MOSFET, in case the schematic is inadequate.
Power
An LM2596 buck converter steps down the 12V from the power supply to 5V for the ESP's VIN. Make sure that your power supply is properly rated for the length of LED strip you use. My 2 meter long strip draws a little more than 2 amps.
Pins and peripherals
Four touch pins are used for, well, touch inputs. My ESP32 board came with an OLED display attached, whose I2C pins were hardwired in. This uses four PWM pins, one for each color component (red, green, and blue), and one for the buzzer.
MOSFET muddles
MOSFETs were chosen to handle the fast switching times for PWM and relatively high current. There is one MOSFET for each color component. I used separate NPN BJTs (BC547) along with a pull-up resistor to drive the IRFZ44Ns, as the 3.3V digital signals from the ESP32 may not have been enough for the MOSFETs to conduct as much current as needed. Logic-level MOSFETs like the IRLZ44N exist, but I found out about them only after I had finished soldering everything up. Either way, my strip that draws ~2A works fine.
Soldering
Screw terminals are used to connect to the LED strip, and female headers to plug the ESP32 into, in case I wanted to replace either of them without desoldering things. Soldering took about two hours, and was very straightforward. I also gave my LED strip some longer wires.
Why I chose the ESP32
It has WiFi and Bluetooth on board (though I've used only WiFi right now), and I had one lying around that I was itching to use. The touch inputs also came in handy for the interface on the controller, as they need only one wire going to a contact. If you wanted to, though, the ESP32 could easily be replaced by a microcontroller like the ESP8266.
Code
I used the Arduino toolset (actually the Arduino extension for VS Code :) ) to program this. There are great tutorials like this one on how to get started with the ESP32 and Arduino IDE, if you haven't already.
There are four different modes to handle: static color, random color, Red Alert, and Blue Alert. There are four touch inputs for up, down, next, and Red Alert. Touch uses interrupts.
I added MQTT to the works as well, so that I could control it over WiFi. I'm trying to get a feel for the web-app big three (HTML, CSS, JS), so I designed a Star Trek-themed (but rather ugly) webpage that communicates with an MQTT broker to control the mood lights.
All my code can be found attached, along with a quick reference sheet, whose filename you may want to change to make it a markdown. Move all the files to a folder with the name "ESP32MQTTMoodLighting" before opening with Arduino.
Note that my code works, but is probably not the greatest. But that shouldn't matter, because you're going to write your own anyway, right? :)
Enclosure and Assembly
During the lockdown, the only material I could get my hands on was a sheet of 5mm MDF. I made the large cuts with a regular hacksaw, and gave everything a good sand. A double coat of enamel paint finished the main preparation.
Back Panel
I wanted my box to be easily openable, so I mounted all my electronics to the back panel with four M2 PCB standoffs. My perfboard already had M2 holes drilled into it. My standoffs had little threaded stubs at the bottom, which I intended to be fixed into the MDF. But, I didn't have an M2 drill bit. So, marking the position of each hole, I used a small flat head screwdriver to manually gouge out the holes. Crude but effective. The diameters of the holes were just a little smaller than those of the threaded portion of the standoff. I twisted the standoffs in and out of the holes a few times, which widened and almost threaded them.
Eventually, the standoffs sat firmly in their holes and held the perfboard in place. Because my MDF was very thick, nothing showed through to the other side.
I drilled the hole for the power jack, and made a slot for the LED strip wires to pass through, right below where my screw terminals were situated.
Front Panel
OLED Display Cutout
I started my cutout for the OLED with a few starter holes, and filed them out to size. It ended up being very wonky and misaligned. Not double-checking measurements may have played a part in that, but save yourself some trouble by not using a development board with a built-in OLED. It's much easier to just mount the display to your hole.
Connector
I fashioned a connector out of some male and female headers. One end attached to the wires connected to the touch contacts on the front panel, while the other side had wires running to the ESP's touch inputs. This was so that the front panel could be completely removed from the back if necessary, without disturbing solder joints. If you mount anything else to your front panel, you may want to make a connector for that as well.
Touch Pads
The touch contacts were made of some aluminum sheet. I cut it to get the four pads needed, and verified that there were no jagged edges. I then drilled holes into the front panel, just big enough for a wire. For letting solder stick to the pads, I scuffed up a small portion of one side with sandpaper to remove the oxidized layer, and then gave it a quick wipe to remove any particles. Running each wire through its corresponding hole in the front panel, I soldered each one to its pad. Make sure your solder doesn't create too large a bulge on the back, as this won't allow the pad to sit flush with the panel.
Finally, add some hot glue to the back of each pad and push them onto the front panel. Adding too much will make the pads sit raised from the panel. Clean up any excess glue that may have been pushed out from under the pads.
The Rest
The side panels are quite straightforward. A quick-access hole to the screw terminals was more trouble than it was worth. I hot glued the side panels to the front panel.
Velcro on two edges holds the front portion to the back panel. The gaps allow for the buzzer's sound to escape. If you do a better job than me, you shouldn't end up with something that looks like a 5-year-old's preschool craft :)
My LED strip had a sticky back (I'm sure yours does too). I mounted mine such that the light diffuses off the wall.
Plug It In!
You should now have a complete MQTT-controlled mood light. I have mounted mine to my desk, where it adds a splash of color to sometimes monotonous work. Night is the ideal time to impress people with it.
I hope you enjoyed reading this Instructable, and got a few ideas for your own projects. As I mentioned before, I am a beginner, and this is my first Instructable. I would appreciate any tips and comments.