NeoPixel Ring

Hi guys,

I apologize for the "noob-ness" of my question, as what I am trying to achieve should be relatively simple I just cannot figure out where to even start from.

I currently have the NeoPixel code set so that it takes a minute to fill the 24 LED's.

What I am trying to accomplish is that after the ring makes one revolution, it add's one LED onto the start and then takes a minute to go around again. Then this repeats till the whole ring is full (should be 24 minutes)

Any insight would be super helpful. Here is the code I have so far.

#include <Adafruit_NeoPixel.h>      //Include AdaFruit NEO Library 
#define PIN            9            //Assign NEO Ring to pin 9
#define NUMPIXELS      24           //Define that there are 24 LED's in ring
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);     //AdaFruit Neo Library

int delayval = 2500;                // delay for 2.5 seconds (24 LED's in a minute)

void setup() {
  pixels.begin();                   // This initializes the NeoPixel library.
}

void loop() {
  for(int i=0;i<NUMPIXELS;i++){
    pixels.setPixelColor(i, pixels.Color(0,0,50));        // Dim Blue Color
    pixels.show();                                        // This sends the updated pixel to the ring
    delay(delayval);                                      // Delay for a period of time
  }
}

What I am trying to accomplish is that after the ring makes one revolution, it add's one LED onto the start

I don't understand that this means. Do you want to turn 24 LEDs on, one at a time, with a definite interval between them, then turn all but one off. On the next iteration, turn 23 LEDs on, with the same interval between them? Or a different interval?

Please try again, to describe what you want to do.

PS: Whatever it is, it is possible.

Ok. Think in terms not of "adding a new blue pixel to the ring", but of clearing the ring and then redawing the whole thing.

You need to keep two variables: "what point are we on the ring" (the job that your i variable is currently doing), and "how many pixels do I need to show".

Now to make all this go, you need to understand the modulus operator '%'. This operator gives the remainder of a division operator. This is important, because it makes the fact that you need to "loop around' at NUMPIXELS much easier to deal with.

Another thing to note is that it's good for the loop() function to do whatever it needs to do and then return immediately, rather than sitting in a loop. I have left this with a "delay" function. You can code this up without delay, but we'll leave that for now.

#include <Adafruit_NeoPixel.h>      //Include AdaFruit NEO Library
#define PIN            9            //Assign NEO Ring to pin 9
#define NUMPIXELS      24           //Define that there are 24 LED's in ring
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);     //AdaFruit Neo Library

int delayval = 2500;                // delay for 2.5 seconds (24 LED's in a minute)
int barStart = 0; // start at point 0
int barSize = 1; // start with one blue pixel

void loop() {
  for(int i=0;i<NUMPIXELS;i++){
    pixels.clear();
  }

  for(int i = 0; i< barSize; i++) {
    // use the modulus operator to wrap around
    pixels.setPixelColor((barStart + i) % NUMPIXELS, pixels.Color(0,0,50));        // Dim Blue Color
  }

  pixels.show();                                        // This sends the updated pixel to the ring
  delay(delayval);                                      // Delay for a period of time

  // now increment everything

  barStart = (barStart + 1) % NUMPIXELS; // move the bar around by 1, but wrap to zero

  // if the start of the bar has wrapped around back to zero, then we need to increase the barSize  

  if(barStart == 0) {
    barSize++;
    // but we don't want the bar to fill up the whole ring
    if(barSize >= NUMPIXELS) {
      barSize = 1; // so, back to a size of 1
    }
  }
}

There are other ways to do this. For instance, you can do stuff that only clears the pixel about to go dark and only lights the pixel about to go light. But it doesn't save you much. because pixels.show() has to push out the entire array to the neopixel ring anyway.

I'll do my best to re-describe what we are trying to accomplish, hopefully it makes more sense this time.

Initiate the whole ring in one color (say red), then have a single pixel (white) that takes 2.5 seconds to fade its way around the ring(while the other pixels all still remain the initial color)

Once the single pixel reaches the last position on the ring (LED 23), turn LED 0 (the initial LED) a different color from the initial color (say from red to green). Then the white "counter" pixel starts its 2.5 second revolution from the pixel after the one that has now changed color. Then repeat this for the whole ring, adding to the new color side of the ring every time the LED makes a "revolution" of the LEDs that are left the initial color.

I'm sure I am making it sound way more complicated than it needs to be lol.

You need a loop to turn all the pixels on one color (red).

Then, you need a loop that moves a white LED through 24 positions, taking the required time. As that loop turns a pixel from white to another color, you need to decide whether the other color is red or green.

You need a variable that keeps track of where the green LEDs start. Each time the cycle completes, you increment that value. If the white position is moving from an pixel below that number, set the pixel back to green. If the white position is moving from a pixel above that value, turn that pixel back to green.

What is to happen when all the red pixels have been turned green? Does the white pixel keep rotating?

Make all the pixels the starting color
Starting marker is zero

  • Change the marker to the marker color and wait
  • Change the marker back to the starting color
  • At the end of the ring change the starting marker to the final color
  • Increment the starting marker and go around again
  • Repeat until the last pixel was the starting marker

I have an 8x8 LED matrix and use the FastLED library, so if you want to base your program on my demo code you'll have to convert to the Adafruit library. Also, it goes fast for testing, you'll have to work out the timing. It is tested working, though.

#include "FastLED.h"

#define START_COLOR CRGB::Red
#define MARKER_COLOR CRGB::White
#define FINAL_COLOR CRGB::grg

#define NUM_LEDS 64

#define DATA_PIN 3
CRGB leds[NUM_LEDS];

// starting place for marker for each pass
int startLED = 0;

void setup() {

  // init leds
  FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);
  FastLED.setBrightness(84);


  // set all to start color
  for (int i = 0; i < NUM_LEDS; i++) {

    leds[i] = START_COLOR;
  }

  FastLED.show();
  delay(500);

}

void loop()
{

  // if we have not changed colors of all LEDs
  if ( startLED < NUM_LEDS )
  {

    // while more LEDs for this pass
    for (int i = startLED; i < NUM_LEDS; i++)
    {

      // change marker
      leds[i] = MARKER_COLOR;
      FastLED.show();
      delay(10);

      // marker back to original color
      leds[i] = START_COLOR;
      delay(10);
      FastLED.show();

    } // for

    // the LED we strted on goes to final color
    leds[startLED] = CRGB::Green;
    FastLED.show();

    // advance starting LED
    startLED++;

  }


}