I’m a sucker for blinking lights. Everything I’m building or is sitting in my notebook in various stages of thinking about involves some sort of LED, EL panel or other bright thing. So when I went to Bunnings yesterday (buying lights for a different project. ahem) and discovered small cheap battery-powered light strings, I couldn’t resist picking some up. No specific project in mind, but how hard can these things be to drive with an Arduino right?
You get a 6m string of wire with 60 tiny LEDs on it. It runs on 3AA batteries, and the controller relies on a basic timer to run for 6 hours in the evening and stay off the rest of the time. I guess it’s up to the user to go and recalibrate the timer every month or two so it still makes sense. It cost me $15 from Bunnings, but I couldn’t find it on their website just now, so YMMV.
The first thing I did was to put batteries in to the controller and play around, to get a feel for how the system was intended to work. And it’s pretty simple. There’s a push button on the controller to switch between full on, timer mode and off.
Then I opened it up, and the controller was about as simple as I expected. There’s a small unmarked IC; undoubtedly a venerable 555 timer, a few capacitors to run the 555 in astable mode, and a transistor to switch the lights.
I’d like to replace that with some sort of Arduino-based controller, so I broke out my multimeter to check what the LEDs were running from. I found that the voltage drop across the string was an even 3V, down a little from the 3.6V input from my rechargeable batteries, and drawing a hair over 92mA.
I didn’t think it would be a great idea trying to run them from a 5V supply, and the current draw was a lot more than Arduinos can typically supply from their on-board 3V regulator, so I’d have to provide my own lower voltage. But apart from that, making these things slightly smarter shouldn’t present any real challenge.
Building a replacement circuit
So a replacement driver for these lights would need two parts; a lower voltage power supply, and something to switch them on and off based on input from the Arduino. I pulled out my notebook and started to draw up a solution.
For the power, I used an LM1117 3.3V linear regulator. Thanks, past me, for buying a dozen the last time you needed one. All I did with that was copy the example usage schematic out of the data sheet.
And then I added an NPN transistor as a low-side switch (I really like Sparkfun’s transistor tutorial to help understand how to use transistors as switches like this).
That’s really all that’s required. I could run an Arduino from a 5V USB connection, feed power from the Arduino’s Vin pin to this circuit, and use a digital output from the Arduino to switch the lights on and off. Time to see if it works.
Testing and assembly
While assembling I realised my schematic had a couple of problems. First, seeing as I was receiving a regulated 5V supply, using two smoothing capacitors for the linear regulator would be overkill, so I just omitted one. Second, I wasn’t sure if the LED string would need current-limiting resistors, so I assumed that it would and added a 100Ω resistor.
I put circuit together on a breadboard and wired my LED string to the board. Then I took a Freetronics Leostick I had spare, connected the 5V and GND pins to my circuit, and the signal to a PWM pin. Loaded up the Blink example sketch and… nothing happened.
So out came the multimeter again. First checking that all of the connections were solid, and then I started measuring voltages in different places. I had the right voltage coming out of the regulator. The Arduino was switching the right output pin on and off. And I was even getting the voltage readings I was expecting across the LED string. But no blinky-blinky. After glaring at it for a minute or two inspiration struck, and I swapped the leads to the LED string around. Blinky-blinky.
Finally, I soldered my components in to a small strip of prototyping board. I intended it to be a sort of shield for the Leostick, so I added header pins for power and signal, and the whole contraption just plugs in on top. I added a couple more header pins for the LED string, and crimped DuPont connectors on to its leads. Hardware complete!
Programming the Arduino
I wanted to be able to control the lights by sending commands over a serial connection. At the very least, I should be able to set them to a static level. More advanced commands might include blinking, or slowly fading between two different levels. My FairyLights.ino sketch implements a very simple text protocol to control the lights, currently just setting a static level (and the all-important
help command). I’ve written enough text parsers in Arduino that I really couldn’t be bothered doing it again, so I picked up the CmdParser library to handle all the hard work, making my sketch very straightforward based on the CmdParser callback demo code.
Lighting it up
I strung the lights up around the desks in my home office, and plugged my new Arduino-based controller in to my desktop PC. Controlling this setup over a serial connection is a trivial task in any language, but seeing as this machine is mostly running Windows these days I thought it’d make sense to talk to it using PowerShell. My resulting script takes a number as a parameter, opens a serial connection and uses the
set command to set the LED light level. Unfortunately Windows makes it slightly difficult to run a PowerShell script without popping up a console, with the common solution being to launch the script from a VBScript. So the Windows directory for this project includes the control script, as well as a couple of vbs wrappers to turn the lights on and off.
The final step for me was to bind the on and off commands to spare macro keys on my Razer Chroma keyboard. And now I have kitcshy bling at my fingertips.
This was a pretty pointless but mostly fun little hack. As usual, all of my code for this is in my arduino repository. The whole process took me somewhere around 6–7 hours over a couple of days. That included the time I wasted with the LED leads the wrong way around, as well as figuring out a weird hardware-related problem with CmdParser (see my pull request for details). Hopefully this post gives a little insight in to how I think about and put together my projects, and provides some inspiration for other people’s.