Pixel Strip Boom

LED Strip Boom

Here’s another LED Strip animation.

I wanted to have the LEDs appear to come from the center of the strip in sets of different colors. The color sets also needed to move from the center at different velocities. I got the code running and then lost it in my list of sketches. I found it again today.

I chose Purple, Red, Yellow and Blue as the colors for this animation. There are other ways to get this sketch to run, but I used the type that checks the clock and compares a previously saved time to see if enough time has passed to move that particular color.

Here’s the full code. Then I’ll give an explanation.

<code>#include <adafruit_neopixel.h>
 
#define PIN 9
#define numberOfPixels 60
int out_interval = 20;
int boom_interval = 10;
int red_interval = 8;
int purple_interval = 75;
int out_count = 0;
int boom_count = 0;
int red_count = 0;
int purple_count = 0;
long outPreviousMillis = 0;
long boomPreviousMillis = 0;
long redPreviousMillis = 0;
long purplePreviousMillis = 0;
unsigned long currentMillis;
Adafruit_NeoPixel strip = Adafruit_NeoPixel(numberOfPixels, PIN, NEO_GRB + NEO_KHZ800);
 
void setup() {
  strip.begin();
  strip.setBrightness(5); // LOW brightness
  allOff();
  strip.show(); // Initialize all pixels to 'off'
}
 
 
void loop() {
  currentMillis = millis();
    tracerout();
    boom();
    redBoom();
    purpleBoom();
    strip.show();
}
 
void boom() {
  if(currentMillis - boomPreviousMillis > boom_interval) {
    boomPreviousMillis = currentMillis;
  if(boom_count>numberOfPixels/2+1) {
    boom_count=0;
  }else{
    boom_count++;
  }
  }
  strip.setPixelColor(numberOfPixels/2+boom_count-1, strip.Color(0,0,0));
  strip.setPixelColor(numberOfPixels/2-boom_count+1, strip.Color(0,0,0));
  strip.setPixelColor(numberOfPixels/2+boom_count, strip.Color(255,255,0));
  strip.setPixelColor(numberOfPixels/2-boom_count, strip.Color(255,255,0));
 
}
 
void redBoom() {
  if(currentMillis - redPreviousMillis > red_interval) {
    redPreviousMillis = currentMillis;
  if(red_count>numberOfPixels/2+1) {
    red_count=0;
  }else{
    red_count++;
  }
  }
  strip.setPixelColor(numberOfPixels/2+red_count-1, strip.Color(0,0,0));
  strip.setPixelColor(numberOfPixels/2-red_count+1, strip.Color(0,0,0));
  strip.setPixelColor(numberOfPixels/2+red_count, strip.Color(255,0,0));
  strip.setPixelColor(numberOfPixels/2-red_count, strip.Color(255,0,0));
 
}
 
void purpleBoom() {
  if(currentMillis - purplePreviousMillis > purple_interval) {
    purplePreviousMillis = currentMillis;
  if(purple_count>numberOfPixels/2+1) {
    purple_count=0;
  }else{
    purple_count++;
  }
  }
  strip.setPixelColor(numberOfPixels/2+purple_count-1, strip.Color(0,0,0));
  strip.setPixelColor(numberOfPixels/2-purple_count+1, strip.Color(0,0,0));
  strip.setPixelColor(numberOfPixels/2+purple_count, strip.Color(255,0,255));
  strip.setPixelColor(numberOfPixels/2-purple_count, strip.Color(255,0,255));
 
}
 
void allOff() {
  for(int i=0; i<numberofpixels; i++)="" {="" strip.setpixelcolor(i,="" strip.color(0,0,0));="" }="" void="" tracerout()="" if(currentmillis="" -="" outpreviousmillis=""> out_interval) {
    outPreviousMillis = currentMillis;
  if(out_count>numberOfPixels/2+3) {
    out_count=0;
  }else{
    out_count++;
  }
  }
    strip.setPixelColor(numberOfPixels/2+out_count, strip.Color(0,0,255));
    strip.setPixelColor(numberOfPixels/2-out_count, strip.Color(0,0,255));
    if(out_count>2) {
      strip.setPixelColor(numberOfPixels/2-out_count+1, strip.Color(0,0,96));
      strip.setPixelColor(numberOfPixels/2-out_count+2, strip.Color(0,0,50));
      strip.setPixelColor(numberOfPixels/2-out_count+3, strip.Color(0,0,0));
      strip.setPixelColor(numberOfPixels/2+out_count-1, strip.Color(0,0,96));
      strip.setPixelColor(numberOfPixels/2+out_count-2, strip.Color(0,0,50));
      strip.setPixelColor(numberOfPixels/2+out_count-3, strip.Color(0,0,0));
    }
    else if(out_count<2) {
      strip.setPixelColor(numberOfPixels/2, strip.Color(0,0,96));
    }
    else
    {
      strip.setPixelColor(numberOfPixels/2, strip.Color(0,0,50));
      strip.setPixelColor(numberOfPixels/2+1, strip.Color(0,0,96));
      strip.setPixelColor(numberOfPixels/2-1, strip.Color(0,0,96));
    }
}
</numberofpixels;></adafruit_neopixel.h></code>


Per my usual way of doing things with RGB LED Strips, I am using Adafruit’s Adafruit_NeoPixel.h library and an Arduino UNO. I have set the brightness to 5 (very low) and am using pin 9. I am using an RGB LED Strip with 60 pixels.

I started coding for only one color to see if I could get the animation to spread our of the center of the strip toward both ends. The color is blue and there are three brightnesses of blue. This is called with tracerout();. The variables for the blue colors are prefixed with ‘out’. They are out_interval, out_count and outPreviousMillis.

Inside tracerout(), first the clock is checked. If the current time, in milliseconds, minus the previous time that was saved is a smaller number than how often I want the code to run (out_interval) then don’t run the code inside this function. I have out_interval set to 20 meaning unless twenty milliseconds have passed don’t run this part of the sketch which makes the blue lights appear to move.

What runs inside the tracerout() function is to check if the blue pixels have gone off the ends of the strip. If so, start them back at the center. If not, increase the counter that moves the blue lights toward the ends of the strip. Then display the blue lights.

There are three brightnesses of Blue and a blank, or zero, brightness of blue. They look like bright blue, medium blue, dim blue and off. The off erases a previous lighted pixel so you don’t have to blank the strip and then draw the new positions of blues.

There are three more similar functions to handle different colors at different speeds. boom() handles the Yellow color at a speed of 10, or twice the speed of Blue. redBoom() handles the Red color at a speed of 8. purpleBoom() handles Purple color at the slowest speed of 75.

They all check on the current time and compare it to the previous recorded time for their color. If enough time has passed then the position of the colors is updated with the new color. When a color position has changed turn off the pixel in the former position and light up the next pixel. This gives the illusion of motion.

My kids, and my wife, say to keep the brightness low. When it is higher it is not easy to look at.

Sparkle LED Strip

Sparkle LED Strip
Here is a nice short sketch for an LED Strip animation with a sparkle added to it. This is the code: However the animated GIF does not have the random delay that is at the end of the sketch.

#include <Adafruit_NeoPixel.h>
 
#define PIN 9
#define numberOfPixels 60
int myRandom = 0;
Adafruit_NeoPixel strip = Adafruit_NeoPixel(numberOfPixels, PIN, NEO_GRB + NEO_KHZ800);
 
void setup() {
  strip.begin();
  strip.setBrightness(5); // LOW brightness
  allBlue();
  strip.show(); // Initialize all pixels to 'off'
}
 
void loop() {
  // put your main code here, to run repeatedly:
myRandom= random(numberOfPixels);
strip.setPixelColor(myRandom, strip.Color(255,255,255));
strip.show();
delay(5);
strip.setPixelColor(myRandom, strip.Color(0,0,50));
strip.show();
delay(random(25,75));
}
 
void allBlue() {
  for(uint16_t i=0; i<strip.numPixels(); i++) {
      strip.setPixelColor(i, strip.Color(0, 0, 50));
      strip.show();
  }
}


It is not very long at all. I like short code examples that give us something to look at.

It uses pin number 9 on an Arduino and Adafruit’s Adafruit_NeoPixel library.

#include <Adafruit_NeoPixel.h>
 
#define PIN 9
#define numberOfPixels 60

There is a random number and the brightness is very low. It is set to 5. You can increase the brightness as you wish. Brightness goes all the way up to 255. I find 255 way too bright. In fact, a brightness of 100 is still quite bright.

int myRandom = 0;
strip.setBrightness(5); // LOW brightness

In setup() the pixels are all set to a dark blue: strip.Color(0,0,50). This is called with allBlue();. While the code runs the default background is set to this dark blue. You can change it to any color you like.

void allBlue() {
  for(uint16_t i=0; i<strip.numPixels(); i++) {
      strip.setPixelColor(i, strip.Color(0, 0, 50));
      strip.show();
  }
}

myRandom is a random number representing each of the pixels on the strip of pixels. Since there are 60 pixels the random number is 0 to 59.

myRandom= random(numberOfPixels);

Once the myRandom number is chosen the pixel associated with that number is set to white for a tiny bit of time. You can see this time in the delay(5); command. After that, the pixel is set back to the blue color. Then there is a random time until the code repeats. Upon repeating the next random pixel is chosen to turn white for a short amount of time. And on it goes.

The random time that is chosen before the code repeats is set by the following line of code. It is setting a delay length of time from 25 through 74.

delay(random(25,75));

RGB LED Strips

I love the individually programmable NeoPixel strips and the animations that you can come up with when using an Arduino or other microcontroller. Adafruit taught me the basics and I took off from there.

My favorite animation from Adafruit is the “rainbowCycle” animation. It is included in the Adafruit_NeoPixel.h library examples inside the strandtest sketch. I took that example out of the sketch by deleting everything I didn’t need and renaming the sketch.
I didn’t like the direction that the animation flows from the far end of the strip to the end near the Arduino, so I figured a way to alter that.

Here is the edited version of the sketch.

#include <Adafruit_NeoPixel.h>
 
#define PIN 9
#define numberOfPixels 60
Adafruit_NeoPixel strip = Adafruit_NeoPixel(numberOfPixels, PIN, NEO_GRB + NEO_KHZ800);
 
void setup() {
  strip.begin();
  strip.setBrightness(5); // LOW brightness
  allOff();
  strip.show(); // Initialize all pixels to 'off'
}
 
void loop() {
rainbowCycle(0);
}
 
void allOff() {
  for(uint16_t i=0; i<strip.numPixels(); i++) {
      strip.setPixelColor(i, strip.Color(0, 0, 0));
      strip.show();
  }
}
 
// Slightly different, this makes the rainbow equally distributed throughout
// I divided the number of pixels by three and got 20. I set up that
// there are three equally distributed rainbows.
void rainbowCycle(uint8_t wait) {
  uint16_t i, j;
 
  for(j=0; j<256*5; j++) { // 5 cycles of all colors on wheel
    for(i=0; i< 20; i++) {
      strip.setPixelColor(19-i, Wheel(((i * 256 / 20) + j) & 255));
      strip.setPixelColor(19-i+20, Wheel(((i * 256 / 20) + j) & 255));
      strip.setPixelColor(19-i+40, Wheel(((i * 256 / 20) + j) & 255));
    }
    strip.show();
    delay(wait);
  }
}
 
// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
  if(WheelPos < 85) {
   return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
  } else if(WheelPos < 170) {
   WheelPos -= 85;
   return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  } else {
   WheelPos -= 170;
   return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
}


The original section in the sketch looks like this:

void rainbowCycle(uint8_t wait) {
uint16_t i, j;
 
for(j=0; j<256*5; j++) { // 5 cycles of all colors on wheel
for(i=0; i< strip.numPixels(); i++) {
strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
}
strip.show();
delay(wait);
}
}


The original code has the rainbow colors spread evenly over the length of the LED strip and cycles the colors from the far end toward the Arduino.

The strip has 60 pixels and I wanted to have the animation appear to flow from the Arduino toward the far end. I also wanted the rainbow to be spread evenly three times over the length of the LED strip.

All of the changes I needed to make are in this section of code:

for(i=0; i< strip.numPixels(); i++) {
strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
}


First of all, to make the animation run in the opposite direction I just put “59-” in front of the “i” where it says “strip.setPixelColor(i, Wheel…”. It looks like:

for(i=0; i< strip.numPixels(); i++) {
strip.setPixelColor(59-i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
}

Yes, I could have had the for loop count down, but adding three characters was much easier. Also, “for(i=strip.numPixels()-1; i > -1; i–)” doesn’t seem to work and trouble shooting it would take longer than just adding three characters.

Instead of 59 I could have used strip.numPixels()-1. I was just making it easier for me with the strip I have.

To get three evenly distributed rainbows across the 60 NeoPixels I had to divide the total number (60) by three. So, I have three sets of twenty.

The three sets are separated out by i, i+20 and i+40. The count goes from 0 to 19, which is twenty numbers. To make the animation run backwards I had to put “19-” in front of the “i”. The section of code looks like:

for(i=0; i< 20; i++) {
strip.setPixelColor(19-i, Wheel(((i * 256 / 20) + j) & 255));
strip.setPixelColor(19-i+20, Wheel(((i * 256 / 20) + j) & 255));
strip.setPixelColor(19-i+40, Wheel(((i * 256 / 20) + j) & 255));
}

In the void loop() I called rainbowCycle(0);. The zero means no delay. I wanted it to run as quickly as possible on the Arduino UNO.

Here, again, is the final sketch.

#include <Adafruit_NeoPixel.h>
 
#define PIN 9
#define numberOfPixels 60
Adafruit_NeoPixel strip = Adafruit_NeoPixel(numberOfPixels, PIN, NEO_GRB + NEO_KHZ800);
 
void setup() {
  strip.begin();
  strip.setBrightness(5); // LOW brightness
  allOff();
  strip.show(); // Initialize all pixels to 'off'
}
 
void loop() {
rainbowCycle(0);
}
 
void allOff() {
  for(uint16_t i=0; i<strip.numPixels(); i++) {
      strip.setPixelColor(i, strip.Color(0, 0, 0));
      strip.show();
  }
}
 
// Slightly different, this makes the rainbow equally distributed throughout
// I divided the number of pixels by three and got 20. I set up that
// there are three equally distributed rainbows.
void rainbowCycle(uint8_t wait) {
  uint16_t i, j;
 
  for(j=0; j<256*5; j++) { // 5 cycles of all colors on wheel
    for(i=0; i< 20; i++) {
      strip.setPixelColor(19-i, Wheel(((i * 256 / 20) + j) & 255));
      strip.setPixelColor(19-i+20, Wheel(((i * 256 / 20) + j) & 255));
      strip.setPixelColor(19-i+40, Wheel(((i * 256 / 20) + j) & 255));
    }
    strip.show();
    delay(wait);
  }
}
 
// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
  if(WheelPos < 85) {
   return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
  } else if(WheelPos < 170) {
   WheelPos -= 85;
   return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  } else {
   WheelPos -= 170;
   return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
}