Long delays in program, how to avoid them ? [Arduino + NeoPixel]

Hi,

I currently making project - Custom Pc lightning. U using Arduino Leonardo + USB Serial Stream.

Here’s my Arduino code:

    #include <Adafruit_NeoPixel.h>
    #include <Wire.h>
    #include "Adafruit_LEDBackpack.h"
    #include "Adafruit_GFX.h"

    //BLYNK
    #include <SoftwareSerial.h>
    SoftwareSerial DebugSerial(4, 5); // RX, TX
    #define BLYNK_PRINT DebugSerial
    #include <BlynkSimpleStream.h>

    char auth[] = "*****";

    #define STRIP1LEN 19
    #define STRIP2LEN 19
    #define STRIP3LEN 11

    #define STRIP1 2
    #define STRIP2 9
    #define STRIP3 8

    Adafruit_NeoPixel strip1 = Adafruit_NeoPixel(STRIP1LEN, STRIP1, NEO_GRB + NEO_KHZ800);
    Adafruit_NeoPixel strip2 = Adafruit_NeoPixel(STRIP2LEN, STRIP2, NEO_GRB + NEO_KHZ800);
    Adafruit_NeoPixel strip3 = Adafruit_NeoPixel(STRIP3LEN, STRIP3, NEO_GRB + NEO_KHZ800);

    int brightness = 250;

    String text = "Hello world!!!";
    int brightnessLVL = 13;
    int lightMode = 1;
    String freeval = "";
    int spee = 25;

    int r = 24 ;
    int g = 107;
    int b = 0;
    int r2 = 255;
    int g2 = 255;
    int b2 = 255;

    //================= LED COLORS ======================

    uint32_t RED;
    uint32_t WHITE;
    uint32_t BLUE;
    uint32_t GREEN;

    void setup() {

      Serial.begin(9600);

      //================= LED STRIPS ======================
      strip1.begin();
      strip1.show(); // Initialize all pixels to 'off'
      strip2.begin();
      strip2.show(); // Initialize all pixels to 'off'
      strip3.begin();
      strip3.show(); // Initialize all pixels to 'off'

      strip1.setBrightness(brightness);
      strip2.setBrightness(brightness);
      strip3.setBrightness(brightness);

      RED = strip1.Color(255, 0, 0);
      WHITE = strip1.Color(255, 255, 255);
      BLUE = strip1.Color(0, 0, 255);
      GREEN = strip1.Color(0, 255, 0);

      //================= BLYNK  ======================
      DebugSerial.begin(9600);
      Blynk.begin(auth, Serial);
      
      setbrightnessLVL(250);
      setLightMode();
    }

    //================= MAIN LOOP  ======================

    void loop() {
      Blynk.run();
      setLightMode();
    }

    BLYNK_CONNECTED() {
        Blynk.syncAll();
    }

    BLYNK_WRITE(V1) {
      lightMode = param.asInt();
    }

    BLYNK_WRITE(V2) {
      
      // prevent changing parameters when doing 'long' loops
      if ( lightMode != 2 || lightMode != 3 || lightMode != 4 ) {
        r = param[0].asInt();
        g = param[1].asInt();
        b = param[2].asInt();
      }
    }

    BLYNK_WRITE(V3) {
      // prevent changing parameters when doing 'long' loops
      if ( lightMode != 2 || lightMode != 3 || lightMode != 4 ) {
        r2 = param[0].asInt();
        g2 = param[1].asInt();
        b2 = param[2].asInt();
      }
    }

    BLYNK_WRITE(V4) {
      // prevent changing parameters when doing 'long' loops
      if ( lightMode != 2 || lightMode != 3 || lightMode != 4 ) {
        int val = param.asInt();
        setbrightnessLVL(val);
      }
    }

    BLYNK_WRITE(V5) {
      // prevent changing parameters when doing 'long' loops
      if ( lightMode != 2 || lightMode != 3 || lightMode != 4 ) {
        spee = param.asInt();
      }
    }

    void setLightMode(){
      switch (lightMode) {
        case 1:
          stripsOff();
          break;
        case 2:
          rainbowCycle(spee/5);
          break;
        case 3:
          rainbowSingleColor(spee);
          break;
        case 4:
          stripOff(strip3);
          singlePixel( spee );
          break;
        case 5:
          singleColor(r, g , b);
          break;
        case 6:
          twoColors(strip1.Color(r, g, b), strip1.Color(r2, g2, b2));
          break;
        default:
          stripsOff();
          break;
      }
    }

    void setbrightnessLVL(int bright){
      strip1.setBrightness(bright);
      strip2.setBrightness(bright);
      strip3.setBrightness(bright);
    }

    //================= MODES  ======================

    void rainbowCircle(uint8_t wait) {
      uint16_t i, j;

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

    void rainbowCycle(uint8_t wait) {
      uint16_t i, j;

      for (j=0; j<256*1; j++) {
        for(i=0; i < strip1.numPixels(); i++) {
          uint32_t col = Wheel( ( (i * 256 / strip1.numPixels() ) + j ) & 255);
          strip1.setPixelColor(i, col);
          strip2.setPixelColor(i, col);
          strip3.setPixelColor(i, col);
        }
        uDelay(wait);
        strip1.show();
        strip2.show();
        strip3.show();
      }
    }

    void rainbowSingleColor(uint8_t wait) {
      uint16_t i, j;
      
       for(j=0; j<256*1; j++) {
        for(i=0; i<strip1.numPixels(); i++) {
          strip1.setPixelColor(i, Wheel((i+j) & 255));
          strip2.setPixelColor(i, Wheel((i+j) & 255));
          strip3.setPixelColor(i, Wheel((i+j) & 255));
        }
        uDelay(wait);
        strip1.show();
        strip2.show();
        strip3.show();
      }
    }

    void singlePixel(uint8_t wait) {

      strip2.show();
      for(uint16_t i=0; i <= strip2.numPixels(); i++) {
        strip2.setPixelColor(i, strip1.Color(r, g, b));

        strip2.setPixelColor(i-1, strip1.Color( 0, 0, 0));
        strip2.show();
        delay(wait);
      }
      strip2.show();

      strip1.show();
      for(uint16_t i = strip1.numPixels(); i != 0 ; i--) {
        strip1.setPixelColor(i,  strip1.Color( 0, 0, 0));

        strip1.setPixelColor(i-1, strip1.Color(r, g, b));
        strip1.show();
        delay(wait);
      }
      strip1.setPixelColor(0, strip1.Color( 0, 0, 0));
      strip1.show();
    }

    void singleColor(int r, int g, int b) {
      for (int i = 0; i < strip1.numPixels(); i++) {
        strip1.setPixelColor( i, strip1.Color(r, g, b) );
        strip2.setPixelColor( i, strip1.Color(r, g, b) );
        strip3.setPixelColor( i, strip1.Color(r, g, b) );
      }

      strip1.show();
      strip2.show();
      strip3.show();
      delay(60);
    }

    //Theatre-style crawling lights.
    void theaterChase(uint32_t c, uint8_t wait) {
      for (int j=0; j<10; j++) {  //do 10 cycles of chasing
        for (int q=0; q < 3; q++) {
          for (int i=0; i < strip1.numPixels(); i=i+3) {
            strip1.setPixelColor(i+q, c);    //turn every third pixel on
          }
          strip1.show();
          for (int i=0; i < strip2.numPixels(); i=i+3) {
            strip2.setPixelColor(i+q, c);    //turn every third pixel on
          }
          strip2.show();
          uDelay(wait);

          for (int i=0; i < strip1.numPixels(); i=i+3) {
            strip1.setPixelColor(i+q, 0);        //turn every third pixel off
          }

          for (int i=0; i < strip2.numPixels(); i=i+3) {
            strip2.setPixelColor(i+q, 0);        //turn every third pixel off
          }
        }
      }
    }

    void colorSwitch(uint32_t Color1, uint32_t Color2, uint8_t wait) {
      int i,j;
      for(j =0; j < 2 ; j++) {
        for (i = 0; i < strip1.numPixels(); i++) {
          if ( (i + j) % 2 == 0) {
            strip1.setPixelColor(i, Color1);
            strip2.setPixelColor(i, Color1);
            strip3.setPixelColor(i, Color1);
          } 
          else {
            strip1.setPixelColor(i, Color2);
            strip2.setPixelColor(i, Color2);
            strip3.setPixelColor(i, Color2);
          }
          strip1.show();
          strip2.show();
          strip3.show();
        }
        delay(wait * 6); //skalar

      }
    }

    void stripOff(Adafruit_NeoPixel strip) { 
      for(int i = 0; i < strip.numPixels(); i++) {
        strip.setPixelColor(i, strip1.Color( 0, 0, 0));
        uDelay(1);
      }
      strip.show();
    }

    void stripsOff() {
      uint16_t i, j;

      for(i=0; i < strip1.numPixels(); i++) {
        strip1.setPixelColor(i, strip1.Color( 0, 0, 0));
        strip2.setPixelColor(i, strip1.Color( 0, 0, 0));
        strip3.setPixelColor(i, strip1.Color( 0, 0, 0));
      }
      uDelay(20);
      strip1.show();
      strip2.show();
      strip3.show();
    }

    //Theatre-style crawling lights with rainbow effect
    void theaterChaseRainbow(Adafruit_NeoPixel strip, uint8_t wait) {
      for (int j=0; j < 256; j++) {     // cycle all 256 colors in the wheel
        for (int q=0; q < 3; q++) {
          for (int i=0; i < strip.numPixels(); i=i+3) {
            strip.setPixelColor(i+q, Wheel( (i+j) % 255));    //turn every third pixel on
          }
          strip.show();
          delay(wait);
        }
      }
    }

    void twoColors(uint32_t Color1, uint32_t Color2) {

      int TotalSteps = strip1.numPixels();
      for (int Index = 0; Index < TotalSteps; Index++) {
        uint8_t red = ((Red(Color1) * (TotalSteps - Index)) + (Red(Color2) * Index)) / TotalSteps;
        uint8_t green = ((Green(Color1) * (TotalSteps - Index)) + (Green(Color2) * Index)) / TotalSteps;
        uint8_t blue = ((Blue(Color1) * (TotalSteps - Index)) + (Blue(Color2) * Index)) / TotalSteps;
        strip1.setPixelColor(Index, strip1.Color(red, green, blue));
        strip2.setPixelColor(Index, strip1.Color(red, green, blue));
        strip3.setPixelColor(Index, strip1.Color(red, green, blue));
      }
      strip1.show();
      strip2.show(); 
      strip3.show();
      delay(20);
    }

    //================= OTHER  ======================

    void uDelay(int waitTime) {
      unsigned long  startTime = micros();
      unsigned long delayTime = waitTime * 1000;
      unsigned long count = 0;
      
      while ( micros() - startTime < delayTime) {
        count++;
      }
    }

    uint8_t Red(uint32_t color) {
      return (color >> 16) & 0xFF;
    }
    uint8_t Green(uint32_t color){
      return (color >> 8) & 0xFF;
    }
    uint8_t Blue(uint32_t color){
      return color & 0xFF;
    }

    // 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 strip1.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
      } 
      else if(WheelPos < 170) {
        WheelPos -= 85;
        return strip1.Color(255 - WheelPos * 3, 0, WheelPos * 3);
      } 
      else {
        WheelPos -= 170;
        return strip1.Color(0, WheelPos * 3, 255 - WheelPos * 3);
      }
    }

The main problem is receiving data from app when Arduino is running functions like: rainbowCycle() or rainbowSingleColor(). I know that I should avoid use delay(), but it’s necessary to slow down animation. I made custom uDelay function (there may function to receive and update values).

I dont know how to change well ‘shared’ variables like ‘lightMode’. Sometimes when app calls BLYNK_WRITE(V1), lightMode shoud be changed to new value, so in next call setLightMode() in main loop program should enter to correct case but it doesn’t.

How to start fixing my problem ?

Use the FastLED library. It has a non-blocking delay built in and is somewhat easier to configure than Neopixels Library.

1 Like

Hello,

sometimes i make a function called Blynk_Delay, here’s an example:

void Blynk_Delay(int milli){
    int end = millis() + milli;
    while(millis() < end){
       Blynk.run();
    }
}

Hope that helps

@patryk0493 remove auth token and replace with *****

I just finished writing version with FastLED instead Neopixel. I deleted unnecessary modes functions. I didnt use any delay() function.

Functions rainbowSingleColor() looks like strobe, here I limited loops quantity to 64, but it isn’t solution.

Here’s code:

#include <Wire.h>
#include "FastLED.h"
#include <OneWire.h>
#include <DallasTemperature.h>
#include <SimpleTimer.h> 
#include <BlynkSimpleStream.h>
#include <SoftwareSerial.h>
SoftwareSerial DebugSerial(4, 5); // RX, TX

char auth[] = "************";

int photoPin = A6;
int photoVal = 0;
SimpleTimer timer;

#define ONE_WIRE_BUS 3
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

#define STRIP1LEN 19
#define STRIP2LEN 19
#define STRIP3LEN 11

#define STRIP1 2
#define STRIP2 9
#define STRIP3 8

CRGB strip1[STRIP1LEN];
CRGB strip2[STRIP2LEN];
CRGB strip3[STRIP3LEN];

int brightness = 250;

int lightMode = 1;
int spee = 25;

int r = 24 ;
int g = 107;
int b = 0;
int r2 = 255;
int g2 = 255;
int b2 = 255;

int hue = 0;

void setup() {

  Serial.begin(9600);

  pinMode(photoPin, INPUT);
  sensors.begin();
  sensors.requestTemperatures();
  
  //================= LED STRIPS ======================
  delay(2000);
  
  FastLED.addLeds<NEOPIXEL, STRIP1>(strip1, STRIP1LEN);
  FastLED.addLeds<NEOPIXEL, STRIP2>(strip2, STRIP2LEN);
  FastLED.addLeds<NEOPIXEL, STRIP3>(strip3, STRIP3LEN);
  
  FastLED.setBrightness(brightness);
  
  //================= BLYNK  ======================
  DebugSerial.begin(9600);
  Blynk.begin(auth, Serial);
  
  FastLED.setBrightness(255);
  setLightMode();
  
  
  timer.setInterval(80L, updateHue);
  timer.setInterval(500L, sendPhoto);
  //timer.setInterval(5000L, sendTemp);
}

//================= BLYNK FUNCTIONS  ======================

void sendPhoto(){
  photoVal = analogRead(photoPin);
  Blynk.virtualWrite(V15, photoVal);
}

void sendTemp(){
  Blynk.virtualWrite(V16, sensors.getTempCByIndex(0));
  sensors.requestTemperatures();
}

void updateHue(){
  hue++;
}

//================= MAIN LOOP  ======================

void loop() {
  Blynk.run();
  setLightMode();
  timer.run();
}

//================= BLYNK FUNCTIONS  ======================

BLYNK_CONNECTED() {
    Blynk.syncAll();
}

BLYNK_WRITE(V1) {
  lightMode = param.asInt();
}

BLYNK_WRITE(V2) {
  r = param[0].asInt();
  g = param[1].asInt();
  b = param[2].asInt();
}

BLYNK_WRITE(V3) {
  r2 = param[0].asInt();
  g2 = param[1].asInt();
  b2 = param[2].asInt();
}

BLYNK_WRITE(V4) {
  int val = param.asInt();
  FastLED.setBrightness(val);
}

BLYNK_WRITE(V5) {
  spee = param.asInt();
}

//================= SET MODE  ======================

void setLightMode(){
  switch (lightMode) {
    case 1:
      stripsOff();
      break;
    case 2:
      rainbowCycle(spee/5);
      break;
    case 3:
      rainbowSingleColor(spee);
      break;
    case 4:
      stripOff(strip3);
      singlePixel( spee );
      break;
    case 5:
      singleColor(r, g , b);
      break;
    case 6:
      twoColors(r, g, b, r2, g2, b2);
      break;
    case 7:
      juggle();
      break;
    case 8:
      bpm();
      break;
    default:
      stripsOff();
      break;
  }
}

//================= MODES  ======================

void rainbowCycle(uint8_t wait) {
  fill_rainbow(strip1, 19, 0, 13);
  fill_rainbow(strip2, 19, 0, 13);
  fill_rainbow(strip3, 19, 0, 13);
  FastLED.show();
  
}

void juggle() {
  // eight colored dots, weaving in and out of sync with each other
  fadeToBlackBy( strip1, STRIP1LEN, 20);
  fadeToBlackBy( strip2, STRIP1LEN, 20);
  fadeToBlackBy( strip3, STRIP1LEN, 20);
  byte dothue = 0;
  for( int i = 0; i < 8; i++) {
    strip1[beatsin16(i+7, 0, STRIP1LEN)] |= CHSV(dothue, 255, 255);
    strip2[beatsin16(i+7, 0, STRIP1LEN)] |= CHSV(dothue, 255, 255);
    strip3[beatsin16(i+7, 0, STRIP1LEN)] |= CHSV(dothue, 255, 255);
    dothue += 32;
  }
  FastLED.show();
}

void bpm() {
  // colored stripes pulsing at a defined Beats-Per-Minute (BPM)
  uint8_t BeatsPerMinute = 602;
  CRGBPalette16 palette = PartyColors_p;
  uint8_t beat = beatsin8( BeatsPerMinute, 64, 255);
  for( int i = 0; i < STRIP1LEN; i++) { //9948
    strip1[i] = ColorFromPalette(palette, hue+(i*2), beat-hue+(i*10));
    strip2[i] = ColorFromPalette(palette, hue+(i*2), beat-hue+(i*10));
    strip3[i] = ColorFromPalette(palette, hue+(i*2), beat-hue+(i*10));
  }
  FastLED.show();
}

void rainbowSingleColor(uint8_t wait) {
  int j;
  for(j=0; j<64; j++) {
    FastLED.showColor(CHSV(j*4, 255, 255));
  }
}

void singlePixel(uint8_t wait) {
  for(int whiteLed = 0; whiteLed < STRIP1LEN; ++whiteLed) {
    strip1[whiteLed] = CRGB::White;
    strip2[whiteLed] = CRGB::White;
    FastLED.show();
    strip1[whiteLed] = CRGB::Black;
    strip2[whiteLed] = CRGB::Black;
  }
}

void singleColor(int r, int g, int b) {
  FastLED.showColor(CRGB(r, g, b));
}

void stripOff(CRGB strip[]) { 
  fill_solid( &(strip[0]), STRIP1LEN, CRGB( 0, 0, 0) );
  FastLED.show();
}

void stripsOff() {
  FastLED.showColor(CRGB(0, 0, 0));
}

void twoColors(int _cr, int _cg, int _cb, int _cr2, int _cg2, int _cb2) {
    fill_gradient_RGB(strip1, STRIP1LEN, CRGB(_cr, _cg, _cb), CRGB(_cr2, _cg2, _cb2)); 
    fill_gradient_RGB(strip2, STRIP1LEN, CRGB(_cr, _cg, _cb), CRGB(_cr2, _cg2, _cb2));
    fill_gradient_RGB(strip3, STRIP1LEN, CRGB(_cr, _cg, _cb), CRGB(_cr2, _cg2, _cb2)); 
    FastLED.show();
}

//================= OTHER  ======================

CRGB Wheel(byte WheelPos) {
  if(WheelPos < 85) {
    return CRGB( WheelPos * 3, 2255 - WheelPos * 3, 0);
  } 
  else if(WheelPos < 170) {
    WheelPos -= 85;
    return CRGB(255 - WheelPos * 3, 0, WheelPos * 3);
  } else {
    WheelPos -= 170;
    return CRGB(0, WheelPos * 3, 255 - WheelPos * 3);
  }
}

@FunguyPro I tried to replace my function with yours- program is hanging.

I made timer who calls ‘updateHue()’ every 80ms to increase variable ‘hue’, but it not working properly - it’s increasing for few seconds, stuck for example on 180, when I change light mode it’s set to 18032 or another random number. When I commented ‘hue++’ it’s still changing, but only send it by ‘Blynk.virtualWrite(V16, hue);’ to check current value.

Really I don’t know whats going on with my code.

Replace updateHuE() with

EVERY_N_MILLISECONDS( 8 ) {
      hue++;

in the loop.

So, I fixed my problem by:

  1. Replacing all Neopixel library code by Fastled

  2. Use this code for timer:

    EVERY_N_MILLISECONDS( 8 ) {
    hue++;
    }
    For long long animations I using methods like beat8() or beatsin16() from Fastled lib

Hi,

I tried using Blynk_Delay. Now I can change color and so on while rainbow is running by pushing a different button in Blynk. But when releasing the button rainbow is still running. So this is not really working.

Before changing everything to FastLED library I like to try this.

My code: Neopixel ring with Particle Photon via Blynk Raw

Any ideas?