0

Colorwipe no delay
Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.

Colorwipe no delay

by Joe36 on Wed Apr 03, 2019 12:04 am

I am trying to have a strip perform a color wipe then color wipe back off and keep cycling fill red then fill black(off) I need this to happen with out using delays. I have some code but what I have just fills the strip with every other led off. then stays that way.



Code: Select all | TOGGLE FULL SIZE
#include <Adafruit_NeoPixel.h>

#define NUM_PIXELS 144
unsigned long interval=50;  // the time we need to wait
unsigned long previousMillis=0;

uint32_t currentColor;// current Color in case we need it
uint32_t currentColorB;
uint16_t currentPixel = 0;// what pixel are we operating on



Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_PIXELS, 7, NEO_GRB + NEO_KHZ800);

void setup() {
  currentColor = strip.Color(255,0,0);
  currentColorB = strip.Color(0,0,0);
  currentPixel = 0;
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'
}

// Basic idea. You could reorg and pass pixel index and color as a function - or you could go through a gradient of colors.
void loop(){
if ((unsigned long)(millis() - previousMillis) >= interval) {
  previousMillis = millis();
  colorWipe();
  colorWipeB();
 }
}


void colorWipe(){
  strip.setPixelColor(currentPixel,currentColor);
  strip.show();
  currentPixel++;
  if(currentPixel == NUM_PIXELS){
    currentPixel = 0;
}
}
void colorWipeB(){
  strip.setPixelColor(currentPixel,currentColorB);
  strip.show();
  currentPixel++;
  if(currentPixel == NUM_PIXELS){
    currentPixel = 0;
}
}


Joe36
 
Posts: 43
Joined: Tue Dec 27, 2016 10:36 am

Re: Colorwipe no delay

by kcl1s on Wed Apr 03, 2019 4:45 am

You will need to use millis to cycle through each colorwipe separately. Maybe set a flag variable for which color you are on. So declare bool colorFlag = true; at the top then something like this inside the millis. Change your flag when you set pixel back to 0 in the functions.
Code: Select all | TOGGLE FULL SIZE
if(colorFlag) {
  colorWipe();
}
else {
  colorWipeB;
}


Fellow hobbyist
Keith

kcl1s
 
Posts: 1289
Joined: Tue Aug 30, 2016 12:06 pm

Re: Colorwipe no delay

by Joe36 on Wed Apr 03, 2019 9:44 am

I added to the code and now it just colorwipes once in red. How do I change the flag from true to false and back?

Code: Select all | TOGGLE FULL SIZE
#include <Adafruit_NeoPixel.h>

#define NUM_PIXELS 144
unsigned long interval=50;  // the time we need to wait
unsigned long previousMillis=0;

uint32_t currentColor;// current Color in case we need it
uint32_t currentColorB;
uint16_t currentPixel = 0;// what pixel are we operating on

bool colorFlag = true;


Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_PIXELS, 7, NEO_GRB + NEO_KHZ800);

void setup() {
  currentColor = strip.Color(255,0,0);
  currentColorB = strip.Color(0,0,0);
  currentPixel = 0;
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'
}

// Basic idea. You could reorg and pass pixel index and color as a function - or you could go through a gradient of colors.
void loop(){
if ((unsigned long)(millis() - previousMillis) >= interval) {
  previousMillis = millis();

 
     if(colorFlag == true) {
  colorWipe();
}
else {
  colorWipeB;
}

 }
}







void colorWipe(){
  strip.setPixelColor(currentPixel,currentColor);
  strip.show();
  currentPixel++;
  if(currentPixel == NUM_PIXELS){
    currentPixel = 0;
}
}
void colorWipeB(){
  strip.setPixelColor(currentPixel,currentColorB);
  strip.show();
  currentPixel++;
  if(currentPixel == NUM_PIXELS){
    currentPixel = 0;
}
}


Joe36
 
Posts: 43
Joined: Tue Dec 27, 2016 10:36 am

Re: Colorwipe no delay

by kcl1s on Wed Apr 03, 2019 12:07 pm

Try this.
Code: Select all | TOGGLE FULL SIZE
#include <Adafruit_NeoPixel.h>

#define NUM_PIXELS 144
unsigned long interval = 50; // the time we need to wait
unsigned long previousMillis = 0;

uint32_t currentColor;// current Color in case we need it
uint32_t currentColorB;
uint16_t currentPixel = 0;// what pixel are we operating on

bool colorFlag = true;


Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_PIXELS, 7, NEO_GRB + NEO_KHZ800);

void setup() {
  currentColor = strip.Color(255, 0, 0);
  currentColorB = strip.Color(0, 0, 0);
  currentPixel = 0;
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'
}

// Basic idea. You could reorg and pass pixel index and color as a function - or you could go through a gradient of colors.
void loop() {
  if ((unsigned long)(millis() - previousMillis) >= interval) {
    previousMillis = millis();
    if (colorFlag == true) {
      colorWipe();
    }
    else {
      colorWipeB();
    }
  }
}

void colorWipe() {
  strip.setPixelColor(currentPixel, currentColor);
  strip.show();
  currentPixel++;
  if (currentPixel == NUM_PIXELS) {
    currentPixel = 0;
    colorFlag = false;
  }
}

void colorWipeB() {
  strip.setPixelColor(currentPixel, currentColorB);
  strip.show();
  currentPixel++;
  if (currentPixel == NUM_PIXELS) {
    currentPixel = 0;
    colorFlag = true;
  }
}



Keith

kcl1s
 
Posts: 1289
Joined: Tue Aug 30, 2016 12:06 pm

Re: Colorwipe no delay

by Joe36 on Wed Apr 03, 2019 4:29 pm

That worked, what was I missing?
Thank you.

Joe36
 
Posts: 43
Joined: Tue Dec 27, 2016 10:36 am

Re: Colorwipe no delay

by Joe36 on Wed Apr 03, 2019 5:33 pm

I see now what I was missing. its at the end of the colorwipe sections.

Joe36
 
Posts: 43
Joined: Tue Dec 27, 2016 10:36 am

Re: Colorwipe no delay

by Joe36 on Wed Apr 03, 2019 5:44 pm

Rather than having it loop I looked at having it fill then unfill back to the start of the strip, I made a change that I thought would work but it fulls to the end then back then just stops.
I changed the currentPixel to 144 for colorwipe then changed currentPixel--; for colorWipeB but that doesnt keep it looping for some reason.

Code: Select all | TOGGLE FULL SIZE
#include <Adafruit_NeoPixel.h>

#define NUM_PIXELS 144
unsigned long interval = 10; // the time we need to wait
unsigned long previousMillis = 0;

//uint32_t currentColor;// current Color in case we need it
//uint32_t currentColorB;
uint16_t currentPixel = 0;// what pixel are we operating on

bool colorFlag = true;


Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_PIXELS, 7, NEO_GRB + NEO_KHZ800);

void setup() {
//  currentColor = strip.Color(255, 0, 0);
 // currentColorB = strip.Color(0, 0, 0);
  currentPixel = 0;
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'
}

// Basic idea. You could reorg and pass pixel index and color as a function - or you could go through a gradient of colors.
void loop() {
  if ((unsigned long)(millis() - previousMillis) >= interval) {
    previousMillis = millis();
    if (colorFlag == true) {
      colorWipe();
    }
    else {
      colorWipeB();
    }
  }
}

void colorWipe() {

  strip.setPixelColor(currentPixel, 255, 0, 0);
  strip.setBrightness(255);
  strip.show();
  currentPixel++;
  if (currentPixel == NUM_PIXELS) {
    currentPixel = 144;
    colorFlag = false;
  }
}

void colorWipeB() {
  strip.setPixelColor(currentPixel, 0,0,0);
  strip.setBrightness(255);
  strip.show();
  currentPixel--;
  if (currentPixel == NUM_PIXELS) {
   
    currentPixel = 0;
    colorFlag = true;
  }
}


Joe36
 
Posts: 43
Joined: Tue Dec 27, 2016 10:36 am

Re: Colorwipe no delay

by Joe36 on Wed Apr 03, 2019 6:00 pm

I got it to work. I had to use greater than or equal to in colorWipeB. I attached the code in case anyone else needs it.




Code: Select all | TOGGLE FULL SIZE
//Colorwipe no delay forward then back.
#include <Adafruit_NeoPixel.h>

#define NUM_PIXELS 144
unsigned long interval = 10; // the time we need to wait
unsigned long previousMillis = 0;

//uint32_t currentColor;// current Color in case we need it
//uint32_t currentColorB;
uint16_t currentPixel = 0;// what pixel are we operating on

bool colorFlag = true;


Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_PIXELS, 7, NEO_GRB + NEO_KHZ800);

void setup() {
//  currentColor = strip.Color(255, 0, 0);
 // currentColorB = strip.Color(0, 0, 0);
  currentPixel = 0;
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'
}

// Basic idea. You could reorg and pass pixel index and color as a function - or you could go through a gradient of colors.
void loop() {
  if ((unsigned long)(millis() - previousMillis) >= interval) {
    previousMillis = millis();
    if (colorFlag == true) {
      colorWipe();
    }
    else {
      colorWipeB();
    }
  }
}

void colorWipe() {

  strip.setPixelColor(currentPixel, 255, 0, 0);
  strip.setBrightness(255);
  strip.show();
  currentPixel++;
  if (currentPixel == NUM_PIXELS) {
    currentPixel = 144;
    colorFlag = false;
  }
}

void colorWipeB() {
  strip.setPixelColor(currentPixel, 0,0,0);
  strip.setBrightness(255);
  strip.show();
  currentPixel--;
  if (currentPixel >= NUM_PIXELS) {
   
    currentPixel = 0;
    colorFlag = true;
  }
}


Joe36
 
Posts: 43
Joined: Tue Dec 27, 2016 10:36 am

Re: Colorwipe no delay

by kcl1s on Wed Apr 03, 2019 9:41 pm

Yes you got it. Just have to think through what you want then use the coding tools available to make it work.

Keith

kcl1s
 
Posts: 1289
Joined: Tue Aug 30, 2016 12:06 pm

Re: Colorwipe no delay

by kcl1s on Wed Apr 03, 2019 10:05 pm

From the Neopixel Uberguide https://learn.adafruit.com/adafruit-neopixel-uberguide/arduino-library-use

setBrightness() was intended to be called once, in setup(), to limit the current/brightness of the LEDs throughout the life of the sketch. It is not intended as an animation effect itself! The operation of this function is “lossy” — it modifies the current pixel data in RAM, not in the show() call — in order to meet NeoPixels’ strict timing requirements. Certain animation effects are better served by leaving the brightness setting alone, modulating pixel brightness in your own sketch logic and redrawing the full strip with setPixel().


Better not to use it in your function.

Keith

kcl1s
 
Posts: 1289
Joined: Tue Aug 30, 2016 12:06 pm

Re: Colorwipe no delay

by kcl1s on Wed Apr 03, 2019 10:15 pm

If you are counting backwards currentPixel--; you should test for 0 in your if statement if (currentPixel < 0) { instead of this if (currentPixel >= NUM_PIXELS) { Not sure why it is working the way you have it coded.

Keith

kcl1s
 
Posts: 1289
Joined: Tue Aug 30, 2016 12:06 pm

Re: Colorwipe no delay

by Joe36 on Wed Apr 03, 2019 11:01 pm

I do have another project I am working on thats much larger and I asked about this because I am trying to implement it in my larger code and I don't want to ask for too much help all at once. I tried to add this section to my larger project and its laggy almost as if there's a delay, (maybe its the issues you have listed). Not sure if you seen my other post about the lamps on a utv or not but thats what I was trying to do. Maybe I will get on discord and see if someone can help me understand a little better. sometimes I just change things and see if it compiles and load it and check the results without understanding what I just did. I know a small amount but not enough to write my own code from scratch, and its also probably how I have weeks worth of trial and error in to what I have. I really appreciate the help. Thank you.

Joe36
 
Posts: 43
Joined: Tue Dec 27, 2016 10:36 am

Re: Colorwipe no delay

by kcl1s on Thu Apr 04, 2019 8:39 am

I saw that post when it went up.

All the frames looked a little much. I think your millis() loops will handle what you need on the fly. It will use less memory and it is what computers are good at.

I like the wipe without using delay you came up with here. You should be able to do all your operations that way.

I would be happy to help. The first thing you need to do is describe your project animations as clear as you can. Such as...
Are half the pixels involved in the turn signal? If less than half how many?
What is the color of each animation?
If stop and turn or running and turn what happens?
If hazard and turn what happens?
If hazard and stop what happens?

That info in words lays out the plan for the code.

Keith

kcl1s
 
Posts: 1289
Joined: Tue Aug 30, 2016 12:06 pm

Re: Colorwipe no delay

by Joe36 on Fri Apr 05, 2019 9:58 am

I believe the color wipe can be used for what I need. It would be laid out like this.
144 LED Strip
20 pixels on each end will be yellow turn signals. (255, 175, 0) from pixel 20 back to the first, then from pixel 124 to pixel 144.
one color wipe will need to be one forward and one will need to be in reverse as the turn signals need to sweep outward from the center of the strip.
The entire strip will be a red running light (30, 0, 0) when active
The entire strip will be a red stop light (255, 0, 0) when active

If running light is active and stop is applied then stop needs to override running light.
turn signals will need to function at all times. if stop and running lights are off then turns need to function only yellow.
if running light is active then turn signals need to function over the top of the red (30, 0, 0). so set base strip color then colorwipe 20 yellow?
Same with the stop, if applied then the base strip needs to be set (255, 0, 0) then colorwipe yellow again.
The last thing is hazard lights this can be a separate input or if both left and right turn can run at the same time this would also work.
If I cant get this to work then my last idea was to separate the strip of led's but I would rather not if I dont have to as I need to keep these water resistant in the silicone sheathing they come in.
I posted the code I have now with the color wipe as one turn signal. I did go in and clean up the set brightness and only have it in setup now.
Let me know your thoughts.
Thank you.




Code: Select all | TOGGLE FULL SIZE
//Rear lights.

#include <Adafruit_NeoPixel.h>
#define RUNNING_LIGHT 12
#define STOP          11 
#define LTURN         10
#define RTURN          9
#define HAZARD         8
#define LENGTH       144

Adafruit_NeoPixel strip = Adafruit_NeoPixel(LENGTH, 7, NEO_GRB + NEO_KHZ800);


const long    turnInterval = 30;
//const long    interval = 100;
unsigned long previousMillis = 0;
bool colorFlag = true;
int currentPixel = 124;// what pixel are we operating on

void setup() {
  currentPixel = 124;
  digitalWrite(RUNNING_LIGHT, HIGH);
  digitalWrite(HAZARD,        HIGH);
  digitalWrite(LTURN,         HIGH);
  digitalWrite(RTURN,         HIGH);
  digitalWrite(STOP,          HIGH);
  strip.setBrightness(255);
  strip.begin();
  strip.show();
 
 // pixels.begin(); // This initializes the NeoPixel library.
 // pixels.show(); // This sends the updated pixel color to the hardware.
     
}

void loop () {

unsigned long currentMillis = millis();   

//If all inputs are high then keep all leds off.
  if (digitalRead(RUNNING_LIGHT) == HIGH and digitalRead(STOP) == HIGH and digitalRead(HAZARD) == HIGH and digitalRead(RTURN) == HIGH and digitalRead(LTURN) == HIGH) {
    for ( int i = 0; i < LENGTH; i++)
      strip.setPixelColor(i, 0,0,0);
      strip.show();
  }
 
       
       
//

//Testing colorwipe section for turn signals.
if (digitalRead(RUNNING_LIGHT) == HIGH and digitalRead(STOP) == HIGH and digitalRead(HAZARD) == HIGH and digitalRead(RTURN) == LOW and digitalRead(LTURN) == HIGH){
             if (currentMillis - previousMillis >= turnInterval){
       previousMillis = currentMillis;
                       
 
if (colorFlag == true) {
      colorWipe();
    }
    else {
      colorWipeB();
    }
  }
}


//Stop Lights 
if (digitalRead(RUNNING_LIGHT) == HIGH and digitalRead(STOP) == LOW and digitalRead(HAZARD) == HIGH and digitalRead(RTURN) == HIGH and digitalRead(LTURN) == HIGH){
    for ( int i = 0; i < LENGTH; i++)
      strip.setPixelColor(i, 255,0,0);
      strip.show();
  }
//Running Lights
 if (digitalRead(RUNNING_LIGHT) == LOW and digitalRead(STOP) == HIGH and digitalRead(HAZARD) == HIGH and digitalRead(RTURN) == HIGH and digitalRead(LTURN) == HIGH){
    for ( int i = 0; i < LENGTH; i++)
      strip.setPixelColor(i, 30,0,0);
      strip.show();
  }
//Second instance of Stop to keep strip full bright while running light and stop are active.
if (digitalRead(RUNNING_LIGHT) == LOW and digitalRead(STOP) == LOW and digitalRead(HAZARD) == HIGH and digitalRead(RTURN) == HIGH and digitalRead(LTURN) == HIGH){
    for ( int i = 0; i < LENGTH; i++)
      strip.setPixelColor(i, 255,0,0);
      strip.show();
  }
}







void colorWipe() {
  strip.setPixelColor(currentPixel, 255, 175, 0);
  strip.show();
  currentPixel++;
  if (currentPixel == LENGTH) {
    currentPixel = 124;
    colorFlag = false;
  }
}

void colorWipeB() {
  strip.setPixelColor(currentPixel, 0,0,0);
  strip.show();
  currentPixel++;
  if (currentPixel == LENGTH) {
    currentPixel = 124;
    colorFlag = true;
  }
}


Joe36
 
Posts: 43
Joined: Tue Dec 27, 2016 10:36 am

Re: Colorwipe no delay

by kcl1s on Fri Apr 05, 2019 6:10 pm

Well it turns out that the millis was not really needed. I went at the problem with the off, running and stop colors as background fill colors for the whole strip, with the order of precedence you described. Then It runs the signal or hazard function as needed. Those functions increment the number of yellow pixels each time through the loop up to the 20 pixels then resets to 0 and repeats.

You can adjust the speed of the signals by adjusting the delay in loop. 30 looks good to me. I tested it on a shorter strip and it seemed to work as intended.

Code: Select all | TOGGLE FULL SIZE
//Include and Define things
#include <Adafruit_NeoPixel.h>
#define LTURN         10
#define RTURN          9
#define STOP          11
#define RUNNING_LIGHT 12
#define HAZARD         8
#define LENGTH       144
Adafruit_NeoPixel strip = Adafruit_NeoPixel(LENGTH, 5, NEO_GRB + NEO_KHZ800);

const uint32_t colorBlack = strip.Color(0, 0, 0);
const uint32_t colorRunning = strip.Color(30, 0, 0);
const uint32_t colorStop = strip.Color(255, 0, 0);
const uint32_t colorTurn = strip.Color(255, 175, 0);

const int LTurnIn = 19;
const int RTurnIn = 124;
const int turnPixels = 20;

uint32_t backColor = colorBlack;
byte LTurnCt = 0;
byte RTurnCt = 0;

void setup() {
  // put your setup code here, to run once:
  pinMode(LTURN, INPUT_PULLUP);
  pinMode(RTURN, INPUT_PULLUP);
  pinMode(STOP, INPUT_PULLUP);
  pinMode(RUNNING_LIGHT, INPUT_PULLUP);
  pinMode(HAZARD, INPUT_PULLUP);
  strip.begin();
  strip.show();
  Serial.begin(9600);
}

void loop() {
  // put your main code here, to run repeatedly:
  backColor = colorBlack;
  if (digitalRead(RUNNING_LIGHT) == LOW) backColor = colorRunning;
  if (digitalRead(STOP) == LOW) backColor = colorStop;
  for (int i = 0; i < LENGTH; i++) strip.setPixelColor(i, backColor);
  if (digitalRead(HAZARD) == LOW) hazardOn();
  else if (digitalRead(LTURN) == LOW) LSignal();
  else if (digitalRead(RTURN) == LOW) RSignal();
  else {
    Serial.print("else ");
    RTurnCt = 0;
    LTurnCt = 0;
    strip.show();
  }
  delay(30);
}

void LSignal() {
  for (int i = LTurnIn; i >= (LTurnIn - LTurnCt); i--) strip.setPixelColor(i, colorTurn);
  LTurnCt++;
  if (LTurnCt > turnPixels) LTurnCt = 0;
  strip.show();
}

void RSignal() {
  for (int i = RTurnIn; i <= (RTurnIn + RTurnCt); i++) strip.setPixelColor(i, colorTurn);
  RTurnCt++;
  if (RTurnCt > turnPixels) RTurnCt = 0;
  strip.show();
}

void hazardOn() {
  for (int i = LTurnIn; i >= (LTurnIn - LTurnCt); i--) strip.setPixelColor(i, colorTurn);
  LTurnCt++;
  if (LTurnCt > turnPixels) LTurnCt = 0;
  for (int i = RTurnIn; i <= (RTurnIn + RTurnCt); i++) strip.setPixelColor(i, colorTurn);
  RTurnCt++;
  if (RTurnCt > turnPixels) RTurnCt = 0;
  strip.show();
}



Let me know what you think

Keith

kcl1s
 
Posts: 1289
Joined: Tue Aug 30, 2016 12:06 pm

Please be positive and constructive with your questions and comments.