Turning Neopixel Ring Chase on with a button for a set time using Millis

Hi,

I recently bought a NeoPixel Ring with 12 LED's.

I want to include it in a current code I have programmed, but I don't understand how to do the simplest thing with it.

Basically all I want to know is how to code the NeoPixel LED's (white) to chase each other (like Knight Rider but only go in one direction) after a button has been pushed, but this chase to only run for a certain amount of milliseconds.

I want to avoid using the delay function, and would rather use millis as I need to incorporate this into an existing program.

I would really appreciate help on how I'm suppose to code this - haven't had any luck looking online yet.

The Adafruit NeoPixel library comes with several examples.

None use Millis though, they all use delay, so i'm unsure how to go about it. I'm very new to programming so don't really understand.

This is my current code:

But I can't get the millis to work and I don't understand so would appreciate some help.

#include <Adafruit_NeoPixel.h>

#define PIN             A5
#define  NUMPIXELS      12

Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

const int ButtonPin = 2;

unsigned long pixelWentOnAt;
int pixelStaysOnFor = 3000;


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

void loop() {
  if (!digitalRead(ButtonPin))
  {
    pixelWentOnAt = millis();
    pixels.setPixelColor(0, pixels.Color(255,255,255));
    pixels.setPixelColor(1, pixels.Color(255,255,255));
    pixels.setPixelColor(2, pixels.Color(255,255,255));
    pixels.setPixelColor(3, pixels.Color(255,255,255));
    pixels.setPixelColor(4, pixels.Color(255,255,255));
    pixels.setPixelColor(5, pixels.Color(255,255,255));
    pixels.setPixelColor(6, pixels.Color(255,255,255));
    pixels.setPixelColor(7, pixels.Color(255,255,255));
    pixels.setPixelColor(8, pixels.Color(255,255,255));
    pixels.setPixelColor(9, pixels.Color(255,255,255));
    pixels.setPixelColor(10, pixels.Color(255,255,255));
    pixels.setPixelColor(11, pixels.Color(255,255,255));
    pixels.show();
    if (millis() - pixelWentOnAt >= (unsigned long) pixelStaysOnFor);
  } else {
    pixels.setPixelColor(0, pixels.Color(0,0,0));
    pixels.setPixelColor(1, pixels.Color(0,0,0));
    pixels.setPixelColor(2, pixels.Color(0,0,0));
    pixels.setPixelColor(3, pixels.Color(0,0,0));
    pixels.setPixelColor(4, pixels.Color(0,0,0));
    pixels.setPixelColor(5, pixels.Color(0,0,0));
    pixels.setPixelColor(6, pixels.Color(0,0,0));
    pixels.setPixelColor(7, pixels.Color(0,0,0));
    pixels.setPixelColor(8, pixels.Color(0,0,0));
    pixels.setPixelColor(9, pixels.Color(0,0,0));
    pixels.setPixelColor(10, pixels.Color(0,0,0));
    pixels.setPixelColor(11, pixels.Color(0,0,0));
    pixels.show();

}
}

Here's a kicker for you.
It alternates "Pixel 0" red/green the non-blocking/millis() way.

#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h> // Required for 16 MHz Adafruit Trinket
#endif
// Which pin on the Arduino is connected to the NeoPixels?
#define PIN        5 // On Trinket or Gemma, suggest changing this to 1
// How many NeoPixels are attached to the Arduino?
#define NUMPIXELS 16 // Popular NeoPixel ring size
Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
#define DELAYVAL 500 // Time (in milliseconds) to pause between pixels
unsigned long capture;
const unsigned long interval = 250; // blinky
const unsigned long duration = 3000; // overall
//unsigned long durationMarker;
unsigned long intervalMarker;
bool pixState;

void setup() 
{
  pinMode(13,OUTPUT);
  digitalWrite(13,LOW);
  
  pixels.begin();
  pixels.clear();
  pixels.show();
  pixState = true;
  pixels.setPixelColor(0, pixels.Color(20,0,0));
  pixels.show();
}

void loop() 
{
  intervalMarker = millis();
  
  do 
  {
    capture = millis();
  }while(capture - intervalMarker < interval);
  pixState = !pixState;
  if(pixState == true)
  {
    pixels.setPixelColor(0, pixels.Color(20,0,0));
  }
  else
  {
    pixels.setPixelColor(0, pixels.Color(0,20,0));
  }
  pixels.show();
}

This has a pushbutton switch added.
Activating the switch triggers the neopixel alternating red/green for 3 seconds.

// neopix_pb_01
//
//
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h> // Required for 16 MHz Adafruit Trinket
#endif
// Which pin on the Arduino is connected to the NeoPixels?
#define PIN        5 // On Trinket or Gemma, suggest changing this to 1
// How many NeoPixels are attached to the Arduino?
#define NUMPIXELS 16 // Popular NeoPixel ring size
Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
#define DELAYVAL 500 // Time (in milliseconds) to pause between pixels
unsigned long capture;
const unsigned long interval = 250;  // blinky
const unsigned long duration = 3000; // overall
unsigned long durationMarker;
unsigned long intervalMarker;
const byte pbswitch = 7;
byte swState;
bool pixState;
bool flag;
void setup() 
{
  pinMode(13,OUTPUT);    //optional
  digitalWrite(13,LOW);  //optional
  pinMode(pbswitch,INPUT_PULLUP);
 
  pixels.begin();
  pixels.clear();
  pixels.show();
  pixState = true;
  flag = false;
  pixels.setPixelColor(0, pixels.Color(20,0,0));
  pixels.show();
}
void loop() 
{
  if(flag == false)
  {
    checkpb();
    durationMarker = millis();
    intervalMarker = millis();
    capture = millis();
  }
  
  while((capture - durationMarker) < duration)
  {
    capture = millis();
    if((capture - intervalMarker) >= interval)
    {
      pixState = !pixState;
      if(pixState == true)
      {
        pixels.setPixelColor(0, pixels.Color(20,0,0));
      }
      else
      {
        pixels.setPixelColor(0, pixels.Color(0,20,0));
      }
      pixels.show();
      intervalMarker = millis();
    }
  }
  flag = false;
  
}
void checkpb ()
{
  do
  {
    swState = digitalRead(pbswitch);
    digitalWrite(13,swState);
  }while(swState == 1);
  flag = true;
}

OK, so, finally,
this chases R-G-B

(Is there anybody out there??)

#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h> // Required for 16 MHz Adafruit Trinket
#endif
// Which pin on the Arduino is connected to the NeoPixels?
#define PIN        5 // On Trinket or Gemma, suggest changing this to 1
// How many NeoPixels are attached to the Arduino?
#define NUMPIXELS 16 // Popular NeoPixel ring size
Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
#define DELAYVAL 500 // Time (in milliseconds) to pause between pixels
unsigned long capture;
const unsigned long interval = 1000; // blinky
const unsigned long duration = 10000; // overall
unsigned long durationMarker;
unsigned long intervalMarker;
const byte pbswitch = 7;
byte swState;
bool pixState;
bool flag;
byte idx;

void setup() 
{
  pinMode(13,OUTPUT);
  digitalWrite(13,LOW);
  pinMode(pbswitch,INPUT_PULLUP);
 
  pixels.begin();
  pixels.clear();
  pixels.show();
  pixState = true;
  flag = false;
  pixels.setPixelColor(0, pixels.Color(20,0,0));
  pixels.setPixelColor(1, pixels.Color(0,20,0));
  pixels.setPixelColor(2, pixels.Color(0,0,10));
  
  pixels.show();
  Serial.begin(9600);
}
void loop() 
{
  if(flag == false)
  {
    // got a pb click
    checkpb();
    durationMarker = millis();
    intervalMarker = millis();
    capture = millis();
    idx = 0;
  }
  
  while((capture - durationMarker) < duration)
  {
    
    capture = millis();
    if((capture - intervalMarker) >= interval)
    {
      idx ++;
      if(idx == 3)
      {
        idx = 0;
      }
      Serial.println(idx);
      
      if(idx == 0)
      {
        pixels.setPixelColor(0, pixels.Color(20,0,0));
        pixels.setPixelColor(1, pixels.Color(0,20,0));
        pixels.setPixelColor(2, pixels.Color(0,0,10));
        pixels.show();
      }
      if(idx == 1)
      {
        pixels.setPixelColor(0, pixels.Color(0,0,10));
        pixels.setPixelColor(1, pixels.Color(20,0,0));
        pixels.setPixelColor(2, pixels.Color(0,20,0)); 
        pixels.show();
      }
      if(idx == 2)
      {
        pixels.setPixelColor(0, pixels.Color(0,20,0));
        pixels.setPixelColor(1, pixels.Color(0,0,10));
        pixels.setPixelColor(2, pixels.Color(20,0,0)); 
        pixels.show();
      }               
      intervalMarker = millis();
    }
  }
  flag = false;
  
}
void checkpb ()
{
  do
  {
    swState = digitalRead(pbswitch);
    digitalWrite(13,swState);
  }while(swState == 1);
  flag = true;
}

Hi,

Thank you for this! However, I feel as though I still don't really understand, sorry i'm extremely new to all this! I think I might just keep this as a separate programme first so whatever code does what I explain below that would be helpful. I think if I learn that first its better, then I'll move on to figuring out how to incorporate it into another programme.

I carried on working with the code I posted earlier and this is where I got to (see code below) - however, as soon as I release the button the LED the chase ends on stays on. I want the button to act more like a switch so the chase continues when the button is released and only turn off once the button is pushed again or the timer runs out (e.g. 3000 milliseconds).

Also is it possible to improve the flow to be a bit better (like this - number 2:red circle rotation 0:16: Arduino NeoPixel Ring 24 HSV Animations - YouTube) - I don't know if this is possible as my neopixel is only a 12 lights- but the fade would be a bonus (obviously across less leds)

I really appreciate the help!!

#include <Adafruit_NeoPixel.h>

#define LED_PIN    13
#define LED_COUNT 12

unsigned long flashInterval = 200;

int fwdState=0;

unsigned long currentMillis = 0;
unsigned long previousMillis = 0;
unsigned long counter=0;

const int buttonPin = 12;
int buttonState = 0;

Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);

void setup()
{
  Serial.begin(9600);
 
 
  strip.begin();
  strip.show();
  previousMillis = millis();

  strip.setBrightness(10); //adjust brightness here

   pinMode(buttonPin, INPUT_PULLUP);
}

Begin at the beginning.
Work that out with one LED and then "scale up".