Overflowing array help please?

greetings,

I would ove some help to idenetify an issue and improve my code please.

This started as a comet effect that runs aong a WS2812B led strip. and changes colours periodically.

I have modified it to react to a "beat trigger" and change direction and colour if a beat is detected.

my issue is that somehow the LED array is overflowing and running negative which is obviously bad. it leads to the pattern being constrained to the single LED at position 0 flickering.

My LEDs are actually arranged in a loop so ideally i would like the pattern to be able to run indefinitely in a loop in either direction and only change direction when a beat is detected.

Any help would be really appreciated.

This example "beat trigger" is made true every second but in reality my code listens to a microphone input but you get the idea...

#include <FastLED.h>

//FASTLED 
#define LEDstripPin 4                          
#define NUM_LEDS 200
#define COLOR_ORDER GRB
#define CHIPSET WS2812B

CRGB leds[NUM_LEDS];

bool BeatTrigger = false;

CRGBPalette16 currentPalette = Rainbow_gp;

void setup() 
{
  FastLED.addLeds<WS2812B,LEDstripPin , GRB>(leds, NUM_LEDS);

  fill_solid(leds, NUM_LEDS, CRGB( 0, 0, 0));
  FastLED.show();
  FastLED.setBrightness(255);
}


void loop() 
{
  BeatTrigger = true;
  RadiationMouse();
  delay(1000);
}

void RadiationMouse()                                                                                                                    // this is not traffic 
{
const byte fadeAmt = 128;
    const int cometSize = 5;
    const int deltaHue  = 4;

    static byte hue = HUE_RED;
    static int iDirection = 1;
    static int iPos = 0;

EVERY_N_SECONDS(5){
  hue += deltaHue;
}
    
    iPos += iDirection;

EVERY_N_MILLISECONDS(100){
    Serial.print("HERE................");
    if (BeatTrigger == true ){                      //if (iPos == (NUM_LEDS - cometSize) || iPos == 0)
        hue += deltaHue;
        iDirection *= -1;
        Serial.print("comet Change = ");     // debug 
        Serial.println(iDirection);
        BeatTrigger = false;
    }
}
    if (iPos == ((NUM_LEDS-1) - cometSize) || iPos == 0){
        iDirection *= -1;
    }
    
    for (int i = 0; i < cometSize; i++){
        if (iPos + i < 0){
          leds[0].setHue(hue);

          }else if (iPos + i > NUM_LEDS-1){
          leds[NUM_LEDS-1].setHue(hue);
          }else {
            leds[iPos + i].setHue(hue);
          }
        Serial.print("LEDS = ");             // debug 
        Serial.println(iPos + i);           // i dont understand how iPos + i can go negative but it does.... 
    }
    // Randomly fade the LEDs
    for (int j = 0; j < NUM_LEDS; j++){
        if (random(10) > 5){
            leds[j] = leds[j].fadeToBlackBy(fadeAmt);  
        }
    }
  BeatTrigger = false;
  FastLED.show();
}

Hello
I gues the variable iPos += iDirection; has no limitation at all

what is modifying BeatTrigger ?
you should print the bounds of every array access, that will give you a hint on what's going on.

beat trigger is connected to other code that samples a microphone input on the ADC so I did not think it was relevant in this example. it is easier to assume the direction should change every second.

thanks for the quick feedback guys :slight_smile:

I will see if this helps;

    iPos += iDirection;
    Serial.print("ipos = ");
    Serial.println(iPos);
    if (iPos < 0){
      iPos = 0; 
      }

any ideas how i would make it work in a loop rather than up and down the strip?

and the upper limit ?

thanks paul

    iPos += iDirection;
    Serial.print("ipos = ");
    Serial.println(iPos);
    if (iPos < 0){
      iPos = 0; 
      }
    if (iPos < NUM_LEDS-1){
      iPos = NUM_LEDS-1; 
      }
      

I understand this if statement is taking care of the direction change when the ends of the array are reached...

    if (iPos == ((NUM_LEDS-1) - cometSize) || iPos == 0){   // this is where the direction changes
        iDirection *= -1;
    }

if i modify this to be >= and <= that should change the direction when the limits are reached but it doesnt directly affect the iPos value. Is that dangerous?

like this?

    if (iPos >= ((NUM_LEDS-1) - cometSize) || iPos <= 0){   // this is where the direction changes
        iDirection *= -1;
    }
 if (iPos > NUM_LEDS-1){
      iPos = NUM_LEDS-1; 

????

Typo, my bad! you are absolutely correct.

So this seems to be working and not getting stuck at the ends of the strip.

but now I would love some help ignoring the ends and have it run in a loop only changing direction when 'beattrigger = true.

Any ideas how I would do that please?

#include <FastLED.h>

//FASTLED 
#define LEDstripPin 4                          
#define NUM_LEDS 200
#define COLOR_ORDER GRB
#define CHIPSET WS2812B

CRGB leds[NUM_LEDS];

bool BeatTrigger = false;

CRGBPalette16 currentPalette = Rainbow_gp;

void setup() 
{
  FastLED.addLeds<WS2812B,LEDstripPin , GRB>(leds, NUM_LEDS);

  fill_solid(leds, NUM_LEDS, CRGB( 0, 0, 0));
  FastLED.show();
  FastLED.setBrightness(255);
}


void loop() 
{
  BeatTrigger = true;
  RadiationMouse();
  delay(1000);
}

void RadiationMouse()                                                                                                                    // this is not traffic 
{
const byte fadeAmt = 128;
    const int cometSize = 5;
    const int deltaHue  = 4;

    static byte hue = HUE_RED;
    static int iDirection = 1;
    static int iPos = 0;

EVERY_N_SECONDS(5){
  hue += deltaHue;
}
    
    iPos += iDirection;
    Serial.print("ipos = ");
    Serial.println(iPos);
    if (iPos < 0){
      iPos = 0; 
      }
    if (iPos > NUM_LEDS-1){
      iPos = NUM_LEDS-1; 
      }
      

  EVERY_N_MILLISECONDS(300){
    //Serial.print("HERE................");
    if (BeatTrigger == true ){                      //if (iPos == (NUM_LEDS - cometSize) || iPos == 0)
        hue += deltaHue;
        iDirection *= -1;
        //Serial.print("comet Change = ");
        //Serial.println(iDirection);
        BeatTrigger = false;
    }
  }
    if (iPos == ((NUM_LEDS-1) - cometSize) || iPos == 0){   // this is where the direction changes
        iDirection *= -1;
    }
    
    for (int i = 0; i < cometSize; i++){
        if (iPos + i < 0){
          leds[0].setHue(hue);

          }else if (iPos + i > NUM_LEDS-1){
          leds[NUM_LEDS-1].setHue(hue);
          }else {
            leds[iPos + i].setHue(hue);
          }
        //Serial.print("LEDS = ");
        //Serial.println(iPos + i);
    }
    // Randomly fade the LEDs
    for (int j = 0; j < NUM_LEDS; j++){
        if (random(10) > 5){
            leds[j] = leds[j].fadeToBlackBy(fadeAmt);  
        }
    }
  BeatTrigger = false;
  FastLED.show();
}

Where I can find the "gearbox" in your sketch ?

Sorry, I don't understand what you mean by gearbox?

a "gearbox" to change the direction, like in the car :grinning:

this is what changes direction when it hits the ends...

Hello
I haven´t study your sketch completely and I don´t know where you can read a button like:
PSEUDOCODE
if (buttonPressed()) iDirection *= -1;

I have no buttons....

beattrigger = true is the only method I want to change direction.

got the code to work how i wanted...

here is the final version of my function thats not particularly elegant but works.

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void RadiationMouse()                                                                                                                    // this is not traffic 
{
const byte fadeAmt = 128;
    const int cometSize = 5;
    const int deltaHue  = 4;

    static byte hue = HUE_BLUE;
    static int iDirection = 1;
    static int iPos = 0;

EVERY_N_SECONDS(5){
  hue += deltaHue;
}
    
    iPos += iDirection;

//    if (iPos < 0){
//      iPos = 0; 
//      }
//    if (iPos > NUM_LEDS-1){
//     iPos = NUM_LEDS-1; 
//     }
      

  EVERY_N_MILLISECONDS(300){
    //Serial.print("HERE................");
    if (BeatTrigger == true ){                      //if (iPos == (NUM_LEDS - cometSize) || iPos == 0)
        hue += deltaHue;
        iDirection *= -1;
        //Serial.print("comet Change = ");
        //Serial.println(iDirection);
        BeatTrigger = false;
    }
  }

if (iPos >= NUM_LEDS && iDirection == 1){                                                                                      
   iPos = 0;  
   //Serial.println("here = 1 "); 
        } 
        
if ((iPos < 0)&&(iDirection == -1)){                                                                                      
  iPos = NUM_LEDS-1;   
  //Serial.print("here = 2 ");
        } 
 
    Serial.print("ipos = ");
    Serial.println(iPos);
        
    
//    if (iPos == ((NUM_LEDS-1) - cometSize) || iPos == 0){   // this is where the direction changes
//        //iDirection *= -1;
//    }
    
    for (int i = 0; i < cometSize; i++){
        if (iPos + i < 0){
          leds[0].setHue(hue);

          }else if (iPos > NUM_LEDS-1){     
          leds[NUM_LEDS-1].setHue(hue);
          }else {
            leds[iPos].setHue(hue); 
          }
    }
    // Randomly fade the LEDs
    for (int j = 0; j < NUM_LEDS; j++){
        if (random(10) > 5){
            leds[j] = leds[j].fadeToBlackBy(fadeAmt);  
        }
    }
  BeatTrigger = false;
  FastLED.show();

}

This was asked a week or two back.

Research the "%" operator. Use it with NUM_LEDS.