Go Down

Topic: LED strobe without delay for RC plane setup (Read 671 times) previous topic - next topic

itg123

Been trying to solve the problem of running an LED strobe pattern while also running a NeoPixel LED ring pattern for an rc airplane lighting setup. Iv read a ton and tried unsuccessfully to replace the delay with if else loops. Any and all help would be greatly appreciated.

Code: [Select]
#include <Adafruit_NeoPixel.h>
#include <FastLED.h>

#define NUM_LEDS_PER_STRIP 3
CRGB redLeds[NUM_LEDS_PER_STRIP];
CRGB greenLeds[NUM_LEDS_PER_STRIP];

Adafruit_NeoPixel strip = Adafruit_NeoPixel(16, 4, NEO_RGB + NEO_KHZ800);


void setup() {
 
  FastLED.addLeds<NEOPIXEL, 2>(redLeds, NUM_LEDS_PER_STRIP);
  FastLED.addLeds<NEOPIXEL, 3>(greenLeds, NUM_LEDS_PER_STRIP);
 
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'
}

void loop() {
  //trying to get this to run at the same time
  //{rainbowCycle(10);

  //trying to replace this section with if else loop or something better
   for(int i = 0; i < NUM_LEDS_PER_STRIP; i++) {
    // set our current dot to red, green, and blue
    redLeds[0] = CRGB::White;
    redLeds[1] = CRGB::Red;
    redLeds[2] = CRGB::Red;
    greenLeds[0] = CRGB::White;
    greenLeds[1] = CRGB::Green;
    greenLeds[2] = CRGB::Green;
   
    FastLED.show();
    delay(100);
   
    // clear our current dot before we move on
    redLeds[0] = CRGB::Black;
    greenLeds[0] = CRGB::Black;
    FastLED.show();
    delay(50);

    redLeds[0] = CRGB::White;
    greenLeds[0] = CRGB::White;
    FastLED.show();
    delay(50);
   
   
    // clear our current dot before we move on
    redLeds[0] = CRGB::Black;
    greenLeds[0] = CRGB::Black;
    FastLED.show();
    delay(1000);
  }
}




// Slightly different, this makes the rainbow equally distributed throughout
void rainbowCycle(uint8_t wait) {
  uint16_t i, j;

  for(j=0; j<256*1000000; j++) { // 5 cycles of all colors on wheel
    for(i=0; i< strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
    }
    strip.show();
    delay(wait);
  }
}

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


Thanks

UKHeliBob

Get rid of all the delay()s, particularly where they occur within a for loop, because they block operation of the program.  Instead use millis() for timing and keep loop() running freely.

Have you looked at Using millis() for timing.  A beginners guide,   Several things at the same time and look at the BlinkWithoutDelay example in the IDE.
Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

GypsumFantastic

Those fastled/neopixel demo patterns use a lot of blocking code besides delay(). Like this for loop:

Code: [Select]
for(j=0; j<256*1000000; j++) { // 5 cycles of all colors on wheel
    for(i=0; i< strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
    }
    strip.show();
    delay(wait);
  }


256*1000000 isn't going to fit into a uint16_t variable, btw.

itg123

Would either of you have a good example I could follow. Iv been trying what you both have suggested with little success.

Thanks for talking the time to help me out.

GypsumFantastic

Here's a thread with a few non-blocking neopixel display examples - you should be able to find a good routine for LED ring in there.

By the way, I don't think you need both the neopixel and fastLED libraries in your sketch. They both do the same thing.

itg123

Thanks for the help. Still working my way through most of this stuff. Ill give it a look over.

Blackfin

#6
Jan 06, 2019, 05:51 pm Last Edit: Jan 06, 2019, 05:52 pm by Blackfin
Give this a shot. It takes your code and makes smaller bites of each of the tasks, using millis() to time.

Compiled on a 2560 but not tested... YMMV.

Code: [Select]
#include <Adafruit_NeoPixel.h>
#include <FastLED.h>

#define NUM_LEDS_PER_STRIP 3
CRGB redLeds[NUM_LEDS_PER_STRIP];
CRGB greenLeds[NUM_LEDS_PER_STRIP];

uint32_t Wheel(byte WheelPos);

#define STRB_STATE_A    0
#define STRB_STATE_B    1
#define STRB_STATE_C    2
#define STRB_STATE_D    3
#define WAIT_TIME       10  //mS

Adafruit_NeoPixel strip = Adafruit_NeoPixel(16, 4, NEO_RGB + NEO_KHZ800);

void setup() {
 
  FastLED.addLeds<NEOPIXEL, 2>(redLeds, NUM_LEDS_PER_STRIP);
  FastLED.addLeds<NEOPIXEL, 3>(greenLeds, NUM_LEDS_PER_STRIP);
 
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'
}

void Strobes( void )
{
    static int
        strobeState = STRB_STATE_A;
    static unsigned long
        strobeTimer = millis();
    unsigned long
        timeNow;

    timeNow = millis();
    if( timeNow < strobeTimer )
        return;
       
    switch( strobeState )
    {
        case    STRB_STATE_A:
            redLeds[0] = CRGB::White;
            redLeds[1] = CRGB::Red;
            redLeds[2] = CRGB::Red;
            greenLeds[0] = CRGB::White;
            greenLeds[1] = CRGB::Green;
            greenLeds[2] = CRGB::Green;
   
            FastLED.show();
            strobeTimer = timeNow + 100;   //100mS
            strobeState = STRB_STATE_B;
        break;

        case    STRB_STATE_B:
            // clear our current dot before we move on
            redLeds[0] = CRGB::Black;
            greenLeds[0] = CRGB::Black;
            FastLED.show();
            strobeTimer = timeNow + 50;    //50mS
            strobeState = STRB_STATE_C;
        break;

        case    STRB_STATE_C:
            redLeds[0] = CRGB::White;
            greenLeds[0] = CRGB::White;
            FastLED.show();
            strobeTimer = timeNow + 50;    //50mS
            strobeState = STRB_STATE_D;
       
        break;

        case    STRB_STATE_D:
            redLeds[0] = CRGB::Black;
            greenLeds[0] = CRGB::Black;
            FastLED.show();
            strobeTimer = timeNow + 1000;    //1-second
            strobeState = STRB_STATE_A;
       
        break;

        default:
            strobeTimer = millis();
            strobeState = STRB_STATE_A;
        break;
       
    }//switch
   
}//Strobes

void loop()
{
    Strobes();
    rainbowCycle();

}//loop

// Slightly different, this makes the rainbow equally distributed throughout
void rainbowCycle( void )
{
    int
        i;
    unsigned long
        timeNow;
    static unsigned long
        rainbowTimer = millis() + WAIT_TIME;
    static unsigned long
        j=0;

    timeNow = millis();
    if( timeNow < rainbowTimer )
        return;

    rainbowTimer = timeNow + WAIT_TIME;

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

    j++;
    if( j >= (unsigned long)(256*1000000) )
        j=0;

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

itg123

Blackfin,

That worked perfectly. Thank you so much for the help. I was trying to do way to much in the viod loop instead of breaking the strobe function into its own loop.

Thanks for everyone that commented and help me through this problem.

Awesome community.

Blackfin

Blackfin,

That worked perfectly. Thank you so much for the help. I was trying to do way to much in the viod loop instead of breaking the strobe function into its own loop.

Thanks for everyone that commented and help me through this problem.

Awesome community.
Great. Just to be clear, it's not that the strobe stuff was just moved into its own function. If you look at the code you won't see any calls to delay() in the strobe or rainbow logic. That's the key in this case to trying to do more than one thing at a time.

itg123

Yeah I'm trying to learn how you did what you did and for what reason. From the examples I was going from, there seemed to be a lot going on that didn't need to be there. Much cleaner looking now.

Thanks again for all the help.

Ian

itg123

Well I finally had time to work on this again. I moved the sketch from a nano board over to a digispark and didn't even think about the sketch being to large. I think the Neopixel library needs to come out. The current sketch is 116% of the digisparks capacity.  From what Iv read online, the FastLED should be able to do most of the same stuff. If anyone had experience with this Id appreciate the help.

Blackfin


itg123

If I could just have the lights chase each other that would work. Its a neopixel ring around the airplane motor.

itg123

Ill just order a bigger board that will fit in the plane. Its a lot of work to drop the library for what I can see.

Thanks again.

Blackfin

I've been playing with it and have something that's at 6066 bytes (max is 6012). Struggling to find those that few bytes (and am not even sure it's problem-free.) Here's what I've got:

Code: [Select]
#include <FastLED.h>

#define NUM_LEDS_PER_STRIP  3
#define NUM_RBOW_LEDS       16

#define RED_DATA_PIN        2
#define GRN_DATA_PIN        3
#define RBOW_DATA_PIN       4

CRGB
    redLeds[NUM_LEDS_PER_STRIP];
CRGB
    greenLeds[NUM_LEDS_PER_STRIP];
CRGB
    strip[NUM_RBOW_LEDS];

void Wheel( byte WheelPos, byte *red, byte *green, byte *blue );

#define NUM_STROBE_STATES   4
#define RBOW_PERIOD        10  //mS

//mS durations for each strobe state
int StrobeDelays[NUM_STROBE_STATES]
    {
        100,
        50,
        50,
        1000
    };

void setup()
{
    FastLED.addLeds<NEOPIXEL, RED_DATA_PIN>(redLeds, NUM_LEDS_PER_STRIP);
    FastLED.addLeds<NEOPIXEL, GRN_DATA_PIN>(greenLeds, NUM_LEDS_PER_STRIP);
    FastLED.addLeds<NEOPIXEL, RBOW_DATA_PIN>(strip, NUM_RBOW_LEDS); 
   
    //fixed nav lights
    redLeds[1].r=255; redLeds[1].g=0; redLeds[1].b=0;               //CRGB::Red
    redLeds[2].r=255; redLeds[2].g=0; redLeds[2].b=0;               //CRGB::Red
    greenLeds[1].r=0; greenLeds[1].g=255; greenLeds[1].b=0;         //CRGB::Green
    greenLeds[2].r=0; greenLeds[2].g=255; greenLeds[2].b=0;         //CRGB::Green
   
}//setup
   
void Strobes( void )
{
    static byte
        strobeState = 0;
    static unsigned long
        strobeTimer = millis();
    static unsigned long
        timeDelay = 0;

    if( (millis() - strobeTimer) < timeDelay )
        return;
   
    strobeTimer = millis();
    if( strobeState & 0x01 )
    {
        //black
        redLeds[0].r = 0;
        redLeds[0].g = 0;
        redLeds[0].b = 0;
        greenLeds[0].r = 0;
        greenLeds[0].g = 0;
        greenLeds[0].b = 0;
    }
    else
    {
        //white
        redLeds[0].r = 0xff;
        redLeds[0].g = 0xff;
        redLeds[0].b = 0xff;
        greenLeds[0].r = 0xff;
        greenLeds[0].g = 0xff;
        greenLeds[0].b = 0xff;
       
    }//else
   
    timeDelay = (unsigned long)StrobeDelays[strobeState];
   
    strobeState = (strobeState + 1) & (NUM_STROBE_STATES-1);
       
    FastLED.show();
   
}//Strobes

void loop()
{
    //never leave loop
    while(1)
    {
        Strobes();
        rainbowCycle();
       
    }//while

}//loop

// Slightly different, this makes the rainbow equally distributed throughout
void rainbowCycle( void )
{
    byte
        i,
        index, red, green, blue;
    static unsigned long
        rainbowTimer = millis();
    static byte
        j=0;

    if( (millis() - rainbowTimer) < RBOW_PERIOD )
        return;

    rainbowTimer = millis();

    for( i=0; i<NUM_RBOW_LEDS; i++ )
    {
        index = (byte)((i << 4) + j);
        Wheel( index, &red, &green, &blue );
        strip[i].r= red;
        strip[i].g= green;
        strip[i].b= blue;
    }//for

    j++;

    FastLED.show();
   
}//rainbowCycle

// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
void Wheel( byte WheelPos, byte *red, byte *green, byte *blue )
{
    byte
        idx,
        k1, k2;
       
    WheelPos = 255 - WheelPos;
    idx = 0;
    if( WheelPos < 170 )
    {
        idx = 1;
        WheelPos -= 85;
    }//else
    else
    {
        idx = 2;
        WheelPos -= 170;
    }//else
       
    k1 = 255 - (WheelPos * 3);
    k2 = WheelPos * 3;

    if( idx == 0 )
    {
        *red = k1;
        *green = 0;
        *blue = k2;
    }//if
    else if( idx == 1 )
    {
        *red = 0;
        *green = k2;
        *blue = k1;
    }//elif
    else
    {
        *red = k2;
        *green = k1;
        *blue = 0;
    }//else
   
}//Wheel

Go Up