Introduction: Starry Sky Led Tie

About: Likes to produce whatever crazy idea comes in my head

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)

Step 1: 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)

- Adafruit Powerboost 500 charger

- Emmerich Li-ion accu ICR-18650NH-SP

- Optic fibers (in different sizes)

Step 2: 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.

Step 3: 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.

Step 4: 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!

Step 5: 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.

Step 6: 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.

Step 7: 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.

Step 8: 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

<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
      }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
          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
          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
          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
          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
    lastRound = millis();                                                                 // Set when the last round is finished.
    writeToLED();                                                                         // Write all data to the LED's

Step 9: Final Product

I think it worked out well. The tie is not too thick, stiff, long or heavy and the star effect looks amazing.