Starry Sky Led Tie
A while ago i found a childs toy with fiberoptics at a dollar store, and started thinking about what i could do with it.
One of the crazy ideas i had, was making a tie with the effect of a starry sky.
I still had some arduino pro mini's, adafruit boards and batteries laying around that would probably fit this project.
So as soon as i found a nice wide tie in a pawnshop in my town and found a box which might fit the hardware, i decided to go for it and try and build it.
This instructable shows you how i made it.
It runs on an arduino pro mini, adafruit powerboost 500 charger, emmerich icr 18650nh-sp and 5 white LED's.
The code makes the LED's change brightness random. (The first 40 seconds of the video are 3x speed)
Schematics and Hardware
I'm using the following hardware:
- PCB with Ice white LEDs and 220 Ohm resistors.
- Arduino pro mini (i used a knockoff) https://store.arduino.cc/arduino-pro-mini
- Adafruit Powerboost 500 charger https://store.arduino.cc/arduino-pro-mini
- Emmerich Li-ion accu ICR-18650NH-SP https://store.arduino.cc/arduino-pro-mini
Making the PCB Hosting the LED's
I cut a strip off a PCB to hold the LED's and used the LED pins to solder it to the main PCB.
Connected all the cathodes (-) to GND, and used half of the pins to solder it stuck to the main PCB.
Connected all the anodes (+) to resistors, and with cables to the arduino.
LEDs each have to be connected to one of the following PWM ports: 3, 5, 6, 9, 10, 11
Silly me made lots of mistakes with this project and forgot to check the correct PWM ports, so i had to resolder a few later. Tested with High/Low so i only noticed this later.
I started with 7 LED's, but there were only 6 PWM ports and one of the LED's i resoldered died. I just kept the 5 working LED's and am not using the 6th.
Making the Box
I used a Bosch GRO (like a Dremel) and a drill to cut out the shape of the battery, the button, the micro-usb port, the headers from the Arduino and the optic fibers. (use a dust mask!)
Glued the battery to the case with 2 bands.
Used screws to mount the Adafruit board and the PCB.
Friction from opening and closing damaged some wires. I had to resolder them and use glue to prevent it from happening again.
Preparing the Tie
Removed the stitching from the bottom part of the tie to fit the rubber sheet.
To hide the hardware and still be able to access it if needed i decided to use a zipper.
I'm no good with a sewing machine, so my sweet mom put a zipper on the back of the tie.
After that was done, i glued the rubber sheet in the tie. I was afraid of using too much glue that would saturate the fabric and be visible from the front, so i tried to even it out and not use too much. Overall it looks good, but at a few places i noticed too much or too little glue, cause it came through the fabric or didn't stick the fabric very well. Fortunately this is only barely visible from close distance in bright light.
The box and tie are now done. Time to glue the fiberoptics!
Glueing the Fiberoptics
The toy had one big bundle fiber optic wires that easily broke apart. I tried gluing them one by one at first, but soon noticed it would be better to make small bundles and stick those to the LED at once. That would make it easier to keep it steady till the glue was dry. Messed up the first LED figuring this out.
Be sure to use a transparent glue! The one i used dried very slow and the fast drying glue i tried on the first LED turned white, making some fibers from the first LED less bright.
I glued small black rubber sheets to prevent light leaking on top and to separate the LED's.
One of the sheets prevented the case from closing so i added a rubber band to keep the cover shut.
Putting Fiberoptics Through the Tie
Starting on the bottom, i pinched holes with a needle and put the fibers through one by one. Each LED's fibers spread random across the tie.
I glued a black strip on the back that was supposed to go all the way up to the smaller part of the tie to keep the weight of the box, but after i put all the wires through and felt the tension of the wires i decided gluing everything to the tie was a better idea and cut the strip off.
Since the fiber optic wires from the toy were so short, it was hard fitting them all over the tie. I was limited in positioning the box and had a hard time making everything as flat as i wanted.
Glueing Fiberoptics to the Tie
I glued all the fiber optic wires to the rubber sheet to prevent the wires from getting pulled out of the rubber sheet and to make the tie flat.
To make sure i didn't glue the clamp to the tie when putting pressure on it i put some paper in between. It doesn't look that great but works well. And you don't see it when it is closed.
After the glue dried i cut off the wires on the front and cut off a bit off the rubber sheet just above the highest wire, cause the tie was a bit too long.
Photos with the white shirt are made before i cut that last bit of rubber off.
The Code
Below the code i wrote for the tie.
All LED's have a set " average " (not actually an average but a middle brightness).
As soon as it reaches that average, it will decide with a chance <1/4 to go high, or >3/4 to go to a lower brightness. It also randomly sets a new minimum brightness, maximum brightness, waiting time for minimum and maximum brightness and the speed it increases or decreases every round (1-255) from 5 preset values. Then it will do a cycle till it reaches the average again. Only 2 LED's can be in a high cycle at the same time.
Every state is represented by an integer value (1-7) determining if it's going avg-low, low-avg, waiting low, updating, etc.
For information about uploading code to the arduino, please have a look at www.arduino.cc
<p>/* Starry Sky Tie<br> * * This is a script to randomly fade 5 LEDs from an average to a lower * or higher brightness with random lower, higher and timing settings * to look like a starry sky when used with fiberoptics. * In this case these will be implemented in a tie. * * Up/down chance = 1/4 up, 3/4 down, with a maximum of 2 * going up to max at the same time. * * Average stays the same. * Minimum, maximum and timing options change randomly * from 5 options every time a LED reaches the average again. * * Created by Billy Jaspers, May 2019. *</p><p>/ Declare pins int LED01 = 3; int LED02 = 5; int LED03 = 6; int LED04 = 9; int LED05 = 11;</p><p>// Time variables unsigned long currentTime; unsigned long waitingTime[5]; unsigned long lastRound;</p><p>// LED Variables int brightMin [5] = { 10, 10, 10, 10, 10 }; // Minimum brightness int brightAvg [5] = { 200, 200, 200, 200, 200 }; // Average brightness int brightMax[5] = { 240, 240, 240, 240, 240 }; // Maximum brightness int timeWaitLow[5] = { 1000, 1000, 1000, 1000, 1000 }; // Waiting time int timeWaitAvg[5] = { 5000, 5000, 5000, 5000, 5000 }; // Waiting time int timeWaitMax[5] = { 4000, 3000, 3000, 3000, 3000 }; // Waiting time int increment[5] = { 2, 5, 4, 5, 2 }; // Increment in brightness int currentBright[5]= { 200, 230, 210, 210, 235 }; // Current brightness</p><p>// LED Variables Possibilities int brightMinPos[5] = { 5, 20, 40, 5, 20 }; // Minimum brightness possibilities int brightMaxPos[5] = { 240, 245, 230, 225, 245 }; // Maximum brightness possibilities int timeLowPos[5] = { 3000, 5000, 4000, 2000, 1000 }; // Waiting time on low brightness possibilities int timeHighPos[5] = { 3000, 1000, 500, 2000, 4000 }; // Waiting time on high brightness possibilities int timeAvgPos[5] = { 3000, 5000, 4000, 7000, 8000 }; // Waiting time on average brightness possibilities int incrementPos[5] = { 2, 4, 5, 3, 1 }; // increment in brightness possibilities</p><p>// Variables bool startup = true; // Do the start settings need to be started?</p><p>// Directional variables /* 0 = Waiting at Average 1 = going Avg to Low 2 = waiting Low 3 = going Low to Avg 4 = going Avg to Max 5 = waiting at Max 6 = going High to Avg 7 = Updating variables*/ int statusLED[5] = { 0, 0, 0, 0, 0 }; int amountHighLED = 0; int refreshRate = 50; bool statusWaiting[5] = { false, false, false, false, false}; // Is the Led waiting?</p><p>// Random variables long randomNumber; // Long to store random number long randomNumberTwo; // Long to store the second random number</p><p>// counters int i = 0; // Counter for main loop</p><p>void setup() { Serial.begin (115200); // Start serial randomSeed(analogRead(A0)); // Set randomseed </p><p>// Declare outputs pinMode (LED01, OUTPUT); pinMode (LED02, OUTPUT); pinMode (LED03, OUTPUT); pinMode (LED04, OUTPUT); pinMode (LED05, OUTPUT); }</p><p>// Write data to LEDs void writeToLED(){ analogWrite(LED01, currentBright[0]); analogWrite(LED02, currentBright[1]); analogWrite(LED03, currentBright[2]); analogWrite(LED04, currentBright[3]); analogWrite(LED05, currentBright[4]); }</p><p>// Main loop void loop() { if (startup){ // Startup settings lastRound = millis(); // Set lastRound for boot writeToLED(); // Write start data to LED startup = false; // Turn off startup } currentTime = millis(); // Set current time</p><p> if (currentTime - lastRound >= refreshRate ){ for (i=0;i<5;i++){ if (statusLED[i] == 7){ // -7- Updating Led randomNumber = random(5); brightMin[i] = brightMinPos[randomNumber]; // Set random value for minimum brightness randomNumber = random(5); brightMax[i] = brightMaxPos[randomNumber]; // Set random value for maximum brightness randomNumber = random(5); timeWaitLow[i] = timeLowPos[randomNumber]; // Set random value for low waiting time randomNumber = random(5); timeWaitMax[i] = timeHighPos[randomNumber]; // Set random value for high waiting time randomNumber = random(5); timeWaitAvg[i] = timeAvgPos[randomNumber]; // Set random value for average waiting time randomNumber = random(5); increment[i] = incrementPos[randomNumber]; // Set random value for increment value randomNumber = random(2); // Set random value for direction randomNumberTwo = random(2); // Set random value for direction if (randomNumber == 1 && randomNumberTwo == 0 && amountHighLED < 2){ // If both are right and not more than 2 are high, go high statusLED[i] = 4; // Set to go Avg to Max amountHighLED = amountHighLED + 1; // Add 1 to the amount of High LEDs }else{ // Else go low statusLED[i] = 1; // Set to go Avg to Low } // Print the status for every LED as soon as it's updated Serial.print("updated"); Serial.print("\t"); Serial.print(i); Serial.print("\t"); Serial.print("to"); Serial.print("\t"); Serial.print(statusLED[i]); Serial.print("\n"); }else if (statusLED[i] == 3){ // -3- Going Low to Avg if ( currentBright[i] >= brightAvg[i] ){ statusLED[i] = 0; // If at lowest point: Go to Waiting Avg }else{ currentBright[i] = currentBright[i]+increment[i]; // Else: Higher Brightness } }else if (statusLED[i] == 2){ // -2- Waiting Low if ( !statusWaiting[i] ){ // If not waiting: waitingTime[i] = millis(); // Set waiting time statusWaiting[i] = true; // Start waiting }else if( statusWaiting[i] && currentTime-waitingTime[i] >= timeWaitLow[i] ){ // If waiting AND timeWaitAvg has passed: statusWaiting[i] = false; // Stop waiting statusLED[i] = 3; // Set statusLed to Waiting for update } }else if (statusLED[i] == 1){ // -1- Going Avg to Low if ( currentBright[i] <= brightMin[i] ){ statusLED[i] = 2; // If at lowest point: Go to Waiting Low }else{ currentBright[i] = currentBright[i]-increment[i]; // Else: Lower Brightness } }else if (statusLED[i] == 6){ // -6- Going Max to Avg if ( currentBright[i] <= brightAvg[i] ){ statusLED[i] = 0; // If at lowest point: Go to Waiting Low amountHighLED = amountHighLED - 1; // -1 on the amount of high LEDs }else{ currentBright[i] = currentBright[i]-increment[i]; // Else: Higher Brightness } }else if (statusLED[i] == 5){ // -5- Waiting Max if ( !statusWaiting[i] ){ // If not waiting: waitingTime[i] = millis(); // Set waiting time statusWaiting[i] = true; // Start waiting }else if( statusWaiting[i] && currentTime-waitingTime[i] >= timeWaitMax[i] ){ // If waiting AND timeWaitAvg has passed: statusWaiting[i] = false; // Stop waiting statusLED[i] = 6; // Set statusLed to Waiting for update } }else if (statusLED[i] == 4){ // -4- Going Avg to Max if ( currentBright[i] >= brightMax[i] ){ statusLED[i] = 5; // If at lowest point: Go to Waiting High }else{ currentBright[i] = currentBright[i]+increment[i]; // Else: Higher Brightness } }else if (statusLED[i] == 0){ // -0- Waiting at Average if ( !statusWaiting[i] ){ // If not waiting: waitingTime[i] = millis(); // Set waiting time statusWaiting[i] = true; // Start waiting }else if( statusWaiting[i] && currentTime-waitingTime[i] >= timeWaitAvg[i] ){ // If waiting AND timeWaitAvg has passed: statusWaiting[i] = false; // Stop waiting statusLED[i] = 7; // Set statusLed to Waiting for update } } } i=0; lastRound = millis(); // Set when the last round is finished. writeToLED(); // Write all data to the LED's } }</p>
Downloads
Final Product
I think it worked out well. The tie is not too thick, stiff, long or heavy and the star effect looks amazing.