NEON FLEX LED SIGN

These Neon Flex (LED) Signs are a great way to take your projects to that next level. We go over Design, Cutting it out, Programing, and more. So if you are intrested in making one check out this 2 Part Series on how you can make a Neon Flex Sign of your own.

Part 1

To get started we go over Materials needed, Design, and the CAD & CAM.

Part 2

In this video we get everything wired up and we take a look at the code.

AFFILIATE LINKS TO MATERIALS USED

LED Flex Light

Power

Pro Micro

Resistor

Capacitor

JST Plugs

WIRING DIAGRAM

ARDUINO CODE:

//GET OUR LIBRARIES

#include <FastLED.h>

#include <OneButton.h>


//DEFINE OUR WHAT IS CONNECTED TO OUR PINES

#define LED_PIN_CENTER     4 //CENTER

#define LED_PIN_A          2 //SIDE A

#define LED_PIN_B          7 //SIDE B

#define BTN_PIN            14  //BUTTON


//DEFINE HOW MANY LEDS EACH STRIP HAS

#define NUM_LEDS_CENTER    139 //NUMBER LEDS CENTER

#define NUM_LEDS_SIDE_A     56 //NUMBER LEDS SIDE

#define NUM_LEDS_SIDE_B     56 //NUMBER LEDS SIDE


//DEFINE SETTINGS FOR SUB LOOPS

#define COOLING  55

#define SPARKING 120


// Define the array of leds, This is what we will use to turn on a specific strand of LEDs

CRGB ledsC[NUM_LEDS_CENTER];

CRGB ledsA[NUM_LEDS_SIDE_A];

CRGB ledsB[NUM_LEDS_SIDE_B];



//Global Variables that can be used in any function

unsigned long interval=25; // the time we need to wait

unsigned long previousMillis=0; // millis() returns an unsigned long.

unsigned long interval_b = 100; // the time we need to wait Part 2


uint8_t patternCounter = 0;

uint8_t minBright = 20;

uint8_t maxBright = 80;

bool gReverseDirection = false;


//MORE GLOBAL VARIABLES FOR SUB LOOPS

int numColors = 1;

int ra = 60;

int rb = 0;

int dir = 0;

int dirb = 0;

int dirc = 0;

int la = 0;

int sat = 0;


// Push button connected between pin 14 and GND (no resistor required) Defining our Push Button

OneButton btn = OneButton(BTN_PIN, true, true);


void setup() {


  //Initializing our LEDs

  FastLED.addLeds<WS2812, LED_PIN_CENTER, GRB>(ledsC, NUM_LEDS_CENTER);

  FastLED.addLeds<WS2812, LED_PIN_A, GRB>(ledsA, NUM_LEDS_SIDE_A);

  FastLED.addLeds<WS2812, LED_PIN_B, GRB>(ledsB, NUM_LEDS_SIDE_B);

  //Set our inital LED Brightness

  FastLED.setBrightness(50);

  //Serial.begin(9600);

  //One Button lets us tell the program what to do when the button is clicked, so it will Run - nextPattern

  btn.attachClick(nextPattern);

  //This gives us time will testing to upload a new sketch to the board in case it gets stuck, Can take this out once code is finalized

  delay(5000);


}


//MAIN LOOP

void loop() {


  //SWITCH & CASE - controls the flow of programs by allowing programmers to specify different code that should be executed in various conditions

  //BREAK - keyword exits the switch statement, and is typically used at the end of each case. Without a break statement, the switch statement will

  //continue executing the following expressions ("falling-through") until a break, or the end of the switch statement is reached.

  switch (patternCounter) {

    case 0:

      solidColor();      

      break;

    case 1:

      rainbowBeat();

      break;

    case 2:

      redAlertB();

      break;

    case 3:

      fire();

      break;

    case 4:

      juggle();

      break;

    case 5:

      movingDots();

      break;

    case 6:

      redAlert();

      break;

    case 7:

      redgold();

      break;

    case 8:

      gradientChangeSlow();

      break;

    case 9:

      gradientChangeFast();

      break;

  }


  //NOTICE FastLED.show is here, and not in our Sub Loops

  FastLED.show();

  btn.tick();

}


void nextPattern() {

  //This changes what Case we are on

  patternCounter = (patternCounter + 1) % 10;           // Change the number after the % to the number of patterns you have

  FastLED.clear (); //Clears our current LEDs

}


//------- Put your patterns below -------//


void solidColor() {


   //TO Change the Speed Change the 5000

   float breath = (exp(sin(millis()/5000.0*PI)) - 0.36787944)*108.0;

   //Map Breath Value from above to 0-255, then get the GLOBAL minBright & maxBright Variable

   breath = map(breath, 0, 255, minBright, maxBright);

   FastLED.setBrightness(breath);


   fill_solid(ledsC, NUM_LEDS_CENTER, CRGB::SlateGray);

   fill_solid(ledsA, NUM_LEDS_SIDE_A, CRGB::Gold);

   fill_solid(ledsB, NUM_LEDS_SIDE_B, CRGB::Gold);

   

}


void rainbowBeat() {


  uint16_t beatA = beatsin16(30, 0, 255);

  uint16_t beatB = beatsin16(20, 0, 255);

  fill_rainbow(ledsC, NUM_LEDS_CENTER, (beatA+beatB)/2, 8);  // Initial Hue - Delta HUE - How fast to advance the led

  fill_rainbow(ledsA, NUM_LEDS_SIDE_A, (beatA+beatB)/2, 8);

  fill_rainbow(ledsB, NUM_LEDS_SIDE_B, (beatA+beatB)/2, 8);

}


void redAlertB() {


    unsigned long currentMillis = millis();

   

    if ((unsigned long)(currentMillis - previousMillis) >= interval) {


        //LEFT SIDE OF CENTER

        ledsC[ra]  = CRGB(255,0,0);

        if (dir == 0){

          ra ++;

            if (ra == 140){

              dir  = 1;

              }

        }

        else if (dir == 1){

          ra --;

            if (ra == 60){

              dir = 0;

            }

        }

        //RIGHT SIDE OF CENTER

        ledsC[rb] = CRGB(255,0,0);

        if (dirb == 0){

          rb ++;

            if (rb == 60){

              dirb  = 1;

              }

        }

        else if (dirb == 1){

          rb --;

            if (rb == 0){

              dirb = 0;

            }

        }



        ledsA[la] = CRGB(255,0,0);

        ledsB[la] = CRGB(255,0,0);

        if (dirc == 0){

          la ++;

            if (la == NUM_LEDS_SIDE_A){

              dirc  = 1;

              }

        }

        else if (dirc == 1){

          la --;

            if (la == 0){

              dirc = 0;

            }

        }

       

       


        fadeToBlackBy(ledsC, NUM_LEDS_CENTER, 8);

        fadeToBlackBy(ledsA, NUM_LEDS_SIDE_A, 15);

        fadeToBlackBy(ledsB, NUM_LEDS_SIDE_B, 15);

        previousMillis = millis();

     

  }

}


void fire()  {

// Array of temperature readings at each simulation cell

  static byte heat[NUM_LEDS_CENTER];


  // Step 1.  Cool down every cell a little

    for( int i = 0; i < NUM_LEDS_CENTER; i++) {

      heat[i] = qsub8( heat[i],  random8(0, ((COOLING * 10) / NUM_LEDS_CENTER) + 2));

    }


    for( int i = 0; i < NUM_LEDS_SIDE_A; i++) {

      heat[i] = qsub8( heat[i],  random8(0, ((COOLING * 10) / NUM_LEDS_SIDE_A) + 2));

    }



    // Step 2.  Heat from each cell drifts 'up' and diffuses a little

    for( int k= NUM_LEDS_CENTER - 1; k >= 2; k--) {

      heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2] ) / 3;

    }


    for( int k= NUM_LEDS_SIDE_A - 1; k >= 2; k--) {

      heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2] ) / 3;

    }    


    // Step 3.  Randomly ignite new 'sparks' of heat near the bottom

    if( random8() < SPARKING ) {

      int y = random8(7);

      heat[y] = qadd8( heat[y], random8(160,255) );

    }


    // Step 4.  Map from heat cells to LED colors

    for( int j = 0; j < NUM_LEDS_CENTER; j++) {

      CRGB color = HeatColor( heat[j]);

      int pixelnumber;

      if( gReverseDirection ) {

        pixelnumber = (NUM_LEDS_CENTER-1) - j;

      } else {

        pixelnumber = j;

      }

      ledsC[pixelnumber] = color;

    }


    // Step 4.  SIDE A

    for( int j = 0; j < NUM_LEDS_SIDE_A; j++) {

      CRGB color = HeatColor( heat[j]);

      int pixelnumber;

      if( gReverseDirection ) {

        pixelnumber = (NUM_LEDS_SIDE_A-1) - j;

      } else {

        pixelnumber = j;

      }

      ledsA[pixelnumber] = color;

    }


    // Step 4.  SIDE B

    for( int j = 0; j < NUM_LEDS_SIDE_B; j++) {

      CRGB color = HeatColor( heat[j]);

      int pixelnumber;

      if( gReverseDirection ) {

        pixelnumber = (NUM_LEDS_SIDE_B-1) - j;

      } else {

        pixelnumber = j;

      }

      ledsB[pixelnumber] = color;

    }    

}


void juggle() {

  fadeToBlackBy( ledsC, NUM_LEDS_CENTER, 20);

  fadeToBlackBy( ledsA, NUM_LEDS_SIDE_A, 20);

  fadeToBlackBy( ledsB, NUM_LEDS_SIDE_B, 20);

  uint8_t dothue = 0;

  for( int i = 0; i < 8; i++) {

    ledsC[beatsin16( i+7, 0, NUM_LEDS_CENTER-1 )] |= CHSV(dothue, 200, 255);

    ledsA[beatsin16( i+7, 0, NUM_LEDS_SIDE_A-1 )] |= CHSV(dothue, 200, 255);

    ledsB[beatsin16( i+7, 0, NUM_LEDS_SIDE_B-1 )] |= CHSV(dothue, 200, 255);

    dothue += 32;

  }

}


void movingDots() {


//       beatsin16( BPM, uint16_t low, uint16_t high) returns a 16-bit value

//                    that rises and falls in a sine wave, 'BPM' times per

//                    minute, between the values of 'low' and 'high'.


  //CENTER

  uint16_t posBeat  = beatsin16(30, 0, NUM_LEDS_CENTER - 1, 0, 0);

  uint16_t posBeat2 = beatsin16(60, 0, NUM_LEDS_CENTER - 1, 0, 0);


  uint16_t posBeat3 = beatsin16(30, 0, NUM_LEDS_CENTER - 1, 0, 32767);

  uint16_t posBeat4 = beatsin16(60, 0, NUM_LEDS_CENTER - 1, 0, 32767);


  //SIDES A & B

  uint16_t posBeat5  = beatsin16(30, 0, NUM_LEDS_SIDE_A - 1, 0, 0);

  uint16_t posBeat6  = beatsin16(60, 0, NUM_LEDS_SIDE_B - 1, 0, 0);


  uint16_t posBeat7 = beatsin16(30, 0, NUM_LEDS_SIDE_A - 1, 0, 32767);

  uint16_t posBeat8 = beatsin16(60, 0, NUM_LEDS_SIDE_B - 1, 0, 32767);  


  // Wave for LED color

  uint8_t colBeat  = beatsin8(45, 0, 255, 0, 0);


  //HUE SATURATION VALUE (Brightness)


  ledsC[(posBeat + posBeat2) / 2]  = CHSV(colBeat, 255, 255);

  ledsC[(posBeat3 + posBeat4) / 2]  = CHSV(colBeat, 255, 255);


  ledsA[(posBeat5 + posBeat6) / 2]  = CHSV(colBeat, 255, 255);

  ledsA[(posBeat7 + posBeat8) / 2]  = CHSV(colBeat, 255, 255);


  ledsB[(posBeat5 + posBeat6) / 2]  = CHSV(colBeat, 255, 255);

  ledsB[(posBeat7 + posBeat8) / 2]  = CHSV(colBeat, 255, 255);


  //Turn Off Lights by fadeing


  fadeToBlackBy(ledsC, NUM_LEDS_CENTER, 10);

  fadeToBlackBy(ledsA, NUM_LEDS_SIDE_A, 10);

  fadeToBlackBy(ledsB, NUM_LEDS_SIDE_B, 10);

}


void redAlert() {


  FastLED.setBrightness(50);


  //(BEATS per min, FIRST LED, LAST LED, TIMEBASE, PHASE OFFSET)

  //beatsin16 generates a 16-bit sine wave at a given BPM, that oscillates within a given range

  //So we are generating this SinWave between 60 & 139 on our LED Strip for the Center part

  uint16_t sinBeatA   = beatsin16(15, 60, 139, 0, 21845);

  uint8_t sinBeatAA   = beatsin8(15, 60, 139, 0, 0);


  uint16_t sinBeatB   = beatsin16(30, 0, 60, 0, 21845);

  uint8_t sinBeatBB   = beatsin8(15, 0, 60, 0, 0);



  uint16_t sinBeatL   = beatsin16(15, 0, 28, 0, 21845);

  uint8_t sinBeatLL   = beatsin8(15, 0, 28, 0, 0);


  uint16_t sinBeatM   = beatsin16(15, 28, 56, 0, 21845);

  uint8_t sinBeatMM   = beatsin8(15, 28, 56, 0, 0);  



  ledsC[sinBeatA]  = CRGB(255,0,0);

  ledsC[sinBeatB]  = CRGB(255,0,0);

  ledsC[sinBeatAA]  = CRGB(255,0,0);

  ledsC[sinBeatBB]  = CRGB(255,0,0);


  ledsA[sinBeatL]  = CRGB(255,0,0);

  ledsA[sinBeatLL]  = CRGB(255,0,0);

  ledsA[sinBeatM]  = CRGB(255,0,0);

  ledsA[sinBeatMM]  = CRGB(255,0,0);  


  ledsB[sinBeatL]  = CRGB(255,0,0);

  ledsB[sinBeatLL]  = CRGB(255,0,0);

  ledsB[sinBeatM]  = CRGB(255,0,0);

  ledsB[sinBeatMM]  = CRGB(255,0,0);    


  fadeToBlackBy(ledsC, NUM_LEDS_CENTER, 5);

  fadeToBlackBy(ledsA, NUM_LEDS_CENTER, 10);

  fadeToBlackBy(ledsB, NUM_LEDS_CENTER, 10);


}



void redgold() {


  uint16_t sinBeat   = beatsin16(30, 0, NUM_LEDS_CENTER - 1, 0, 0);

  uint16_t sinBeat2  = beatsin16(30, 0, NUM_LEDS_CENTER - 1, 0, 21845);

  uint16_t sinBeat3  = beatsin16(30, 0, NUM_LEDS_CENTER - 1, 0, 43690);


  uint16_t sinBeat4  = beatsin16(30, 0, NUM_LEDS_SIDE_A - 1, 0, 0);

  uint16_t sinBeat5  = beatsin16(30, 0, NUM_LEDS_SIDE_A - 1, 0, 21845);

  uint16_t sinBeat6  = beatsin16(30, 0, NUM_LEDS_SIDE_A - 1, 0, 43690);



  ledsC[sinBeat]   = CRGB::Red;

  ledsC[sinBeat2]  = CRGB::DarkRed;

  ledsC[sinBeat3]  = CRGB::Maroon;



  ledsA[sinBeat4]  = CRGB::DarkGoldenrod;

  ledsA[sinBeat5]  = CRGB::Goldenrod;

  ledsA[sinBeat6]  = CRGB::Gold;  


  ledsB[sinBeat4]  = CRGB::DarkGoldenrod;

  ledsB[sinBeat5]  = CRGB::Goldenrod;

  ledsB[sinBeat6]  = CRGB::Gold;



  fadeToBlackBy(ledsC, NUM_LEDS_CENTER, 6);

  fadeToBlackBy(ledsA, NUM_LEDS_SIDE_A, 6);

  fadeToBlackBy(ledsB, NUM_LEDS_SIDE_A, 6);  

}


void gradientChangeSlow() {

  uint8_t starthue_c = beatsin8(4, 0, 255);

  uint8_t endhue_c = beatsin8(8, 255, 255);


  uint8_t starthue_ab = beatsin8(2, 0, 255);

  uint8_t endhue_ab = beatsin8(4, 255, 255);


  unsigned long currentMillis = millis();

   

  if ((unsigned long)(currentMillis - previousMillis) >= interval_b) {


      fill_gradient(ledsC,NUM_LEDS_CENTER,CHSV(starthue_c, 255, 255),CHSV(endhue_c, starthue_c, 255),FORWARD_HUES);

      fill_gradient(ledsA,NUM_LEDS_SIDE_A,CHSV(starthue_ab, 255, 255),CHSV(endhue_ab, starthue_ab, 255),FORWARD_HUES);

      fill_gradient(ledsB,NUM_LEDS_SIDE_B,CHSV(starthue_ab, 255, 255),CHSV(endhue_ab, starthue_ab, 255),FORWARD_HUES);

     

  }

}


void gradientChangeFast() {

  uint8_t starthue_c = beatsin8(32, 0, 255);

  uint8_t endhue_c = beatsin8(32, 255, 0);


  unsigned long currentMillis = millis();

   

  if ((unsigned long)(currentMillis - previousMillis) >= interval_b) {


      fill_gradient(ledsC,NUM_LEDS_CENTER,CHSV(starthue_c, 255, 255),CHSV(endhue_c, starthue_c, 255),FORWARD_HUES);

      fill_gradient(ledsA,NUM_LEDS_SIDE_A,CHSV(starthue_c, 255, 255),CHSV(endhue_c, starthue_c, 255),FORWARD_HUES);

      fill_gradient(ledsB,NUM_LEDS_SIDE_B,CHSV(starthue_c, 255, 255),CHSV(endhue_c, starthue_c, 255),FORWARD_HUES);

     

  }

}