Wednesday, April 9, 2014

Lights In a Jar

I've liked blue lights since I was a kid. I noticed the blue lights when we drove past the airport. I like blue glass also. It's a pleasing color. I was drinking some wine recently and was struck by the blue bottle.

I thought it might look nice if illuminated from inside. Being a little creative, I thought about fun ways to light the bottle from the inside. My first thought was using white LEDs. I though, why not put some strings of LEDs inside at different angles. The next day, I remembered I had an Adafruit Trinket laying around and wondered if it would fit in the mouth of the bottle. It does, with room to spare! How many PWM outputs? 3? nice! Each can drive 20mA, so hmm, ok, with a transistor, could drive some more LEDs off each output. I settled on 3 strings of 4 LEDs hung at different heights in the bottle. I thought I could drive them to fade out at regular intervals to add some interest and make it a little more dynamic.

I wrote some code and soon found that the 3rd PWM output wasn't enabled by default using the Arduino IDE. There is a workaround on the Adafruit forums. Their whole site was down for maintenance when I was working on the code, so I didn't get that fix in until later that evening. I made a video of the problem prior to that, so you can see the earlier code in action. I've posted the code on github.

Let me take a little time to talk about the code for those not so familiar with software design (since that is my profession). If you follow the github link and look at LightsInAJar.ino, you'll find the normal setup and loop functions, but also more. The PWM4_init and analogWrite4 functions come from that forum post and handle the pint 4 PWM problem I mentioned. Setup is pretty straight forward in that it sets the 3 output pin modes, then configures the troublesome PWM output. After that, we get into some logic for a state machine. For those unfamiliar, state machines have been around for a long time. They are sometimes helpful in software since they consist of discrete states and transitions between states. In this case, I've defined 4 states for each of the outputs;
// states for 3 led strands
// 0 = off
// 1 = turning on
// 2 = on
// 3 = turning off

The code in the update function handles what to do in each state. If you check the main loop, it calls update for each LED, then delays 20 milliseconds and repeats, forever. So, for each LED, update is called every 20 milliseconds. Each state increments a counter since I want the LED to remain in each state for a period of time. It also checks a limit to see when it is time to move to the next state. For states 0 and 2, it simply waits and moves to the next state. For states 1 and 3, the PWM value for that pin is also changed. In those states, we are either turning the LED on or off, so we pass the counter value to analogWrite4 when turning the light on, and we pass 128-counter when turning the light off (instead of decrementing the counter. All of the state machine logic is the same for each LED. I set up the state variables differently for each LED to make each output start at a different state, and counter value. I also used "pass by reference" to allow me to pass variable into the update function and use those external variable directly within the function.

Enough about the code! I have single LEDs turning on and off, but I still needed to design the transistor driver circuit and since I'm a little rusty on that, I looked for an on-line circuit simulator. I found CircuitLab which worked pretty well, but for serious use, they need a paid acct. If anybody can give me a pointer to some decent open source visual circuit simulation, I'd be very happy!
I set up a simple driver circuit, designed to handle 4 LEDs at 20mA each. Here's a picture I took of the simulation.

I wired this up and it worked very nicely! I will point out that I am using blue LEDs for breadboarding. I ordered some compact white LEDs from eBay and hope to get those within a week. They were $2.30 for 100, which is way more than I need, but 1/10th the price of RadioShack (which is where I picked up the transistors and resistors).

To power this, I plan on using an old wall adapter for a bluetooth headset. Those put out 300mA and will be enough for this since 12 LEDs at 20mA each + 12mA for the trinket adds up to 252mA. I plan on including a proper power switch as well since I want to power the whole thing off. Otherwise, I may have simply connected a pushbutton to the trinket and made a software switch. I'll follow up with the rest of the project soon!