Go Down

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

PaulRB

Good. So you want to use Mike's code and add this new 2-colour fade pattern? You want each of the 7 pixels to fade between two colours art random intervals. What would be the slowest and fastest interval, in seconds?  How are the colours chosen? Do all pixels use the same two colours?

Grumpy_Mike

If you want to fade between two colours you first need to know how many steps you want to use call it numberOfSteps. Then take the difference between each colour and divide it by the number of steps to get an increment. Their will be three increments one for each RGB. This will also need to be a floating point variable.

Then at each call of the state machine function add the increment value to the current colour at time intervals of your choosing until the number of steps has been made.

oboeman123

If you want to fade between two colours you first need to know how many steps you want to use call it numberOfSteps. Then take the difference between each colour and divide it by the number of steps to get an increment. Their will be three increments one for each RGB. This will also need to be a floating point variable.

Then at each call of the state machine function add the increment value to the current colour at time intervals of your choosing until the number of steps has been made.
I am kind of understanding what needs to be done.  I have found the following code and I think it does what you are saying.  Correct me if I am wrong, but what I have is a definition of Color 1 and 2 as well as each of the three colors.  The ColorSet is combining each of the 3 colors and defining the color?  How would I get the Red, Green, and Blue to be declared?  Thank you for helping, I am completely new and both you and Paul have been very patient and helpful.

Code: [Select]
void Fade(uint32_t color1, uint32_t color2, uint16_t steps, uint8_t interval)
    {

        Interval = interval;
        TotalSteps = steps;
        Color1 = color1;
        Color2 = color2;
        Index = 0;
        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;
        ColorSet(Color(red, green, blue));

        strip.show();
    }

Grumpy_Mike

Well not quite.
First off when ever you go:-  uint8_t you are defining a new variable so don't do that make them global variables or static ones.
Next I said make the increment value a float type, and have one for each of the colours, you haven't done that.
Next your value of index is always zero, it never changes. Make it a static variable and increment it on each entry.

The code to set up the fixed variables should be done when the index is zero and at no other time. It is probably best to use a separate setup function for this.
I don't understand what
Code: [Select]
Red(Color1)
does. Especially as the parameter passed to it is a long int, it doesn't make sense to me.

oboeman123

I think I might be at the point of diminishing returns.  I don't give up easily but I am way over my head.  I have no idea how to separate to each RGB increment.  I have looked up how to use float but do I use that for each R, G, & B?  I just have no idea even where to start now.  It seems with my limited experience that I start to understand but only to find out that I still am clueless. 

Grumpy_Mike

Quote
I have no idea how to separate to each RGB increment.
Code: [Select]

redIncrement = (redStartValue - redEndValue) / TotalSteps;
greenIncrement = (greenStartValue - greenEndValue) / TotalSteps;
blueIncrement = (blueStartValue - blueEndValue) / TotalSteps;

oboeman123

Am I on the right path?  Using your help this is what I think I did.  I defined 2 Colors and the steps.  The floating variable next with your help.  Finally telling what pixels and to start with Color 1 and then lighting the pixels.  Is my thinking correct? 

Code: [Select]
void fade(Color1, Color2, totalsteps) {
  TotalSteps = totalsteps;
  Color1 = (redStartValue, greenStartValue, blueStartValue);
  Color2 = (redEndValue, greenEndValue, blueEndValue);
 
  redIncrement = (redStartValue - redEndValue) / TotalSteps;
  greenIncrement = (greenStartValue - greenEndValue) / TotalSteps;
  blueIncrement = (blueStartValue - blueEndValue) / TotalSteps;

  for (int i = 0; i < strip.numPixels(); i++) {
  strip.setPixelColor(i, Color1);

  strip.show();
}
}

Grumpy_Mike

#22
Sep 13, 2017, 05:47 am Last Edit: Sep 13, 2017, 05:56 am by Grumpy_Mike
Quote
Is my thinking correct?  
Not too sure because there is quite a lot missing. You need a state machine type of function that makes one step in the fade each time it is called. So you need to have either global variables or static variables that the function uses. Something like this, but it is not tested:-

Code: [Select]

void fade(int redStartValue, int redEndValue, int greenStartValue, int greenEndValueint, int blueStartValue, int blueEndValue, int totalsteps) {
static float redIncrement, greenIncrement, blueIncrement;
static float red, green, blue;
static int step = 0;

if (step == 0){ // first step is to initialise the initial colour and increments
  red = redStartValue;
  green = greenStartValue;
  blue = blueStartValue;

  redIncrement = (float)(redStartValue - redEndValue) / (float)totalSteps;
  greenIncrement = (float)(greenStartValue - greenEndValue) / (float)totalSteps;
  blueIncrement = (float)(blueStartValue - blueEndValue) / (float)totalSteps;
  step = 1; // next time the function is called start the fade
}
else { // all other steps make a new colour and display it
  // make new colour
  red += redIncrement;
  green +=  greenIncrement;
  blue += blueIncrement;
 
  // set up the pixel buffer
  for (int i = 0; i < strip.numPixels(); i++) {
  strip.setPixelColor(i, strip.Color((int)red,(int)green,(int)blue));
  }
 // now display it
  strip.show();
step += 1; // go on to next step
if(step > totalSteps) step = 0; // start again
 }
}

oboeman123

That code works!  There is no way I could have even come close to that.  Feel free to just tell me to stop... but if I add another step, could I fade back to the original color? So at the end of the first else do something like

Code: [Select]
if(step > totalSteps) step = 2;

Then set up is if==2 and reverse the colors?  Thanks again for your help!

Grumpy_Mike

If you want to fade back to the original colours then in place of this:-
Code: [Select]
if(step > totalSteps) step = 0; // start again

You could use this, again not tested:-
Code: [Select]

if(step > totalSteps) {
  redIncrement = -redIncrement;
  greenIncrement = -greenIncrement;
  blueIncrement = -blueIncrement;

step = 1; // don't calculate the increments again but start at first change
}

By simply making the increments the negitave of what they were, you should be able to fade back to the the original colour.

Grumpy_Mike

#25
Sep 15, 2017, 11:45 am Last Edit: Sep 15, 2017, 11:46 am by Grumpy_Mike
OK I have now tested this and made a few changes to make it work better and stop the flash at the fade switch around. This is the complete sketch for the state machine function with the fade function added.

Code: [Select]


// StrandTest from AdaFruit implemented as a state machine
// pattern change by push button
// By Mike Cook Jan 2016
// Fade function added Sept 2017

#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, 30 } ; // speed for each pattern - add here when adding more cases
int fadeStep = 0; // stste variable for fade function
int numberOfCases = 4; // how many case statements or patterns you have
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 = 4, lastReading; // start with the fade function
  int reading = digitalRead(button);
  if(lastReading == HIGH && reading == LOW){
    pattern++ ; // change pattern number
    fadeStep = 0; // reset the fade state variable
    if(pattern > numberOfCases) 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;
        
    case 4:
         fade(0,255, 0,64, 0,0, 400); // fade from black to oraange and back
         break;                  
  }
}

void fade(int redStartValue, int redEndValue, int greenStartValue, int greenEndValue, int blueStartValue, int blueEndValue, int totalSteps) {
static float redIncrement, greenIncrement, blueIncrement;
static float red, green, blue;
static boolean fadeUp = false;

if (fadeStep == 0){ // first step is to initialise the initial colour and increments
  red = redStartValue;
  green = greenStartValue;
  blue = blueStartValue;
  fadeUp = false;

  redIncrement = (float)(redEndValue - redStartValue) / (float)totalSteps;
  greenIncrement = (float)(greenEndValue - greenStartValue) / (float)totalSteps;
  blueIncrement = (float)(blueEndValue - blueStartValue) / (float)totalSteps;
  fadeStep = 1; // next time the function is called start the fade
}
else { // all other steps make a new colour and display it
  // make new colour
  red += redIncrement;
  green +=  greenIncrement;
  blue += blueIncrement;
 
  // set up the pixel buffer
  for (int i = 0; i < strip.numPixels(); i++) {
  strip.setPixelColor(i, strip.Color((int)red,(int)green,(int)blue));
  }
 // now display it
  strip.show();
fadeStep += 1; // go on to next step
if(fadeStep >= totalSteps) { // finished fade
  if(fadeUp){ // finished fade up and back
     fadeStep = 0;
     return; // so next call recalabrates the increments
  }
  // now fade back
  fadeUp = true;
  redIncrement = -redIncrement;
  greenIncrement = -greenIncrement;
  blueIncrement = -blueIncrement;
  fadeStep = 1; // don't calculate the increments again but start at first change
}
 }
}

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);
}


oboeman123

Thanks Mike!  That code works perfect!  This has certainly been a learning experience.  Thanks for all your help.

Go Up