Go Down

Topic: FastLED/NeoPixel examples that are non-blocking? (Read 2677 times) previous topic - next topic

felic

I have been looking at quite a few examples of the FastLED and NeoPixel library, but they all use make use the delay function a lot (a function that imo should have never been implemented). Causing me to be unable to run other code in the meantime. 

So I'm wondering if there are any good examples that are... let's call it non-blocking.

Riva

Neopixels require precise timing to work properly so any delays within the Neopixel libraries are probably needed but not delays within the main sketch code.
Tell us more details on what your wanting to do and maybe post the examples code your not happy with.
Don't PM me for help as I will ignore it.

felic

Yes, I get that. While the code is actually interacting with the strip, you can't do anything else.

But instead of
Code: [Select]
uint32_t red = strip.Color(255, 0, 0);

void loop() {
  colorWipe_stupid(red);
}

void colorWipe_stupid(uint32_t color) {
  static uint8_t wait = 50;
  for(uint16_t currentLed=0; currentLed<strip.numPixels(); currentLed++) {
    strip.setPixelColor(currentLed, color);
    strip.show();
    delay(50);
  }
}


You can easily write:
Code: [Select]
uint32_t red = strip.Color(255, 0, 0);

void loop() {
  colorWipe_smart(red);
}

void colorWipe_smart(uint32_t color) {
  static uint8_t wait = 50;
  static unsigned long lastUpdate = 0;
  static uint16_t currentLed = 0;
 
  unsigned long now = millis();
  if (now > lastUpdate+delay) {
    strip.setPixelColor(currentLed, color);
    strip.show();   
    currentLed = currentLed>strip.numPixels() ? 0 : currentLed+1;
    lastUpdate = now;
  }
}


And now all the time that would be wasted by delay() can be used for other things. For example another LED strip that should be change at the same time.

dgarcia42

Look in the FastLED example DemoReel100 - there's examples of using the macros EVERY_N_MILLISECONDS and EVERY_N_SECONDS to do what you want (which is, something every few milliseconds or seconds, without constantly calling delay).
--

FastLED (formerly FastSPI_LED) -- new home http://fastled.io

Grumpy_Mike

#4
Jul 13, 2016, 06:00 pm Last Edit: Jul 13, 2016, 06:03 pm by Grumpy_Mike
This is a version of the AdaFruit strand test that is non blocking and advances through the diffrent patterns at a push of a button.

Code: [Select]

// StrandTest from AdaFruit implemented as a state machine
// pattern change by push button
// By Mike Cook Jan 2016

#define PINforControl   7 // pin connected to the small NeoPixels strip
#define NUMPIXELS1      256 // number of LEDs on strip

#include <Adafruit_NeoPixel.h>
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUMPIXELS1, PINforControl, NEO_GRB + NEO_KHZ800);

unsigned long patternInterval = 20 ; // time between steps in the pattern
unsigned long lastUpdate = 0 ; // for millis() when last update occoured
unsigned long intervals [] = { 20, 20, 50, 100 } ; // speed for each pattern
const byte button = 2; // pin to connect button switch to between pin and ground

void setup() {
  strip.begin(); // This initializes the NeoPixel library.
  wipe(); // wipes the LED buffers
  pinMode(button, INPUT_PULLUP); // change pattern button
}

void loop() {
  static int pattern = 0, lastReading;
  int reading = digitalRead(button);
  if(lastReading == HIGH && reading == LOW){
    pattern++ ; // change pattern number
    if(pattern > 3) pattern = 0; // wrap round if too big
    patternInterval = intervals[pattern]; // set speed for this pattern
    wipe(); // clear out the buffer
    delay(50); // debounce delay
  }
  lastReading = reading; // save for next time

if(millis() - lastUpdate > patternInterval) updatePattern(pattern);
}

void  updatePattern(int pat){ // call the pattern currently being created
  switch(pat) {
    case 0:
        rainbow();
        break;
    case 1:
        rainbowCycle();
        break;
    case 2:
        theaterChaseRainbow();
        break;
    case 3:
         colorWipe(strip.Color(255, 0, 0)); // red
         break;     
  } 
}

void rainbow() { // modified from Adafruit example to make it a state machine
  static uint16_t j=0;
    for(int i=0; i<strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel((i+j) & 255));
    }
    strip.show();
     j++;
  if(j >= 256) j=0;
  lastUpdate = millis(); // time for next change to the display
 
}
void rainbowCycle() { // modified from Adafruit example to make it a state machine
  static uint16_t j=0;
    for(int i=0; i< strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
    }
    strip.show();
  j++;
  if(j >= 256*5) j=0;
  lastUpdate = millis(); // time for next change to the display
}

void theaterChaseRainbow() { // modified from Adafruit example to make it a state machine
  static int j=0, q = 0;
  static boolean on = true;
     if(on){
            for (int i=0; i < strip.numPixels(); i=i+3) {
                strip.setPixelColor(i+q, Wheel( (i+j) % 255));    //turn every third pixel on
             }
     }
      else {
           for (int i=0; i < strip.numPixels(); i=i+3) {
               strip.setPixelColor(i+q, 0);        //turn every third pixel off
                 }
      }
     on = !on; // toggel pixelse on or off for next time
      strip.show(); // display
      q++; // update the q variable
      if(q >=3 ){ // if it overflows reset it and update the J variable
        q=0;
        j++;
        if(j >= 256) j = 0;
      }
  lastUpdate = millis(); // time for next change to the display   
}

void colorWipe(uint32_t c) { // modified from Adafruit example to make it a state machine
  static int i =0;
    strip.setPixelColor(i, c);
    strip.show();
  i++;
  if(i >= strip.numPixels()){
    i = 0;
    wipe(); // blank out strip
  }
  lastUpdate = millis(); // time for next change to the display
}


void wipe(){ // clear all LEDs
     for(int i=0;i<strip.numPixels();i++){
       strip.setPixelColor(i, strip.Color(0,0,0));
       }
}

uint32_t Wheel(byte WheelPos) {
  WheelPos = 255 - WheelPos;
  if(WheelPos < 85) {
    return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  }
  if(WheelPos < 170) {
    WheelPos -= 85;
    return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
  WheelPos -= 170;
  return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}

SwinBreaux

This is a version of the AdaFruit strand test that is non blocking and advances through the diffrent patterns at a push of a button.

Thanks for this. I been looking for for this!
Completed Projects: rPi Kodi; RetroPi; rPi & Arduino Nano LED Strip Lighting
In progress: Security System; CarPi
Future: Home Automation; Weather Station; Info System w/Calendar; Drinko Bartender; Smoker/Meat Temp Monitor

INTP

Here's some non-blocking code I found

Code: [Select]
uint32_t red = strip.Color(255, 0, 0);

void loop() {
  colorWipe_smart(red);
}

void colorWipe_smart(uint32_t color) {
  static uint8_t wait = 50;
  static unsigned long lastUpdate = 0;
  static uint16_t currentLed = 0;
 
  unsigned long now = millis();
  if (now > lastUpdate+delay) {
    strip.setPixelColor(currentLed, color);
    strip.show();   
    currentLed = currentLed>strip.numPixels() ? 0 : currentLed+1;
    lastUpdate = now;
  }
}

oboeman123

Bringing a helpful thread back from the dead!  Mike you helped me out so much, however I do have a question.  When I modify your code to include more than 3 cases, why will it just freeze the state of case 3?  I have modified the if (pattern > 5) pattern = 0 to include the new cases but still nothing.  Thanks again!

PaulRB

Post your code!

Did you set up an interval for the new patterns, in the array on line 3?

oboeman123

Post your code!

Did you set up an interval for the new patterns, in the array on line 3?
That was my mistake.  Thank you.  You have no idea how much your post helped!

oboeman123

I am wondering if anyone has an example code to have a pixel fade from one color to another and then back in the same style as Paul?   I have looked at a tutorial that adafruit has for their Neopixels, however it seems to be in a different style.

PaulRB

#11
Sep 11, 2017, 08:45 am Last Edit: Sep 11, 2017, 08:48 am by PaulRB
Quote
in the same style as Paul?
Huh?

To fade from one colour to another, you could use map() function. Suppose you want to fade from colour (r1,g1,b1) to (r2,g2,b2) over time period t1 to t2. The formula for r at time t would be map(t,t1,t2,r1,r2). Similar for g and b.

oboeman123

#12
Sep 11, 2017, 05:28 pm Last Edit: Sep 11, 2017, 06:13 pm by oboeman123
Huh?
I am new to all of this (I am sure you can tell).  I guess the correct wording should have format, not style.  Thanks for the help, am I on the correct path?  I know I have not defined t.  Not sure exactly how to define it.

Code: [Select]
void RedtoGreen() {
  uint32_t R = strip.Color(255, 0, 0);
  uint32_t G = strip.Color(0, 255, 0);
  uint32_t B = strip.Color(0, 0, 255);
  
  R = map(t, 0, 1000, 255 ,0);
  G = map(t, 0, 1000, 0, 255);
  B = map(t, 0, 1000, 0, 0);
    
    strip.show();
}

PaulRB

I'm sorry, your code makes no sense at all. I thought you might need a little push in the right direction, apologies for misjudging your needs. Given that you will need much more detailed guidance, perhaps you could explain in more detail what it is you want to do, so we don't waste time creating something that doesn't do what you want. You say you want to fade between two colours, but which two, how will the colours be chosen?  Will just one pixel be doing this fade, or all of them? If just one, what will the others be doing?

oboeman123

I program large light shows at Christmas time so once I had a project idea I thought that I would be able to jump in and make it work.  I misjudged the complexity of this.  My project is a fiber optic hat that will cycle through looping sequences with a push button.  I am using 7 Neopixels and have taken your example from above with success.  My final wish would be to have the pixels fade between two colors until the button push.  I would prefer to have half color 1 to color 2, and the other half opposite.  If I could have the timing random between different pixels it would be ideal, however, I am sure that is much above my current level.  I appreciate the help so far and I apologize for not being super clear. 

Go Up