Neopixel strip control without delays

Hi. I have several effects on a Neopixel Strip. I want to trigger them with a push button.
First press -effect 1, Second press -effect 2 ..and so on. easy.
I have set them on a "switch case".
The push counter uses millis(). so do not stop the code. The simple code to control de pixels strip is this:

    for(int j =0; j<26;j++){
    tira.setPixelColor(j,0,0,255);
    tira.show();
delay(500);

Now the code blocks the counter so it does not switch between cases and the for loop does not work.

Is there a simple way to replace the delay(). ?
I have seen several topics here but..really confusing.

Thanks in advance.

1 Like

Post the entire code. If You think the error is limited to that snippet, don't ask... find out Yourself.

delay(500) kills the execution for half a second. Not strange if button pressings don't work.

Please

In the Arduino IDE, use Ctrl T or CMD T to format your code then copy the complete sketch.

Use the </> icon from the ‘reply menu’ to attach the copied sketch.

#include <Adafruit_NeoPixel.h>

Adafruit_NeoPixel tira = Adafruit_NeoPixel(14, 2, NEO_GRB + NEO_KHZ800);

int buttonState = 0;
int lastButtonState = 0;

int period = 50;
unsigned long time_now = 0;
unsigned long prevTime = 0;

const int  buttonPin = 4;

int var = 0;

void setup() {
  Serial.begin(9600);
  tira.begin();
  tira.show();
  tira.setBrightness(50);

  pinMode(13, OUTPUT);
  pinMode(buttonPin, INPUT_PULLUP);
}
void loop() {


  buttonState = digitalRead(buttonPin);
  if (buttonState != lastButtonState) {
    if (buttonState == LOW) {
      var++;

    } else {
    }
    time_now = millis();
    if (millis() < time_now + period) {
    }
  }
  lastButtonState = buttonState;

  switch (var) {
    case 1:
      for (int i = 0; i < 14; i++) {
        tira.setPixelColor(i, 255, 0, 0);
        tira.show();
        delay(500);
      }
      break;
    case 2:
      for (int i = 0; i < 14; i++) {
        tira.setPixelColor(i, 0, 255, 0);
        tira.show();
        delay(500);
      }
      break;
    case 3:
      for (int i = 0; i < 14; i++) {
        tira.setPixelColor(i, 0, 0, 255);
        tira.show();
        delay(500);
      }
      break;
  }


}

I just want to jump over the cases with a push button.


    if (millis() < time_now + period) {
    }

What do you think the above code does ?


What values can var be ?


Edit.
Move this inside the change in state condition, it just wastes time we’re it is now:

lastButtonState = buttonState;

Why this code? That else will be a NOP, No OPeration. The following lines are executed regardless of buttonState being low or high.

yeah , does not do nothing.... but I dont care about it. The code works if I delete the delay() on the switch cases. And that is the real problem. Without the delay there is no effect on the strip.

Yeah I can improve the first part of the code. I have test it with switch cases and serial.println

The real problem is the delay()

You should care.

Try these changes:

#include <Adafruit_NeoPixel.h>

Adafruit_NeoPixel tira = Adafruit_NeoPixel(14, 2, NEO_GRB + NEO_KHZ800);

bool flag                   = false;

const byte heartbeatLED     = 13;
const byte  buttonPin       = 4;

byte buttonState            = 0;
byte lastButtonState        = 0;
byte mState                 = 0;
byte iteration              = 0;

//timing stuff
unsigned long commonMillis;
unsigned long switchMillis;
unsigned long heartbeatMillis;

//*********************************************************************
void setup()
{
  Serial.begin(9600);
  tira.begin();
  tira.show();
  tira.setBrightness(50);


  pinMode(heartbeatLED, OUTPUT);

  pinMode(buttonPin, INPUT_PULLUP);
}

//*********************************************************************
void loop()
{
  //**********************************************
  //used to check for blocking code
  if (millis() - heartbeatMillis >= 500)
  {
    //restart the TIMER
    heartbeatMillis = millis();

    digitalWrite(heartbeatLED, !digitalRead(heartbeatLED));
    
  }

  //**********************************************
  //is it time to check the switches ?
  if (millis() - switchMillis >= 50)
  {
    //restart the TIMER
    switchMillis = millis();

    checkSwitches();
  }

  //**********************************************
  //state machine
  switch (mState)
  {
    //*******************
    case 0:
      //do nothing

      break;

    //*******************
    case 1:
      if (flag == true && millis() - commonMillis >= 500)
      {
        //restart the TIMER
        commonMillis = millis();

        //green
        tira.setPixelColor(iteration, 255, 0, 0);
        tira.show();

        //next LED
        iteration++;

        if (iteration > 13)
        {
          //we are finished now
          flag = false;
        }
      }

      break;

    //*******************
    case 2:
      if (flag == true && millis() - commonMillis >= 500)
      {
        //restart the TIMER
        commonMillis = millis();

        //green
        tira.setPixelColor(iteration, 0, 255, 0);
        tira.show();

        //next LED
        iteration++;

        if (iteration > 13)
        {
          //we are finished now
          flag = false;
        }
      }

      break;

    //*******************
    case 3:
      if (flag == true && millis() - commonMillis >= 500)
      {
        //restart the TIMER
        commonMillis = millis();

        //blue
        tira.setPixelColor(iteration, 0, 0, 255);
        tira.show();

        //next LED
        iteration++;

        if (iteration > 13)
        {
          //we are finished now
          flag = false;
        }
      }

      break;

  } //END of switch/case


} //END of loop()


//*********************************************************************
void checkSwitches()
{
  //**********************************************
  //has there been a change in state on the switch ?
  buttonState = digitalRead(buttonPin);

  if (lastButtonState != buttonState)
  {
    //update to the new state
    lastButtonState = buttonState;

    //is the switch closed?
    if (buttonState == LOW)
    {
      //clear all the LEDs
      clearLEDs();

      //select the machine state
      mState++;

      //limit the range
      if (mState > 3)
      {
        mState = 1;
      }

      //start with the first LED
      iteration = 0;

      //enable timing
      flag = true;

      //restart the TIMER
      commonMillis = millis();
    }

  } //END of   if(buttonState != lastButtonState)

} //END of   checkSwitches()


//*********************************************************************
void clearLEDs()
{
  //all LEDs to black
  for (byte x = 0; x < 14; x++)
  {
    tira.setPixelColor(x, 0, 0, 0);
  }

  tira.show();

} //END of clearLEDs()

!!! LarryD
Your code works fine!

I will try now for more cool effects.
Thank you very much!

But do you understand the what and why ?

I´m on it. Yes I like understand, not just copy and paste, that improve coding skills for other proyects.

Yeah but the first thing I did is gone like crazy to check it.

By the way your code is amzing explained with the comments

Thanks again

I have never used the Neopixel library, but the FastLED library has a delay function:
fastLED.delay (unsigned long ms)

Delay will call .show() constantly to drive the dithering engine.

LarryD.
I have tried it... but I can´t do anything but your code :pensive:

I want to make a very few very simple effects(no more than 4). Can you help me on it ?

What do you want to do ?

Would be nice these 3 effects.

1-Fade between 4 colors. Not going to black.
2- Moving pixel through fixed background. like the code you sent me, but keeping the no moving
pixels with a color.
3- Moving Rainbow.

Many thanks in advance. and many other thanks if you accept this mission. :sunglasses:

Pick one and we’ll try to make it happen.

2- Moving pixel through fixed background. like the code you sent me, but keeping the no moving
pixels with a color.

Just a bit more information.

We always need to explain exactly how things will look.

What will happen at the start, what delay is desired, how does it end or repeat.

This might be what you want but you really need to explain things fully to get yourself understood.

// Version    YY/MM/DD  Description
// 1.00       21/09/08  Running sketch
// 1.01       21/09/09  Added state 4, magenta LED goes back and forth
// 1.02       21/09/09  Made name changes to different variables, added comments

#include <Adafruit_NeoPixel.h>

#define CLOSED                LOW
#define numberOfPixels        14

Adafruit_NeoPixel tira = Adafruit_NeoPixel(numberOfPixels, 2, NEO_GRB + NEO_KHZ800);

bool flag                   = false; //'false' means the TIMER is disabled

//a 'char' has a range of +-128
char incDec                 = 1;     //(incement/decrement) this will be: 1 for up, -1 for down 
char pixelNumer             = 0;

const byte heartbeatLED     = 13;    //toggles ever 500ms
const byte buttonPin        = 4;
const byte maximumState     = 4;     //there are 4 states in the 'State Machine'

byte buttonState            = 0;
byte lastButtonState        = 0;
byte mState                 = 0;     //the current state the machine is in

//timing stuff
unsigned long commonMillis;
unsigned long switchMillis;
unsigned long heartbeatMillis;

//*********************************************************************
void setup()
{
  Serial.begin(9600);
  tira.begin();
  tira.show();
  tira.setBrightness(50);

  pinMode(heartbeatLED, OUTPUT);

  pinMode(buttonPin, INPUT_PULLUP);
}

//*********************************************************************
void loop()
{
  //**********************************************
  //used to check for blocking code
  if (millis() - heartbeatMillis >= 500)
  {
    //restart the TIMER
    heartbeatMillis = millis();

    //toggle the LED state
    digitalWrite(heartbeatLED, !digitalRead(heartbeatLED));

  }

  //**********************************************
  //is it time to check the switches ?
  if (millis() - switchMillis >= 50)
  {
    //restart the TIMER
    switchMillis = millis();

    checkSwitches();
  }

  //**********************************************
  //State Machine
  switch (mState)
  {
    //*******************
    case 0:
      //do nothing

      break;

    //*******************
    case 1:
      if (flag == true && millis() - commonMillis >= 500)
      {
        //restart the TIMER
        commonMillis = millis();

        //green
        tira.setPixelColor(pixelNumer, 255, 0, 0);
        tira.show();

        //next LED
        pixelNumer++;

        //are we finished ?
        if (pixelNumer > numberOfPixels - 1)
        {
          //we are finished now
          flag = false;
        }
      }

      break;

    //*******************
    case 2:
      if (flag == true && millis() - commonMillis >= 500)
      {
        //restart the TIMER
        commonMillis = millis();

        //green
        tira.setPixelColor(pixelNumer, 0, 255, 0);
        tira.show();

        //next LED
        pixelNumer++;

        //are we finished ?
        if (pixelNumer > numberOfPixels - 1)
        {
          //we are finished now
          flag = false;
        }
      }

      break;

    //*******************
    case 3:
      if (flag == true && millis() - commonMillis >= 500)
      {
        //restart the TIMER
        commonMillis = millis();

        //blue
        tira.setPixelColor(pixelNumer, 0, 0, 255);
        tira.show();

        //next LED
        pixelNumer++;

        //are we finished ?
        if (pixelNumer > numberOfPixels - 1)
        {
          //we are finished now
          flag = false;
        }
      }

      break;

    //*******************
    case 4:
      if (flag == true && millis() - commonMillis >= 100)
      {
        //restart the TIMER
        commonMillis = millis();

        //*************************
        //if we going up, we need to turn off the previous pixel
        if (pixelNumer != 0 && incDec == 1)
        {
          //turn off the preceeding pixel
          tira.setPixelColor(pixelNumer - 1, 0, 0, 0);
          tira.show();
        }

        //*************************
        //if we going down, we need to turn off the previous pixel
        if (incDec == -1)
        {
          //turn off the preceeding pixel
          tira.setPixelColor(pixelNumer + 1, 0, 0, 0);
          tira.show();
        }

        //magenta
        tira.setPixelColor(pixelNumer, 255, 0, 255);
        tira.show();

        //next pixel
        pixelNumer = pixelNumer + incDec;

        //*************************
        //have we reached the top most pixel ?
        if (pixelNumer > numberOfPixels - 1)
        {
          //readjust to the next pixel 
          pixelNumer = numberOfPixels - 2;

          //we will now be going down
          //toggle increment/decrement
          incDec = -1;
        }

        //*************************
        //have we reached the bottom most pixel ?
        if (pixelNumer < 0)
        {
          //readjust to the next pixel 
          pixelNumer = 1;

          //we will now be going up
          //toggle increment/decrement
          incDec = 1;
        }
      }

      break;

  } //END of switch/case


} //END of loop()


//*********************************************************************
void checkSwitches()
{
  //**********************************************
  //has there been a change in state on the switch ?
  buttonState = digitalRead(buttonPin);

  if (lastButtonState != buttonState)
  {
    //update to the new state
    lastButtonState = buttonState;

    //is the switch closed?
    if (buttonState == CLOSED)
    {
      //clear all the LEDs
      clearLEDs();

      //the state in the machine
      mState++;

      //limit the state range
      if (mState > maximumState)
      {
        //back to the begining
        mState = 1;
      }

      //start with the first LED
      pixelNumer = 0;

      //enable timing
      flag = true;

      //restart the TIMER
      commonMillis = millis();
    }

  } //END of   if(buttonState != lastButtonState)

} //END of   checkSwitches()


//*********************************************************************
void clearLEDs()
{
  //all LEDs to black
  for (byte x = 0; x < numberOfPixels; x++)
  {
    tira.setPixelColor(x, 0, 0, 0);
  }

  tira.show();

} //END of clearLEDs()

Yeah, I should explain it more. I thought the idea was clear and I can customize the parameters to my needs.
I'm gonna test now the code.

THX