Wait a minute, is that a Members Only Jacket? |
To go along with our costumes, we wanted some sort of lighted helmet that would have a robot-like appearance similar to the Daft Punk guys, but still be able to see out of them. I decided on a 90-LED "circuit" board out of 1/32 inch (flexible) plexiglass, powered by an Arduino microcontroller, mounted just behind the visor of the helmet. I had 5 weeknights to build two of them. Here's how I did it.
We found a couple of cheap albeit decent looking motorcycle helmets on Ebay for about $30 each.
Pretty sure these $30 helmets are not D.O.T. approved. |
I wanted to take advantage of as much of the space behind the visor as possible. I made a quick paper template of the visor's viewable surface area, and drew up grid patterns in a few different configurations before settling on this -
Why yes, you DO need a drafting scale to make 1/2 inch grid lines. Asshole. |
This pattern would allow for 90 LEDs spaced on a 1/2 inch by 1/2 inch grid, the top 4 rows being 18 columns wide, the 5th row having 12 wide, and a sixth row with 6 LEDs. This way, when fitted to the curvature of the visor, the bulk of the lighting was in the front of the viewing area, yet with plenty of lights wrapping around the sides.
Using the template, I traced and cut out a few pieces of thin plexiglass. I was surprised to learn that tin snips would cut thin plexiglass, as long as I was taking short snips and taking off less than 3/8 inch or so at a time. I taped the template and pieces of plexiglass together (including a third sheet as a spare) and began drilling holes, using a piece of 1x6 as backing.
Psshh...pine. The Mark Wahlberg of building materials. Might as well be using dirt. |
To keep things in a straight line, I started by drilling 1/16 inch holes, followed by 1/8 and then the final size - 13/64. Got a few small cracks, but for hand drilling, it turned out pretty well.
Cracks? More like character. |
Next, I set each LED with a dab of hot glue, keeping all the leads in line. I looked for the brightest LEDs I could find for the price. These are Kingbright 400mcd diffused reds - 1.85v @ 20mA. Picked up 200 for 5 1/2 cents each at Mouser.com. The datasheet is here.
Jefe: Oh yes, you have a plethora. El Guapo: Jefe, what is a plethora? |
For the first helmet, I glued the LEDs in place after bending the plexiglass to fit the contour of the visor. I figured if I glued them in first and then bent the plexi, it would put undue stress on the holes/glue, which may cause it to crack or break. This didn't appear to be necessary. With the LEDs mounted, the plexi was still quite flexible and I didn't have any problems. To hold the plexi in its curved shape until I could fit it into the helmet, I simply used a piece of 16awg solid conductor wire, bent around the sides as shown -
Normally, I'm a three-wire kinda guy. |
Starting to come together: The first plexiglass board, with the LEDs glued in -
Awwwwwh Yeeeaaahhh |
Next, I bent each LED's lead at a 90 degree angle and soldered them to the next LED in the column. Thus, each column would light together. Unfortunately this would only allow for a limited number of lighting effects - a matrix configuration would have been optimal. More on this later. Difficult to see, but the picture below shows the columns soldered together. Still plenty of room to see out!
But you, sir, cannot see in. |
On to the fun stuff. I needed something to control 90 LEDs (really only 18 since they're connected by column). Since I planned on embedding everything in the helmet, it was going to have to be small. I've been playing around with the Arduino boards for a while now, and am amazed at their capability. If you're not familiar, they're easy to use and there's a ton of support available. Check out http://www.arduino.cc/ At about 2 inches square and $20 from Sparkfun electronics, the Arduino Pro would do nicely:
I did not steal this picture. I did not steal this picture. I did not steal this picture. |
The Arduino Pro has an available 14 digital input / outputs and 6 analog inputs, of which [the analog inputs] can be software configured to also be used as digital outputs. Since I have 18 columns of lights to control, I used digital pins 0-13 and analog pins 0-3, leaving analog pins 4 and 5 as inputs, which I will also use. More on this later.
The Arduino is capable of sinking or sourcing up to 40mA at each pin. Each LED, however, uses (up to) 20mA, which means we're going to need transistors to switch the loads. Nothing special here, I just used some cheap 2N2222's with a 1k ohm base resistor. Since I didn't have the time nor the space inside the helmet to build a circuit board for all 18 transistors and their respective support components, I decided to mount them in the plexiglass at the tops of each column as shown:
Transistors: the things that let you download porn and listen to mp3's at the same time! |
Since each LED is rated at 20mA, the total current consumption for each column would be between 80 and 120mA. (The actual current consumption was later determined to be considerably less, but we'll consider that a different topic..) Since we're using a 6 volt source to power everything, and the LEDs require 1.85 volts, we'll need a voltage dropping / current limiting resistor at each column. You can see these mounted at the bottom of each column in the picture above. Since the LEDs are wired in parallel, the resistor will have to drop 4.15 volts. Using Ohms law: (6v - 1.85v) / 0.1A = 41.5 ohms, (the 0.1A is just the average column current) so a 39 ohm resistor would do fine. Using Watt's law: 4.15 volts x 0.1 amps = 0.415 watts, so I used 1/2 watt resistors. Here's the schematic for each column -
Yes, 18x of these. Ahh, the magical age of...er, number 18. |
After connecting and soldering up all the components on the plexiglass, I used an old 20 conductor parallel printer cable and a 2 conductor 18 awg power cord to connect the LED board to the Arduino and battery pack, respectively. I mounted the LED board inside the helmet about 1/4 inch behind the visor and the Arduino board just below the visor, as shown below -
The teardrop-lookin thing is not the helmet telling you it's unhappy. Helmets love Daft Punk. |
The data cable sort-of snakes it's way around the side of the helmet and over to one side of the LED board. This allows for the visor to be opened if needed, with no wires showing. The dials on the right are just potentiometers - one is connected to Analog Input 5 and is used to select between the different light effects. The second is used for sensitivity control, connected to a separate circuit board shown below, for the sound-to-light effect.
Cute little guy. |
This is an old Velleman Sound-to-light kit, re-purposed to provide more of a sound-to-voltage signal for the Arduino. It originally had 4 on-board LEDs and an on-board microphone and sensitivity control. For about $6, it worked extremely well. I removed the LEDs and soldered a 10k resistor in their place. I also removed and re-wired the microphone and sensitivity control, as shown above, in order to remotely mount them. When connected to the 6 volt power source, it provided a nice 0 to 5 volt signal based on the sound level at the microphone, which is exactly the range of the Arduino's analog to digital converter. This was then connected to the Arduino's analog input 4 through a 1k resistor, and tucked inside the helmet next to the Arduino, as shown here -
Well...kinda. |
Toward the left of the photo you can also see where I mounted the microphone.
Finally time to program the Arduino. Given the fact that I only had vertical columns of lights to work with, I couldn't do anything really cool like display scrolling words across the visor, so I was limited to the following sequences. Had I connected the LEDs in a matrix configuration, I would have a few more options. Unfortunately, a matrix configuration would require 24 outputs to my available 18, additional components, and considerably more programming. All of which I didn't have time for. So here's what I could do with vertical columns -
- Left to Right flashing
- Left to Right "negative" flashing
- Middle to Sides flashing
- Sides to Middle flashing
- All flashing at a high rate
- All On steady
- Random lighting
- Sound-to-light
The program is shown at the end of the page.
That's about it! They're a far cry from the original Daft Punk helmets, but they worked well for our little costume party. I read somewhere that the company that made the original Daft Punk helmets will make you one (the multi-colored one) for $64,000.00. I made both of these for about $130.00, including the cost of the helmets. Here's a few videos showing their operation and pics of us in costume -
The first video is just a demo of the first 6 sequences -
Next video shows the random lighting effect - randomly lights between 3 and 9 columns of light each for a random time between 50ms and 1 sec -
And finally, the sound-to-light part of the program -
With the visors open:
Number 1 at something, anyway. |
On stage:
Security detail. Long story short: we were drinking and this was our only ticket to getting up on stage. Long story even shorter: We were drinking. |
The code. (Thanks again to JR for all his help here! If you're familiar with C++, you can probably tell which parts I wrote and which parts he wrote...)
int soundpin = 4; // analog sound input on pin 4
int selectpin = 5; // analog input on analog pin 5
int pinArray[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17};
int count = 0; // for left to right sequences
int timer = 15; // for left to right sequences
int timer2 = 50; // for middle - out sequences
long prevMilliseconds = 0; // for random light sequence
long currInterval = 0; // for random light sequence
int value = 0; // the value of the potentiometer position
void setup()
{
pinMode(soundpin, INPUT);
pinMode(selectpin, INPUT);
for (count=0;count<16;count++)
{
pinMode(pinArray[count], OUTPUT);
}
}
void sequence1() // left to right sequence
{
for (count=0;count<16;count++)
{
digitalWrite(pinArray[count], HIGH);
delay(timer);
digitalWrite(pinArray[count + 1], HIGH);
delay(timer);
digitalWrite(pinArray[count + 2], HIGH);
delay(timer);
digitalWrite(pinArray[count + 3], HIGH);
delay(timer);
digitalWrite(pinArray[count + 2], LOW);
delay(timer);
digitalWrite(pinArray[count + 1], LOW);
delay(timer);
digitalWrite(pinArray[count], LOW);
delay(timer*2);
}
}
void sequence2() // left to right reverse lighting sequence
{
TurnAllPinsOn();
for (count=0;count<16;count++)
{
digitalWrite(pinArray[count], LOW);
delay(timer);
digitalWrite(pinArray[count + 1], LOW);
delay(timer);
digitalWrite(pinArray[count + 2], LOW);
delay(timer);
digitalWrite(pinArray[count + 3], LOW);
delay(timer);
digitalWrite(pinArray[count + 2], HIGH);
delay(timer);
digitalWrite(pinArray[count + 1], HIGH);
delay(timer);
digitalWrite(pinArray[count], HIGH);
delay(timer*2);
}
}
void sequence3() //sides to middle sequence
{
digitalWrite(0, HIGH);
digitalWrite(17, HIGH);
delay(timer2);
digitalWrite(1, HIGH);
digitalWrite(16, HIGH);
delay(timer2);
digitalWrite(2, HIGH);
digitalWrite(15, HIGH);
delay(timer2);
digitalWrite(3, HIGH);
digitalWrite(14, HIGH);
digitalWrite(0, LOW);
digitalWrite(17, LOW);
delay(timer2);
digitalWrite(4, HIGH);
digitalWrite(13, HIGH);
digitalWrite(1, LOW);
digitalWrite(16, LOW);
delay(timer2);
digitalWrite(5, HIGH);
digitalWrite(12, HIGH);
digitalWrite(2, LOW);
digitalWrite(15, LOW);
delay(timer2);
digitalWrite(6, HIGH);
digitalWrite(11, HIGH);
digitalWrite(3, LOW);
digitalWrite(14, LOW);
delay(timer2);
digitalWrite(7, HIGH);
digitalWrite(10, HIGH);
digitalWrite(4, LOW);
digitalWrite(13, LOW);
delay(timer2);
digitalWrite(8, HIGH);
digitalWrite(9, HIGH);
digitalWrite(5, LOW);
digitalWrite(12, LOW);
delay(timer2);
digitalWrite(6, LOW);
digitalWrite(11, LOW);
delay(timer2);
digitalWrite(7, LOW);
digitalWrite(10, LOW);
delay(timer2);
digitalWrite(8, LOW);
digitalWrite(9, LOW);
}
void sequence4() // middle to sides sequence
{
digitalWrite(8, HIGH);
digitalWrite(9, HIGH);
delay(timer2);
digitalWrite(7, HIGH);
digitalWrite(10, HIGH);
delay(timer2);
digitalWrite(6, HIGH);
digitalWrite(11, HIGH);
delay(timer2);
digitalWrite(5, HIGH);
digitalWrite(12, HIGH);
digitalWrite(8, LOW);
digitalWrite(9, LOW);
delay(timer2);
digitalWrite(4, HIGH);
digitalWrite(13, HIGH);
digitalWrite(7, LOW);
digitalWrite(10, LOW);
delay(timer2);
digitalWrite(3, HIGH);
digitalWrite(14, HIGH);
digitalWrite(6, LOW);
digitalWrite(11, LOW);
delay(timer2);
digitalWrite(2, HIGH);
digitalWrite(15, HIGH);
digitalWrite(5, LOW);
digitalWrite(12, LOW);
delay(timer2);
digitalWrite(1, HIGH);
digitalWrite(16, HIGH);
digitalWrite(4, LOW);
digitalWrite(13, LOW);
delay(timer2);
digitalWrite(0, HIGH);
digitalWrite(17, HIGH);
digitalWrite(3, LOW);
digitalWrite(14, LOW);
delay(timer2);
digitalWrite(2, LOW);
digitalWrite(15, LOW);
delay(timer2);
digitalWrite(1, LOW);
digitalWrite(16, LOW);
delay(timer2);
digitalWrite(0, LOW);
digitalWrite(17, LOW);
}
void sequence5() // high rate flashing
{
TurnAllPinsOn();
delay(50);
TurnAllPinsOff();
delay(50);
}
void sequence6() // all lights on
{
TurnAllPinsOn();
}
void sequence7() // random flashing
{
int minNumberOfLights = 3;
int maxNumberOfLights = 9;
int minDigitalOutputPin = 0;
int maxDigitalOutputPin = 17;
int randomDigitalOutput = 1;
int numOfLightsToUse = 0;
if(RandomNonBlockingDelay())
{
TurnAllPinsOff();
numOfLightsToUse = int(random(minNumberOfLights, maxNumberOfLights + 1));
for(int i = 1; i <= numOfLightsToUse; i++)
{
randomDigitalOutput = int(random(minDigitalOutputPin, maxDigitalOutputPin + 1));
digitalWrite(randomDigitalOutput, HIGH);
}
}
}
void sequence8() // sound to light
{
while (analogRead(soundpin) > 500)
{
TurnAllPinsOn();
}
TurnAllPinsOff();
}
void TurnAllPinsOn()
{
int minPin = 0;
int maxPin = 17;
for(int i = minPin; i <= maxPin; i++)
{
digitalWrite(i, HIGH);
}
}
void TurnAllPinsOff()
{
int minPin = 0;
int maxPin = 17;
for(int i = minPin; i <= maxPin; i++)
{
digitalWrite(i, LOW);
}
}
bool RandomNonBlockingDelay()
{
int minTimeToDelay = 50;
int maxTimeToDelay = 1000;
if(currInterval <= 0 || prevMilliseconds <= 0)
{
//Generate a new interval
currInterval = random(minTimeToDelay, maxTimeToDelay);
prevMilliseconds = millis();
return true;
}
else
{
long currMilliseconds = millis();
if((currMilliseconds - prevMilliseconds) >= currInterval)
{
currInterval = 0;
prevMilliseconds = 0;
return true;
}
else
return false;
}
}
void loop()
{
value = analogRead(selectpin);
if ( value <= 128 )
{
sequence1();
}
else if(value >= 129 && value <= 256)
{
sequence2();
}
else if(value >= 257 && value <= 384)
{
sequence3();
}
else if(value >= 385 && value <= 512)
{
sequence4();
}
else if(value >= 513 && value <= 640)
{
sequence5();
}
else if(value >= 641 && value <= 768)
{
sequence6();
}
else if(value >= 769 && value <= 896)
{
sequence7();
}
else //For any value >= 897
{
sequence8();
}
}
Ha ha, what a laff! Great idea and brilliantly executed!
ReplyDeleteKudos to you!
These are great Motorcycle Helmets.
ReplyDeleteWow great project!I really appreciate your creative work keep it up!! pcb suppliers
ReplyDelete