0

XRAD'S non blocking neopixel fade with servo
Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.

XRAD'S non blocking neopixel fade with servo

by XRAD on Sat Mar 23, 2019 1:45 pm

For Trinket M0 props: Might be helpful to some . It does not change servo position and change the neopixel display at same time. But, there is functional single button state control of 'slow move' servo position, with three neopixel display actions and state control of interruptable neopixel fade. Might be good for a prop. I am using it in a part of my plasma engine. In the code, there are two versions. one is with clearPixels() function and the other is not using this function. the difference is that you can wipe over another color pixel vs clearing the pixels and then displaying the new color.

If you choose to use the clearPixels(), then you can use :
Code: Select all | TOGGLE FULL SIZE
uint32_t offColor = pixels.Color(100, 0, 55); //violet, the 'off' position color
uint32_t onColor = pixels.Color(55, 100, 0); //light green, the 'on' position color

which makes color selection easier...

If you choose to not use the clearPixels(), then you have to code the neopixel color directly into the loop and the setup.

short vid here:
https://www.youtube.com/watch?v=_CVM9LdnKnQ


with clearPixels():
Code: Select all | TOGGLE FULL SIZE
/*=======XRAD'S TrinketM0 Frankencode Neopixel button control neopixel
 * fade non-blocking with slow servo control....some base code from Grumpy Mike:
   https://forum.arduino.cc/index.php?topic=412232.0
   and:
   https://blog.adafruit.com/2013/08/30/adafruit-neopixel-uberguide/
   You can run the fade code without servo jitter, and interrupt fade
   at any time.
*/

#include <Adafruit_NeoPixel.h>
#include <Servo.h>

#define PIXELPIN      0 // pin connected to the small NeoPixels strip
#define NUMPIXELS    20 // number of LEDs on strip
#define BUTTON        3 // +3.3v to this pin triggers action
#define BRIGHTNESS  120 // set neopixel brightness(0-255)
#define DELAYVAL1    60 //  Delay to write the Adafruit_NeoPixel color
#define DELAYVAL2    10 //  Delay for servo write speed
#define POS1        150 //servo open position, my current SG90 servo does not like more than this
#define POS2         10 //servo closed position


Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIXELPIN, NEO_GRB + NEO_KHZ800);
Servo Servos;

int fadeStep = 0; // fade step variable
int buttonState = 0; // current button state
int lastButtonState = 0;
int pos;// servo pos variable

//I use these because easier for me to change color thoughout display
uint32_t offColor = pixels.Color(100, 0, 55); //violet, the 'off' position color
uint32_t onColor = pixels.Color(55, 100, 0); //light green, the 'on' position color

void fade(int blueStartValue, int blueEndValue, int totalSteps) {
  static float   blueIncrement;
  static float   blue;
  static boolean fadeUp = false;

  if (fadeStep == 0) { // initialise the colour and increments
    blue = blueStartValue;
    fadeUp = false;
    blueIncrement = (float)(blueEndValue - blueStartValue) / (float)totalSteps;
    fadeStep = 1; // next time the function is called start the fade
  }

  else { //  make a pixel display
    blue += blueIncrement;
    // set up the pixel buffer
    for (int i = 0; i < pixels.numPixels(); i++) {
      pixels.setPixelColor(i, pixels.Color( 0, 0, (int)blue));
    }
    pixels.show();
    fadeStep += 1; // go on to next step
    if (fadeStep >= totalSteps) { // finished fade
      if (fadeUp) { // finished fade up and back
        fadeStep = 0;
        return; //next call recalabrates the increments
      }
      // now fade back
      fadeUp = true;
      blueIncrement = -blueIncrement;
      fadeStep = 1; // don't calculate the increments again but start at first change
    }
  }
}

//clearing with pixels.show(); causes jitter, this does not
void clearPixels() { 
  for (int i = 0; i < pixels.numPixels(); i++) {
    pixels.setPixelColor(i, pixels.Color(0, 0, 0));
  }
}


void setup() {
  Serial.begin(9600);  // initialize serial communication
  pinMode(BUTTON, INPUT_PULLDOWN); //So I can use 3.3v to button then to BUTTON pin, built into chip
  pixels.begin();   //  initialize the NeoPixel library.
  clearPixels(); // clears the pixel buffers, need this step or servo jitter
  pixels.setBrightness(BRIGHTNESS);
  //starting color diplay, 'off' position
  for (int i = 0; i < NUMPIXELS; i++) {
    pixels.setPixelColor(i, offColor);// or use (i, pixels.Color(100, 0, 0)); // red
    pixels.show();
  }
  delay(100);
  Servos.attach(4); // add the servo
  Servos.write(POS2);  // servo move to close position
}


void loop() {
  // read the pushbutton input pin
  buttonState = digitalRead(BUTTON);
  if ((buttonState == LOW) && (lastButtonState == 1)) {
    fade(255, 0, 700); // fade blue
  }
  //compare the buttonState to its previous state
  //this code will run once when button pressed
  if (buttonState == HIGH) {   // button FIRST press
    delay (30); // Delay a little bit to avoid button bounce

    if (lastButtonState == 0) {
      clearPixels();//need to clear pixel set-up buffer on button press for no servo jitter
      Serial.print("(ON)Servo Move To:");
      Serial.println(POS1);
      Serial.println("COLORWIPE");
      //neopixels light up in one direction
      for (int i = 0; i < NUMPIXELS; i++) {
        pixels.setPixelColor(i,onColor);//or you can set as this (i, pixels.Color(0, 100, 0)); // green,
        //if you want to remove not use clearPixels(); and have one color overwrite the old color
        pixels.show(); // send data to neopix
        delay(DELAYVAL1);
      }
      for (int pos1 = (POS2); pos1 <= (POS1); pos1 += 1) { // 1 degree steps
        Servos.write(pos1);  // servo move to new position
        delay(DELAYVAL2);    // slow servo down in msec
      }
      lastButtonState = 1;
    }

    else if (lastButtonState == 1) {
      clearPixels();//need to clear buffer on button press for no servo jitter
      Serial.print("(OFF)Servo Move To:");
      Serial.println(POS2);
      Serial.println("COLORWIPE");
      //neopixels light up in opposite direction
      for (int i = NUMPIXELS; i > -1; i--) {
        pixels.setPixelColor(i, offColor) ;//or you can set as this (i, pixels.Color(100, 0, 0)); // red,
        //if you want to remove not use clearPixels(); and have one color overwrite the old color     
        pixels.show();
        delay(DELAYVAL1);
      }
      for (int pos = (POS1); pos >= (POS2); pos -= 1) { // 1 degree steps
        Servos.write(pos);  // servo move to new position
        delay(DELAYVAL2);   // slow servo down in msec
      }
      lastButtonState = 0;
    }
  }
}



without clearPixels() in the loop (I like this one better)

Code: Select all | TOGGLE FULL SIZE
/*=======XRAD'S TrinketM0 Frankencode Neopixel button control neopixel
 * fade non-blocking with slow servo control....some base code from Grumpy Mike:
   https://forum.arduino.cc/index.php?topic=412232.0
   and:
   https://blog.adafruit.com/2013/08/30/adafruit-neopixel-uberguide/
   You can run the fade code without servo jitter, and interrupt it
   at any time.
*/

#include <Adafruit_NeoPixel.h>
#include <Servo.h>

#define PIXELPIN      0 // pin connected to the small NeoPixels strip
#define NUMPIXELS    20 // number of LEDs on strip
#define BUTTON        3 // +3.3v to this pin triggers action
#define BRIGHTNESS  120 // set neopixel brightness(0-255)
#define DELAYVAL1    60 //  Delay to write the Adafruit_NeoPixel color
#define DELAYVAL2    10 //  Delay for servo write speed
#define POS1        150 //servo open position, my current SG90 servo does not like more than this
#define POS2         10 //servo closed position


Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIXELPIN, NEO_GRB + NEO_KHZ800);
Servo Servos;

int fadeStep = 0; // fade step variable
int buttonState = 0; // current button state
int lastButtonState = 0;
int pos;// servo pos variable


void fade(int blueStartValue, int blueEndValue, int totalSteps) {
  static float   blueIncrement;
  static float   blue;
  static boolean fadeUp = false;

  if (fadeStep == 0) { // initialise the colour and increments
    blue = blueStartValue;
    fadeUp = false;
    blueIncrement = (float)(blueEndValue - blueStartValue) / (float)totalSteps;
    fadeStep = 1; // next time the function is called start the fade
  }

  else { //  make a pixel display
    blue += blueIncrement;
    // set up the pixel buffer
    for (int i = 0; i < pixels.numPixels(); i++) {
      pixels.setPixelColor(i, pixels.Color( 0, 0, (int)blue));
    }
    pixels.show();
    fadeStep += 1; // go on to next step
    if (fadeStep >= totalSteps) { // finished fade
      if (fadeUp) { // finished fade up and back
        fadeStep = 0;
        return; //next call recalabrates the increments
      }
      // now fade back
      fadeUp = true;
      blueIncrement = -blueIncrement;
      fadeStep = 1; // don't calculate the increments again but start at first change
    }
  }
}

//clearing with pixels.show(); causes jitter, this does not
void clearPixels() { 
  for (int i = 0; i < pixels.numPixels(); i++) {
    pixels.setPixelColor(i, pixels.Color(0, 0, 0));
  }
}


void setup() {
  Serial.begin(9600);  // initialize serial communication
  pinMode(BUTTON, INPUT_PULLDOWN); //So I can use 3.3v to button then to BUTTON pin, built into chip
  pixels.begin();   //  initialize the NeoPixel library.
  clearPixels(); // clears the pixel buffers, need this step or servo jitter
  pixels.setBrightness(BRIGHTNESS);
  //starting color diplay, 'off' position
  for (int i = 0; i < NUMPIXELS; i++) {
    pixels.setPixelColor(i, pixels.Color(100, 0, 55)); // violet
    pixels.show();
  }
  delay(100);
  Servos.attach(4); // add the servo
  Servos.write(POS2);  // servo move to close position
}


void loop() {
  // read the pushbutton input pin
  buttonState = digitalRead(BUTTON);
  if ((buttonState == LOW) && (lastButtonState == 1)) {
    fade(255, 0, 700); // fade blue
  }
  //compare the buttonState to its previous state
  //this code will run once when button pressed
  if (buttonState == HIGH) {   // button FIRST press
    delay (30); // Delay a little bit to avoid button bounce

    if (lastButtonState == 0) {
      Serial.print("(ON)Servo Move To:");
      Serial.println(POS1);
      Serial.println("COLORWIPE");
      //neopixels light up in one direction
      for (int i = 0; i < NUMPIXELS; i++) {
        pixels.setPixelColor(i, pixels.Color(55, 100, 0)); //light green
        pixels.show(); // send data to neopix
        delay(DELAYVAL1);
      }
      for (int pos1 = (POS2); pos1 <= (POS1); pos1 += 1) { // 1 degree steps
        Servos.write(pos1);  // servo move to new position
        delay(DELAYVAL2);    // slow servo down in msec
      }
      lastButtonState = 1;
    }

    else if (lastButtonState == 1) {
      Serial.print("(OFF)Servo Move To:");
      Serial.println(POS2);
      Serial.println("COLORWIPE");
      //neopixels light up in opposite direction
      for (int i = NUMPIXELS; i > -1; i--) {
        pixels.setPixelColor(i, pixels.Color(100, 0, 55));
        pixels.show();
        delay(DELAYVAL1);
      }
      for (int pos = (POS1); pos >= (POS2); pos -= 1) { // 1 degree steps
        Servos.write(pos);  // servo move to new position
        delay(DELAYVAL2);   // slow servo down in msec
      }
      lastButtonState = 0;
    }
  }
}

XRAD
 
Posts: 532
Joined: Sat Nov 19, 2016 3:28 pm

Please be positive and constructive with your questions and comments.