Last Modified: | September 23, 2014, at 05:59 PM |
By: | |
Author: | Garth Fielding II |
This sketch is a program to simulate the Will o' the Wisps that you see in the movie "Brave" by Disney. The LED's will slowly fade on one by one until all are on. At that point, they pulse giving the appearance of a breathing pulsing wisp. After a few seconds of them all being on the first one will start to flicker and fade away. The next one starts to flicker as the first is fading and so on down the line until they are all off. After a few seconds the cycle will begin again.
You can find some 22/4 security wire at many hardware stores (solid core is preferred). It's 22awg wire with 4 wires. Strip just a little bit off the end of each of the 4 wires on both ends. Attach 2 LED's to the 4 wires (pick a color - one end you'll plug into ground and the other to where you have a current limiting resistor coming from a pin). You can solder the wires if you want or just use electrician's tape to affix the LED's to the wires like I did. Either way, wrap some electrician's tape between and around the exposed wires and LED leads to prevent them from touching each other.
Take three 1x2 eight foot pieces of lumber. Cut 16 inches off the middle one so you have a total of 8'x8'x6'8"=22 feet 8 inches lying end to end. Drill 10 holes 30" (2 1/2 feet) apart from each other and place wooden dowels in them so they come up about waist high. Optionally glue some side braces on to help with stability. It looks best if you paint all of the wood black at this point. Run the security wire from the Arduino along the sides of the 1x2 and up the wooden dowel. Wrap electrician's tape around the wire just before the top of the wooden dowel. The LED should now be sitting flush with the wooden dowel and about eye level with children.
LEDs with current limiting resistors attached from each of the 10 pins (2-11) to ground. The perfect wisp in my opinion is a microtivity IL142 5mm Diffused Blue LED with a 3.0-3.1V forward voltage and a current of 20mA using the 100 ohm resistors that came with the LED's.
R = (VS - VL) / I ResistorNeeded = (SourceVoltage - LEDForwardVoltage) / Current
Example of LED setup (where the LED has a Forward Voltage of 3.0v). R=(5v-3.0v)/.02=100= 100 ohm - `
Note: Forward Voltages are different for every LED. Your package should tell you what they are. For example: Clear Red and Clear Yellow 1.88-2.0V, Clear Green: 2.89-3.1V, Clear Blue, Clear White and Clear Pink: 3.0-3.2V. If you are unsure of what voltage your LED is rated at, connect it up to a circuit with 5V power, a 10k-ohm resistor and use a voltmeter to measure the voltage across the 2 wires of the LED. That will tell you the approximate voltage. Once you have that setting, do the math above to find a 20ma current and then after building that check the LED with the voltmeter again. The settings for the forward voltage may change slightly if at all.
You can easily build this entire circuit on your breadboard to get it working the way you want then come Halloween just pull the LED's off the board and plug in the 22/4 security wire's you've attached to the LED's and voila, instant wisps.
The code below is setup so that it currently outputs to only 10 pins.
MAKE SURE YOU DO NOT EXCEED 20mA OF CURRENT ON ANY ONE LED (See description above for calculating your current)
Ever wondered why every example of lighting up LED's only lights up 10 pins total? While each pin can send 40mA of power through it, the total power sent through the system at one time cannot exceed 150mA. That means that if you were running LED's on more than 7 pins at full brightness (20mA) you could hit that limit. Some people say you have 200mA and in that case you'd be able to have 10 pins running LED's at full brightness simultaneously (like you see on other examples of PWM with LED's). This program will run at times near the 200mA limit if you use 20mA for each LED. If you are worried, I suggest you decrease the amount of current running through your system by using a larger resistor.
/* Will o' the Wisp This sketch is a program to simulate the Will o' the Wisps that you see in the movie "Brave" by Disney. The LED's will slowly fade on one by one until all are on. At that point, they pulse giving the appearance of a breathing pulsing wisp. After a few seconds of them all being on the first one will start to flicker and fade away. The next one starts to flicker as the first is fading and so on down the line until they are all off. After a few seconds the cycle will begin again. created 2014 by Garth Fielding II The circuit: LEDs with current limiting resistors attached from each of the 10 pins (2-11) to ground. The perfect wisp in my opinion is a microtivity IL142 5mm Diffused Blue LED with a 3.0-3.1V forward voltage and a current of 20mA using the 100 ohm resistors that came with the LED's. R = (VS - VL) / I ResistorNeeded = (SourceVoltage - LEDForwardVoltage) / Current Example of LED setup (where the LED has a Forward Voltage of 3.0v). R=(5v-3.0v)/.02=100= 100 ohm 100 ohm LED (3.0v) Ground PIN ---`/\/\/\/`------|>|--------___ - ` Note: Forward Voltages are different for every LED. Your package should tell you what they are. For example: Clear Red and Clear Yellow 1.88-2.0V, Clear Green: 2.89-3.1V, Clear Blue, Clear White and Clear Pink: 3.0-3.2V. If you are unsure of what voltage your LED is rated at, connect it up to a circuit with 5V power, a 10k-ohm resistor and use a voltmeter to measure the voltage across the 2 wires of the LED. That will tell you the approximate voltage. Once you have that setting, do the math above to find a 20ma current and then after building that check the LED with the voltmeter again. The settings for the forward voltage may change slightly if at all. You can easily build this entire circuit on your breadboard to get it working the way you want then come Halloween just pull the LED's off the board and plug in the 22/4 security wire's you've attached to the LED's and voila, instant wisps. Setup in your yard You can find some 22/4 security wire at many hardware stores (solid core is preferred). It's 22awg wire with 4 wires. Strip just a little bit off the end of each of the 4 wires on both ends. Attach 2 LED's to the 4 wires (pick a color - one end you'll plug into ground and the other to where you have a current limiting resistor coming from a pin). You can solder the wires if you want or just use electrician's tape to affix the LED's to the wires like I did. Either way, wrap some electrician's tape between and around the exposed wires and LED leads to prevent them from touching each other. Take three 1x2 eight foot pieces of lumber. Cut 16 inches off the middle one so you have a total of 8'x8'x6'8"=22 feet 8 inches lying end to end. Drill 10 holes 30" (2 1/2 feet) apart from each other and place wooden dowels in them so they come up about waist high. Optionally glue some side braces on to help with stability. It looks best if you paint all of the wood black at this point. Run the security wire from the Arduino along the sides of the 1x2 and up the wooden dowel. Wrap electrician's tape around the wire just before the top of the wooden dowel. The LED should now be sitting flush with the wooden dowel and about eye level with children. In the picture below, the "X" is an "LED", the "|" is a "wooden dowel", and the "-" is the "1x2". X X X X X X X X X X | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | --------------------------------------------------------------------------------------------------------- This is currently timed so someone walking at a fairly normal pace (very subjective) would keep pace with the LED's going off at 2 1/2 feet apart. */ /* ---DO NOT BLOW UP YOUR ARDUINO BY SENDING TOO MUCH POWER THROUGH IT--- The code below is setup so that it currently outputs to only 10 pins. MAKE SURE YOU DO NOT EXCEED 20mA OF CURRENT ON ANY ONE LED (See description above for calculating your current) Ever wondered why every example of lighting up LED's only lights up 10 pins total? While each pin can send 40mA of power through it, the total power sent through the system at one time cannot exceed 150mA. That means that if you were running LED's on more than 7 pins at full brightness (20mA) you could hit that limit. Some people say you have 200mA and in that case you'd be able to have 10 pins running LED's at full brightness simultaneously (like you see on other examples of PWM with LED's). This program will run at times near the 200mA limit if you use 20mA for each LED. If you are worried, I suggest you decrease the amount of current running through your system by using a larger resistor. ---DO NOT BLOW UP YOUR ARDUINO BY SENDING TOO MUCH POWER THROUGH IT--- */ #define PULSING_INTERVAL 1000 #define MAX_PULSING_BRIGHTNESS 700 #define MIN_PULSING_BRIGHTNESS 300 #define DIGITAL_FADE_INTERVAL 2000 //5000 #define DIGITAL_FADEDOWN_WAIT 10 //30 #define DIGITAL_FADEUP_WAIT 600 #define FLICKERING_DURATION 900000 //Used to indicate the 4 states we can be in. typedef enum {PULSING, FLICKERING, FADEUP, FADEDOWN, OFF} WispState; typedef struct WispStruct { byte pin; //PWM output pins are 3,5,6,9,10,and 11 WispState state; //used to determine what state the LED is in unsigned int pulsePeriod; unsigned long lastPulseTime; //used to calculate how long the led will be on unsigned long pulsingChangeTime; //used to calculate how long the led will be on unsigned long TEMPtimeToFade; //used to calculate how long the led will be on boolean toggle; //Used for toggling the LED on/off with PWM //fading unsigned long fadeWait; //used to increase the time it takes to fade so it lasts just a little longer. } Wisp; int wispPins[] = { 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; const int MAXPINS = sizeof(wispPins)/sizeof(*wispPins); Wisp wisps[MAXPINS]; boolean wispPinsOff(){ for (int i=0; i<MAXPINS; i++) { if (wisps[i].state != OFF) return false; } return true; } void setup(){ for (int i=0; i<MAXPINS; i++) { wisps[i].pin = wispPins[i]; pinMode(wisps[i].pin, OUTPUT); } wisps[0].state = FADEUP; } void pwm(unsigned long currentTime, int interval, int i) { if (currentTime - wisps[i].lastPulseTime > interval - wisps[i].pulsePeriod && wisps[i].toggle == true) { wisps[i].toggle = false; wisps[i].lastPulseTime = currentTime; } else if (currentTime - wisps[i].lastPulseTime > wisps[i].pulsePeriod && wisps[i].toggle == false) { wisps[i].toggle = true; wisps[i].lastPulseTime = currentTime; } if (wisps[i].toggle == true) digitalWrite(wisps[i].pin, LOW); else digitalWrite(wisps[i].pin, HIGH); } void flicker(unsigned long currentTime, int i) { if (currentTime > wisps[i].pulsingChangeTime) { if (wisps[i].toggle == true) wisps[i].pulsingChangeTime = currentTime + (unsigned long)random(30)*1000; else wisps[i].pulsingChangeTime = currentTime + (unsigned long)random(100)*1000; wisps[i].toggle = !wisps[i].toggle; } if (wisps[i].toggle == true) digitalWrite(wisps[i].pin, LOW); else digitalWrite(wisps[i].pin, HIGH); } void pulsing(unsigned long currentTime, int i) { pwm(currentTime, PULSING_INTERVAL, i); if (currentTime - wisps[i].pulsingChangeTime > (unsigned long)50*1000) { //50ms wisps[i].pulsePeriod = random(MIN_PULSING_BRIGHTNESS, MAX_PULSING_BRIGHTNESS+1); wisps[i].pulsingChangeTime = currentTime; } } void flickering(unsigned long currentTime, int i) { flicker(currentTime, i); if (micros() - wisps[i].TEMPtimeToFade > FLICKERING_DURATION) { wisps[i].state = FADEDOWN; wisps[i].pulsePeriod = DIGITAL_FADE_INTERVAL; wisps[i].fadeWait = micros(); wisps[i].TEMPtimeToFade = micros(); if (i < MAXPINS - 1) { wisps[i+1].TEMPtimeToFade = currentTime; wisps[i+1].state = FLICKERING; } } } void fadeDown(unsigned long currentTime, int i) { //When we are processing 10 wisps, there is additional overhead to process the flicker, pulse, fade. //This results in the wisps having a slow fade at the beginning but then when we get to the last //couple of wisps it's almost an instant off (no fade at all) because the other LED's are off and //no processing is taking place (which slows down this processing). That's why we add this additional fade here. unsigned long waitDueToLessProcessingTime = i*15ul; pwm(currentTime, DIGITAL_FADE_INTERVAL + waitDueToLessProcessingTime, i); if (wisps[i].pulsePeriod == 1) { wisps[i].state=OFF; digitalWrite(wisps[i].pin, LOW); } else if (currentTime - wisps[i].fadeWait > DIGITAL_FADEDOWN_WAIT + waitDueToLessProcessingTime) { //We have a short wait before incrementing the value to make the fade take just a little longer. wisps[i].pulsePeriod--; wisps[i].fadeWait = micros(); } } void fadeUp(unsigned long currentTime, int i) { pwm(currentTime, DIGITAL_FADE_INTERVAL, i); if (wisps[i].pulsePeriod >= DIGITAL_FADE_INTERVAL/4) { wisps[i].pulsePeriod = 0; wisps[i].state=PULSING; if (i < MAXPINS - 1) { wisps[i+1].pulsePeriod = 0; wisps[i+1].state = FADEUP; wisps[i+1].TEMPtimeToFade = millis(); } } else if (currentTime - wisps[i].fadeWait > DIGITAL_FADEUP_WAIT) { //We have a short wait before incrementing the value to make the fade take just a little longer. wisps[i].pulsePeriod++; wisps[i].fadeWait = micros(); } } void off(unsigned long currentTime, int i) { digitalWrite(i, LOW); } unsigned long timeToSwitch; void loop(){ unsigned long currentTime = micros(); if (millis()-timeToSwitch > 15000) { if (wispPinsOff()) { wisps[0].state = FADEUP; } else { wisps[0].TEMPtimeToFade = currentTime; wisps[0].state = FLICKERING; } timeToSwitch = millis(); } for (int i=0; i<MAXPINS; i++) { if (wisps[i].state == FADEUP) { fadeUp(currentTime, i); } else if (wisps[i].state == PULSING) { pulsing(currentTime, i); } else if (wisps[i].state == FLICKERING) { flickering(currentTime, i); } else if (wisps[i].state == FADEDOWN) { fadeDown(currentTime, i); } else { //OFF off(currentTime, i); } } }