Introduction: Arduino-controlled Halloween RGB Lights and Strobe

I recently went to a "Trunk or Treat" where you decorate the trunk/inside of your car and join a bunch of others in a parking lot so that neighborhood kids can trick-or-treat without having to walk all over their neighborhoods. I'm one of those guys who likes going overboard, so I figured I'd throw and Arduino and a whole bunch of LED's in the car along with the spooky decorations my wife picked out, and a big pot of dry ice soup to crank out lots of "smoke".

I neglected to get pictures of the whole setup while it was still in the car. This was all installed in a 2006 Grand Cherokee with two of the RGB channels fastened to the ceiling, pointing down in the back, then one channel on both the rear and front seats pointing up. The back of the Jeep was lined with black fleece and spooky decorations. The pot of dry ice was also in the back with the "smoke" pouring out over the bumper and onto the ground. The strobes were put under the Jeep, facing rearward.

Ultimately this guide is about building the light show. How/where you install it is up to your creativity. This could very easily be used inside/outside your house rather than in a car. On to the build...

Step 1: Assemble the Parts

The BOM for this project was:

  • 1x Arduino Mega
  • 1x Screw terminal breakout shield (optional)
  • 1x 5 meter roll of 5050 RGB LEDs (waterproof if appropriate)
  • 4x 12VDC COB LEDs (in my case, two cool white and two warm because that's what I had laying around)
  • 1x 12VDC 2A power supply (generic LED driver)
  • 1x 19VDC 9A power supply (generic laptop charger)
  • 3x 10k potentiometers with knobs (only two shown in photos)
  • 14x RFP30N06LE mosfets or similar logic-level switching transistor
    • The important thing for this part is that it have a Vgs(th) range of 1-2v so that the Arduino can effectively turn it on and off with the least resistance possible
  • 4x 5 position terminal blocks
  • Assorted wires, jumpers and header pins, plus a piece of perf-board for soldering down the mosfets.

COB LEDs are much more common these days so there's a lot to choose from. Keep in mind that the more LEDs in the COB array, the more you can over-drive them because the over-current will be distributed across more chips. This avoids burning out the individual LEDs. In the Arduino code you'll see where the on-time for these COBs is set initially very low. This is to avoid burning them out straight away if you're using smaller arrays. Start with the initial value of 500 and increase it by 200-300 until you either get the brightness you want, or you burn out your LEDs. In my case, I had the on-time set to 5000 but your settings will vary greatly depending on the LEDs and power supply you choose.

Step 2: Solder All Those Mosfets

Begin by laying out your perf-board with all the mosfets. I laid mine out so that it was broken into four sets of three (four channels, each with one red/green/blue driver) and lined up the mosfet pins so that I could easily solder all the source pins together. If you don't know how mosfets work, or what the pins on them are, there's tons of handy tutorials out there so Google-up a few. For our time together, I'll assume you know what the three terminals on a mosfet are (source, drain, gate).

Solder everything down. Now connect the header pins to each of the gate pins on the mosfets, and then add a wire to each of the drain pins as well. These drain pin wires will later screw down to the terminal blocks to make connecting/disconnecting the LED strings easier.

You could also solder down the potentiometers to this board, but I opted to just hot-glue them to the plywood that everything else was mounted to then connect them via a screw terminal breakout. This was just for the sake of convenience.

Step 3: Prepare Your LEDs

I setup four RGB LED panels by gluing down two lengths of the RGB tape to a piece of foam-core board, then connecting the R, G, B and 12+ terminals from each strip to the other at one end. I added hot glue across the strips for added stability, then soldered some 20ga solid wire to the other end of one strip. This 20ga wire is what ran to the terminal blocks. In the pictures, these 20ga wires were cut to facilitate removing the LED panels from the car at the end of the night.

I also fastened the four COB LEDs to a piece of 1/8" plywood and connected them all in parallel. The Arduino sketch is setup to handle two independent strobes because I initially thought I'd have one strobe facing the front of the car and the other to the rear, but I ended up just using one channel. You can certainly use both if your application calls for it, or add more by copying/pasting the relevant code to suit your needs.

Last I wired the two power supplies to the terminal blocks. Because I used NPN mosfets, the switched leg was ground so the source pins from all the mosfets were connected to the ground terminal on the blocks. The positive leads from all the LEDs were connected directly to the 12v for RGB and 19v for strobes.

Step 4: Wire Up the Arduino

Wiring for the Arduino is straightforward. RGB channels go to PWM pins, strobes go to regular digital pins and the pots go to analog pins.

The Arduino Mega is COMPLETE over kill for this project, but it's the only board that has this many native PWM pins. I probably could have done this with a regular Uno or Pro Mini, because the sketch is really small, but then I'd need some external PWM source that runs over I2C or SPI and that just seemed like it was overly complicated. Plus I had recently picked up a pile of off-brand Mega boards from Microcenter for $10/ea so cost wasn't really a factor.

I powered the Mega with a USB battery pack because, well, I had one laying around. The Mega could have just as easily run off the 12v power supply but to avoid any possibility of noise or interference I decided to keep it separate.

Step 5: And Now, the Code!

This sketch got thrown together in like 10 minutes in the parking lot before the event started, so super inefficient. I should have used while loops in a bunch of places, and probably should have used an array for storing a bunch of the RGB variables. Because this was all running on a Mega and size wasn't a consideration, I decided to write the sketch in such a way that it was easy to understand and change for your needs.

// First channel
int red1 = 2; int green1 = 3; int blue1 = 4; // Second channel int red2 = 5; int green2 = 6; int blue2 = 7; // Third channel int red3 = 8; int green3 = 9; int blue3 = 10; // Fourth channel int red4 = 11; int green4 = 12; int blue4 = 13; // First channel int redVal1 = 0; //Starting value for red int greenVal1 = 125; //Starting value for green int blueVal1 = 255; //Starting value for blue int redStep1 = 10; // Increase for coarser transitions int greenStep1 = 6; // Decrease for finer transitions int blueStep1 = 2; // Set all six to the same values to only fade white // Second channel int redVal2 = 75; int greenVal2 = 100; int blueVal2 = 200; int redStep2 = 14; int greenStep2 = 2; int blueStep2 = 20; // Third channel int redVal3 = 30; int greenVal3 = 60; int blueVal3 = 90; int redStep3 = 9; int greenStep3 = 40; int blueStep3 = 100; // Fourth channel int redVal4 = 200; int greenVal4 = 125; int blueVal4 = 10; int redStep4 = 45; int greenStep4 = 75; int blueStep4 = 95; long randomNumber; int fadeDelay = 200; long fadeLast = 0; int strobePin1 = 28; int strobePin2 = 30; int strobeDelay1 = 200; int strobeDelay2 = 200; long strobeLast1 = 0; long strobeLast2 = 0; int strobeDuration = 500; // This is microseconds, start at 500 and adjust up to prevent // burning out your LEDs. High chip-count COB's can be // overdriven much more than single LED's or smaller arrays #define RANDOMSTROBE 1 #define TWOSTROBES 0 void setup() { pinMode(red1, OUTPUT); pinMode(red2, OUTPUT); pinMode(red3, OUTPUT); pinMode(red4, OUTPUT); pinMode(green1, OUTPUT); pinMode(green2, OUTPUT); pinMode(green3, OUTPUT); pinMode(green4, OUTPUT); pinMode(blue1, OUTPUT); pinMode(blue2, OUTPUT); pinMode(blue3, OUTPUT); pinMode(blue4, OUTPUT); pinMode(strobePin1, OUTPUT); pinMode(strobePin2, OUTPUT); randomSeed(analogRead(0)); } void setColor1(int red, int green, int blue) { red = 255 - red; green = 255 - green; blue = 255 - blue; analogWrite(red1, red); analogWrite(green1, green); analogWrite(blue1, blue); } void setColor2(int red, int green, int blue) { red = 255 - red; green = 255 - green; blue = 255 - blue; analogWrite(red2, red); analogWrite(green2, green); analogWrite(blue2, blue); } void setColor3(int red, int green, int blue) { red = 255 - red; green = 255 - green; blue = 255 - blue; analogWrite(red3, red); analogWrite(green3, green); analogWrite(blue3, blue); } void setColor4(int red, int green, int blue) { red = 255 - red; green = 255 - green; blue = 255 - blue; analogWrite(red4, red); analogWrite(green4, green); analogWrite(blue4, blue); } void loop() { fadeDelay = analogRead(0); fadeDelay = map(fadeDelay, 0, 1023, 50, 200); if ((millis() - fadeLast) > fadeDelay) { fadeLast = millis(); // First channel redVal1 = redVal1 + redStep1; greenVal1 = greenVal1 + greenStep1; blueVal1 = blueVal1 + blueStep1; // Second channel redVal2 = redVal2 + redStep2; greenVal2 = greenVal2 + greenStep2; blueVal2 = blueVal2 + blueStep2; // Third channel redVal3 = redVal3 + redStep3; greenVal3 = greenVal3 + greenStep3; blueVal3 = blueVal3 + blueStep3; // Fourth channel redVal4 = redVal4 + redStep4; greenVal4 = greenVal4 + greenStep4; blueVal4 = blueVal4 + blueStep4; if (redVal1 > 255) { redVal1 = random(0, 200); } if (greenVal1 > 255) { greenVal1 = random(0, 200); } if (blueVal1 > 255) { blueVal1 = random(0, 200); } if (redVal2 > 255) { redVal2 = random(0, 200); } if (greenVal2 > 255) { greenVal2 = random(0, 200); } if (blueVal2 > 255) { blueVal2 = random(0, 200); } if (redVal3 > 255) { redVal3 = random(0, 200); } if (greenVal3 > 255) { greenVal3 = random(0, 200); } if (blueVal3 > 255) { blueVal3 = random(0, 200); } if (redVal4 > 255) { redVal4 = random(0, 200); } if (greenVal4 > 255) { greenVal4 = random(0, 200); } if (blueVal4 > 255) { blueVal4 = random(0, 200); } setColor1(redVal1, greenVal1, blueVal1); setColor2(redVal2, greenVal2, blueVal2); setColor3(redVal3, greenVal3, blueVal3); setColor4(redVal4, greenVal4, blueVal4); } if (RANDOMSTROBE) { if ((millis() - strobeLast1) > strobeDelay1) { strobeLast1 = millis(); digitalWrite(strobePin1, HIGH); delayMicroseconds(strobeDuration); digitalWrite(strobePin1, LOW); strobeDelay1 = random(250, 2000); } if (TWOSTROBES) { if ((millis() - strobeLast2) > strobeDelay2) { strobeLast2 = millis(); digitalWrite(strobePin2, HIGH); delayMicroseconds(strobeDuration); digitalWrite(strobePin2, LOW); strobeDelay2 = random(250, 2000); } } } else { if ((millis() - strobeLast1) > strobeDelay1) { strobeLast1 = millis(); digitalWrite(strobePin1, HIGH); delayMicroseconds(strobeDuration); digitalWrite(strobePin1, LOW); strobeDelay1 = analogRead(1); strobeDelay1 = map(strobeDelay1, 0, 1023, 250, 2000); } if (TWOSTROBES) { if ((millis() - strobeLast2) > strobeDelay2) { strobeLast2 = millis(); digitalWrite(strobePin2, HIGH); delayMicroseconds(strobeDuration); digitalWrite(strobePin2, LOW); strobeDelay2 = analogRead(2); strobeDelay2 = map(strobeDelay2, 0, 1023, 250, 2000); } } } }

Step 6: Make It Your Own

The sketch is setup to cycle through the three colors in each channel at different rates, and the first pot is used to speed up or slow down the speed of the transitions. You can alter the last two values in "fadeDelay = map(fadeDelay, 0, 1023, 50, 200)" to create a larger range of speeds to select from.

The second and third pots control the delay between strobe flashes, or you can skip connecting these two pots and set the "#define RANDOMSTROBE 0" to "1" instead and let the Arduino randomly select a delay each time the strobe fires. Using the pots gives you more of a "dance club" effect while the random option makes it look a little more like lightning.

Because each of the four RGB groups is independent, you can change the code for each one to get a different effect. Altering the values for "redStepX", "greenStepX", and "blueStepX" at the beginning of the sketch will increase or decrease the number of steps each color will take between full on and full off. You could also change the four "setColor" functions to make each groups behave differently. It's totally up to you.

Lastly, because everything is driven by mosfets you can use any RGB LED's you like. There's really cool high powered RGB LED spotlights out there (10W, 20W, up to 100W!) that would be pretty awesome for light shows outside your house. You can find much, much longer RGB strips that could cover a lot more area. The mosfets I used are rated for 30A and a max of 60V so you could drive some seriously big loads. I would suggest adding heatsinks to them if you're pushing more than 10A as they will get hot.

Ultimately, this instructable is intended to give you a place to start if you want to build something custom, or give you a perfectly good setup if you want to just build it and go without changing anything.