Introduction: Customizable Jack-O-Lantern Lights
The idea behind this project was pretty simple: let my kids pick and change the color of the lights in their Jack-o-lanterns. I had two goals for the project:
1) make is simple for my kids to change the color with out me having to supervise or be involved.
2) make the result mimic an actual candle by making a realistic flickering effect.
Step 1: Gather Parts and Tools
The following parts and tools were what I used. For most of these parts, it isn't essential that you use the exact same part, so if you want to search for cheaper options, feel free.
The following parts and supplies were used to build this project:
- Arduino Micro Buy $25
- Adafruit 24 channel 12-bit PWM Driver Buy $15
- Adafruit full sized Perma-Proto board Buy $7
- Male Headers Buy $5
- Female Headers Buy $8
- Ribbon Cable Buy $3
- Solid Core Hook-Up Wire (Lots of colors Buy $17 or single color Buy $2.50)
- 10 mm Diffused RGB LED (common anode) Buy $10
- Spring Terminal Connectors Buy $5
- 10k Linear Potentiometers (x 9) Buy $1 X 9 = $9
- Potentiometer Caps
- Power Jack Buy $3
- 9v Power Adapter Buy $7
- Perf Boards Buy $1.50 each (buy one for each "candle" you plan to make)
- Heat Shrink Buy $8
The following tools were used:
- Soldering Iron
- Solder
- Wire Strippers
- Wire Cutters
- Philips Head Screw Driver
- Black Electricians Tape
Step 2: The Circuit Diagram
This is the basic layout of the circuit for this project.
A few things to note:
- I used an Arduino Micro specifically because of the number of Analog Inputs it has. I wanted a set of Red/Green/Blue selectors for all three of my kids, which meant I needed a total of 9 Analog Input pins. Most of the other boards available had less than 9 Analog pins. If you don't want 3 sets of RGB Selectors, and only want one or two sets, then you could use a variety of similar boards.
- I used the Adafruit 24-channel PWM Driver because of the number of lights I wanted. Currently, I'm only using three of the sets of pins to drive the LED Candles, but I have the option of adding up to 8 LED Candles. In the future, I want to make more of these available and have more than three LEDs, so I got the bigger board. If you only want up to 4 LED Candles, you might want to look at the smaller and cheaper board Adafruit offers (link)
NOTE: I do have a small error in the diagram. One of the wires connecting the PWM Driver to the Arduino is not shown connected to the correct Arduino pin. I made a note of it in the diagram and posted a picture of the correct pin connection.
Step 3: Assemble the Main Perf Board
When attaching the various components to the main perf board, I didn't want things to be permanent attached, so I soldered a bunch of female headers onto the perf board so that I could detach various pieces in the event that I wanted to make improvements or repairs.
I did solder a few wires permanently onto the perf board. For instance, the wires connecting the Arduino headers and the PWM Driver headers are connected by wires that I soldered onto the board. If you look at the attached image, you'll see:
- There is a brown wire connecting Arduino Pin 6 to the PWM Driver LAT (latch) header pin.
- There is a white wire connecting Arduino Pin 5 to the PWM Driver CLK (clock) header pin
- There is a Yellow wire connecting Arduino Pin 4 to the PWM Driver DAT (data) header pin.
I also soldered on the wires supplying power and ground to the headers that connect to the PWM Driver's power and ground pins.
You may also notice in one of the pictures that I soldered the wires from the power jack directly to the perf board, but that specific piece is covered in the next section, so I didn't go into any details about it here.
Step 4: Add a Power Supply to the Board
In order to supply power to this project, I purchased a 9v power adapter and a power jack for it to plug into on my project.
I attached the power jack to the outside of my enclosure. The positive wire (red) is then soldered onto the perf board so that it links to the VIN pin on the Arduino. The Ground wire (black) from the power jack is then soldered directly to the perf board so that it links to the GRN pin on the Arduino.
That will supply power to the Arduino, but not the whole perf board. To supply power to everything else, I connected the 5v regulated output line from the Arduino to the red power bar on the outside of the perf board. I also connected the Arduino's GRN pin to the blue bar on the outside of the perf board. I also connected the red and blue bars on the left and right side of the perf board by running wire to connect them at the very end of the perf board.
Step 5: Assemble the Potentiometers That Select the RGB Colors
To assemble the potentiometers (pots), follow these steps:
- Use two small sections of ribbon cable, with 2 lines, to connect the three 5v pins and the three Ground pins to each other. Make sure to use enough cable to allow the pots to be spaced far enough apart in the enclosure you will eventually use. In the pictures above, this is the section of ribbon cable that is red and brown.
- Using a longer section of ribbon cable, with 3 lines, connect to the middle output pin of the three pots. This is the yellow, green and blue section of ribbon cable in the pictures above. If you aren't sure how long to make this section of cable, error on the side of being too long.
- At the other end of the ribbon cable that connects to the output pins, I soldered these to a three pin male header. If you look at the diagram earlier in this instructable, you'll notice that one of the sets of analog pins on the Arduino Micro have a 4th pin sandwiched in between the analog pins. So for one of the sets of potentiometers, you will either need to solder this to a 4 pin male header, or split the 3 pin male header into a 2 pin and single pin header. For my setup, I went with the second option and split it into a 2 pin and single pin connection.
- Use electrical tape or heat shrink to ensure each connection between the wires and the headers are isolated and can't accidentally come in contact with the connection next to it. I just used electrical tape. It doesn't look as clean when you're done, but it works.
- Use electrical tape or heat shrink to ensure each connection between the wires and the potentiometer pins are isolated.
Repeat these steps three times to make the three (or as many as you need and/or your Arduino board can handle) sets of potentiometers that will select your RGB values.
Step 6: Assemble the "Candles"
To assemble the "candles", you will need to do the following:
- Take a small piece of perf board to be the base of your candle. You can either buy small individual perf boards, or buy a larger piece that you can cut into smaller pieces. In my case, I did the latter. The smallest you could probably do is 2X8, but a bit bigger than that isn't going to cause problems. The ones that I used were roughly 7X7.
- Cut a long piece of ribbon cable to the size that you need. In my case, each one ended up being about 2 feet long. You will need 4 wires in the ribbon cable.
- Solder an RGB LED to the small piece of perf board.
- Solder one end of each of the 4 wires in the ribbon cable to the perf board.
- Connect the ends of the wires to the leads on the RGB LED.
- Connect 4 pieces of solid core wire to the "other" end of the ribbon cable.
Once you have your candle assembled, you'll need to protect it from possible shorts. The inside of a pumpkin can be pretty wet, so I'm guessing it could cause some havoc with the electric signals going to the LEDs. To avoid this, I simply wrapped the finished product in black electrical tape. This not only protects the electrical connections from the moisture within the pumpkin, but it is also pretty easy to clean off if the inside of the pumpkin is a little messy and gets stuck to your candle.
Step 7: Assemble the Terminals Where You Plug in the Candle
You're going to have to use your imagination a bit on this step. I had everything assembled by the time I realized that needed to add this information, and I didn't want to take it all apart.
Basically, all that I did for this step was to take three sets of four sprint terminals and soldered them onto a small perf board. I then took three long pieces of ribbon cable (each with three wires) and connected one end of the ribbon cable to the spring terminals and the other end to male headers. For the ends that connect to the spring terminal, make sure you keep track of which wire connects to which terminal. You want these three wires to connect to the Red, Green and Blue lead of the LED.
I then took a single wire and attached it to the "5v" terminal on all three sets of spring terminals. On the other end of this single wire I attached a male header which allowed me to plug it into the perf board to supply the 5v connection for all the LEDs.
Once all the necessary wires were soldered onto the perf board and connected to the spring terminals, I cut a small hole in the side of my enclosure and stuck the spring terminals out. I then used a couple of screws and lots of electrical tape to secure the perf board to the inside of the enclosure to hold the terminals in place.
Step 8: Attach the Potentiometers to the Main Board
You can go any number of different ways to make an enclosure for your project, but I just used a shoe box and then glued black construction paper to the outside of it. Obviously you can use something sturdier or fancier, but I went a pretty cost-efficient route and it has worked out fine for me.
The first thing I did to my enclosure was to measure out the spots for the potentiometers on the top. I have 9 potentiometers, which I arranged in 3 columns of 3. The columns are about 2 1/2 inches apart and the potentiometers in each column are about 1 1/8 inches apart. Once I had the positions measured out, I drilled holes to stick the potentiometers through.
Make sure to put the potentiometers in the correct order! I put the ones that adjusts red on top (near the green spring terminals), green in the middle and blue on the bottom. You don't need to use that exact order, but you do need to make sure you plug the wire from that potentiometer into the correct Arduino pin. I have labeled one of the above images to show which potentiometer goes to which Arduino pin on my setup.
The result is a bit mess of wires going all over the place. I've attached a picture of my setup, but I'm not sure how useful it will be.
Step 9: The Code
The code can be downloaded here: github
A couple of things to note in order to understand the code better; all of the logic is contained with in a class called RGB_Candle and the SETUP procedure. If you look at the main LOOP procedure, you'll see that it is doing nothing. That is because the SETUP procedure sets up a timer interrupt, and the procedure that is called by the interrupt event simply calls a method in the RGB_Candle object called "flicker", which does all the work.
Timer Interrupts
I can try to explain why I used Timer Interrupts instead of a bunch of DELAY() statements in the code, but there is already a set of tutorials on Adafruit that does a better job of it than I could do, so I recommend jumping over there and reading those: Part 1Part 2
Array with RGB Number Values
At the very beginning of the code, you'll see an array named "gamma" defined with a bunch of numeric values. These are non-linear gamma corrected values for the RGB LEDs. What is a gamma corrected value? Well, here is a link to another Adafruit tutorial that explains it better than I can: Gamma Correction
Setup Procedure
OK, so now that you know all about Timer Interrupts and Gamma Corrected Values, lets take a look at the SETUP procedure. There isn't a lot going on here, but what is there is fairly important.
void setup() { Serial.begin(9600); candle5.begin(A5,A4,A3,5); candle6.begin(A2,A1,A0,6); candle7.begin(A10,A9,11,7); tlc.begin(); if (oe >= 0) { pinMode(oe, OUTPUT); digitalWrite(oe, LOW); } // timer interup set on timer0 OCR0A = 0xAF; TIMSK0 |= _BV(OCIE0A); }
First, you can see that I have initialized my three Candle objects. If you wanted to change the number of candles, this is the only place where you'd need to add or delete code. The parameters passed to the BEGIN() procedure are:
- Arduino Analog Pin to read the RED value
- Arduino Analog Pin to read the Green value
- Arduino Analog Pin to read the Blue Value
- Set of pins on the TLC5947 board to use to output the values to create a flickering flame effect. The board starts numbering at 0 and has 8 sets of pins (0 thru 7). In my code, I used sets 5, 6 and 7 simply because they were positioned closest to the spot where the wires needed to go.
Next, we initialize the TLC5947. The specific Arduino pins we use to communicate with this board were defined near the top of the code, using the constant variable clock, data and latch.
Finally, we set up a timer interrupt on timer0. This is pretty standard code if you want to use the timer interrupt. It uses a built in timer within the Arduino to call an interrupt process once per millisecond. Because the timer interrupt is going to call this procedure once per millisecond, there isn't any work to be done in the LOOP() procedure, so you'll notice that it is empty.
Interrupt Procedure
The procedure called by timer0 will be defined as SIGNAL(TIMER0_COMPA_vect). That is simply how it is set up to work, so don't try to name it something "better".
// method called by interup on timer0 SIGNAL(TIMER0_COMPA_vect) { unsigned long lCurrMillis = millis(); candle5.Flicker(lCurrMillis); candle6.Flicker(lCurrMillis); candle7.Flicker(lCurrMillis); }
As you can see, the procedure doesn't do much. It gets the current value from MILLIS() and then passes it to each of the Candle objects that I have defined, using the FLICKER() procedure.
Candle.Flicker()
The Candle class is actually where you find most of the work being done in the code. Each candle has three possible display states:
- ShowStandard
- ShowDifference
- Unknown
If the candle is in a "Show Standard" state, it will make the LED light up with the values read from the appropriate potentiometers. If the candle is in a "Show Difference" state, it will make the LED light up with values that are similar to the ones read from the potentiometers, but they will be a little bit off. This is in order to create the appearance of a flickering candle flame.
If the FLICKER() procedure is called, and the Candle object is in a "Show Standard" state, the code will:
- read the RGB values from the potentiometers
- write the RGB values out to the LEDs (via the TLC5947)
- calculate a delay (I currently have it set for a random number of milliseconds, between 0 and 200).
- change the state to "Show Difference"
As the timer interrupt continues to call FLICKER(), the code will continue to check the value of MILLIS() with the delay value calculated earlier. When the appropriate number of milliseconds have gone by, the procedure will execute the code in the "Show Difference" section. This section of the code will:
- read the RGB values from the potentiometers
- determine which value (red, green or blue) has the greatest value
- call calculateFlickerDiff() to randomly alter the value for the color selected in step 2
- write the RGB values (including the modified value from step 3) out to the LEDs (via the TLC5947)
- calculate a delay
- change the state to "Show Standard"
At this point, the timer interrupt will continue to call FLICKER() until the value from MILLIS() surpasses the delay value, and then it will go back into the "Show Standard" code and start the process over again. It will just keep repeating this over and over again, with variable delays and variable adjustments to one of the RGB values to create a flickering effect.
Step 10: Pulling It All Together
At this point, you should be able to plug in you device and test everything out to make sure that it works.
Once you've got everything working correctly, you just need to prepare your jack-o-lantern. For mine, I simply cut a small hole in the back. I made it big enough that I could fit the end of the candle cable through (the end with the 4 loose wires, not the end with the candle itself). The hole was small enough that you didn't notice it at all from the front of the pumpkin.
After your candle is placed in the jack-o-lantern, plug it into the spring terminal on the front of your device. Power up the device and turn a few of the potentiometers to non-zero values and the candles should light up!