Happy Hack-o-ween: Electronics and a microcontroller spice up the haunt
Ah, Halloween, when a young woman’s fancy turns to love. And zombies.
I had two personal requirements for the costume I would build this year:
- It shall be spooky.
- It shall blink.
I’ll tell you about the final result, the electronics and the software that went into it, plus the techniques I used to achieve wearable electronics. I’ll introduce you to the Arduino, an open-source microcontroller prototyping platform, which is an exhilarating tool/toy for making your software skills manifest in the physical world.
My husband and I have been teaching ourselves electronics. A few months ago, Dad taught me to solder. I recently read Syuzi Pakhchyan’s excellent primer on wearable electronics and smart materials, Fashioning Technology. And I’ve been making things with my Arduino. All these ideas were swirling and combining in my head to inspire this year’s Halloween project. Er, costume. Same difference.
What was I? I was a nightmare… the thing under your bed… the reason for your well developed sense of paranoia…
I sported a crop of writhing eyeballs erupting from my head. Each eyeball has an LED inside it, and they blink randomly and independently, until I trigger a hidden switch, which causes the blinky ones to go dark and two red eyes to pulse menacingly. In the Flickr photoset, you can see the construction process.
The Arduino Sketch
The term “Arduino” is overloaded to mean:
- a particular chip and circuit board which you can buy or build;
- the IDE in which you write programs for the chip;
- the language, which is C-flavored;
- fun.
Arduino programs are called sketches. Every sketch must contain two functions: setup (runs once) and loop (runs continuously). Here’s my sketch, with extra explanatory comments, that blinks the six regular eyeballs and responds to the switch by pulsing the red eyeballs.
1 #define SWITCH 8
2 int ledPins[] = {2, 3, 4, 5, 6, 7};
3 const int ledPinsCount = 6;
4 int redEyePins[] = {10, 11};
5 const int redEyePinsCount = 2;
6 long durations[ledPinsCount];
7 int ledStates[ledPinsCount];
8 long previousTimes[ledPinsCount];
9 int i;
10
11 void setup()
12 {
13 pinMode(SWITCH, INPUT); //Specify the switch pin as an input.
14
15 for (i = 0; i < redEyePinsCount; i++)
16 {
17 pinMode(redEyePins[i], OUTPUT); //Specify each red-eye LED pin as an output.
18 }
19
20 for(i = 0; i < ledPinsCount; i++)
21 {
22 pinMode(ledPins[i], OUTPUT); //Specify each regular LED pin as an output.
23 ledStates[i] = random(1); //Randomly set the LEDs to on or off (1 or 0).
24 durations[i] = GetRandomDuration(); //Define a random duration for each LED to stay in that state.
25 previousTimes[i] = 0; //At time of setup, the "last time we changed" is at 0 milliseconds, the start of time.
26 }
27 }
28
29 void loop()
30 {
31 if (digitalRead(SWITCH) == HIGH)
32 {
33 TurnOffLeds();
34 PulseRedEyes();
35 }
36 else
37 {
38 for(i = 0; i < redEyePinsCount; i++)
39 {
40 digitalWrite(redEyePins[i], LOW); //Turn the red eyes all the way off.
41 }
42
43 for(i = 0; i < ledPinsCount; i++) //For each LED:
44 {
45 if (millis() - previousTimes[i] > durations[i])
46 {
47 ChangeLed(i); //If this one's duration is up, then flip it.
48 }
49 }
50 }
51 }
52
53 void TurnOffLeds()
54 {
55 for(i = 0; i < ledPinsCount; i++)
56 {
57 digitalWrite(ledPins[i], LOW);
58 }
59 }
60
61 void PulseRedEyes()
62 {
63 //Fade on, then off.
64 int j;
65 for(j = 0; j < 255; j+=5)
66 {
67 for(i = 0; i < redEyePinsCount; i++)
68 {
69 analogWrite(redEyePins[i], j);
70 delay(10);
71 }
72 }
73 for(j = 255; j > 0; j-=5)
74 {
75 for(i = 0; i < redEyePinsCount; i++)
76 {
77 analogWrite(redEyePins[i], j);
78 delay(10);
79 }
80 }
81 }
82
83 void ChangeLed(int ledPin)
84 {
85 previousTimes[ledPin] = millis(); //Update the "last time we changed" to now.
86 durations[ledPin] = GetRandomDuration(); //Give it a new random duration.
87 ledStates[ledPin] = 1 - ledStates[ledPin]; //Flip the state between on and off.
88 digitalWrite(ledPins[ledPin], ledStates[ledPin]); //Set the LED to that state.
89 }
90
91 long GetRandomDuration()
92 {
93 //Random number between 1 and 10, then multiplied by 400 to give it a detectable duration.
94 return random(1, 10) * 400;
95 }
I like the way the eyes blink independently. If they all flashed in unison, they would look like Christmas lights, and you would notice that two were “special” because they weren’t flashing. Instead, the duration that any given eyeball is lit or dark constantly changes.
The blinking is managed by a collection of arrays. One array represents each of my LED pins, so that I can address them in a for loop. The three other arrays hold: the state (on/off) of each LED; the duration each LED should stay in that state; the reading from the millisecond counter when the LED last flipped its state. Each time the loop function executes, if the switch is not connected, then I look at each LED; if the difference between the current time and the time when it previously changed is greater than its duration, flip its state (from off to on, or from on to off), randomly assign it a new duration, and record “now” as the new “previously changed” time. If the switch is connected, then I make the red eyes fade on and fade off.
Fading with PWM
PWM (Pulse-Width Modulation) is a technique for making a digital component (one that turns on or off) simulate analog behavior (be a little bit on, and then a little bit more on). If you turn an LED off and on really quickly, you won’t perceive the flickering, but it will look half as bright, because it is actually off for half the time. If you let it spend a little more time off than on, it will appear even dimmer. So by varying the width of the pulses, you can control how bright the LED looks.
The Arduino comes with built-in PWM functions; some pins are already set up to be PWM pins. If you plug an LED into one of the PWM pins, then you can write to it as if it were an analog component. That’s why, in my sketch above, I set the brightness of the red eyes using analogWrite(), instead of digitalWrite(). My for loop increments the counter j from 0 to 255, and sets the brightness of both red eyes to the value of j. The Arduino takes care of (imperceptibly) flickering the LEDs with the right ratio of on-time and off-time to achieve a j amount of brightness. So the eyes get gradually brighter, then gradually dimmer. (Then control returns to the main loop function, but if my switch is still connected, the red eyes will throb again.)
Snaps: Wearable Plugs
A metal sewable snap is like a plug for your clothing, an interface between the world of textiles and the world of wires. This is handy when you need the electronics to be separate while you are getting into the clothing, or if you want to wash the clothing. My Arduino hung out at the base of my neck, to be near the LEDs on my head but hidden underneath my wig, but my control switch was near my hip. I could have run a wire down to the switch, but conductive thread was more subtle and more comfortable.
To complete the connection, I soldered a short wire to one side of the snap. That wire plugged into a pin on the Arduino. The conductive thread ran from the switch at my hip up to the back of my dress near the Arduino, and I sewed that conductive thread to the other half of the snap. When the two halves are snapped together, the wire and the thread make a complete connection, as if they were one continuous wire.
I had two threads (going out to the switch and back), so I encased them each in a bias tape tube, to prevent them from touching each other and shorting out.
I’ve been saying “switch,” but actually, I simplified at the 11th hour. I tied each thread around a safety pin, and stuck the pins to my dress. When the safety pins touched each other, they completed the circuit, which the Arduino sketch interpreted as triggering the switch—cue red-eye glare.
What’s Next
Soldering and sewing are both liberating skills to possess—they free up your creativity to make wilder and more integrated stuff. If you are currently proficient with only one, ask around and see if you can find a buddy who’s good at the other, and teach each other.
The Arduino comes with a great community of hackers and makers, lots of people to learn from and collaborate with. Definitely check it out. There is lots of fun to be had, and blinking LEDs is the barest beginning of what it can do.