For loop variable iteration

I’m using the FastLED library to try to create a chase with a fade (starting with full brightness orange and fading to black in 5 steps) on 5 addressable LEDs. I’m using a for loop and I have a serial output showing the variable’s value, which works fine as long as I don’t iterate the variable in the for loop above 7. The following code is what works:

#include <FastLED.h>

#define DATA_PIN 9
#define NUM_LEDS 5

CRGB leds[NUM_LEDS];

//Define input pins
#define i 2

void setup() {
  FastLED.addLeds<WS2812B, DATA_PIN, GRB>(leds, NUM_LEDS);
  
  Serial.begin(9600);      // open the serial port at 9600 bps:
    
  pinMode(i, INPUT);
}

void loop() {

if (digitalRead(i) == HIGH) {

for(int x = 0; x < NUM_LEDS+2; x++) { 
  leds[x].setRGB( 255, 30, 0); 
  leds[x-1].setRGB( 204, 24, 0);
  leds[x-2].setRGB( 153, 18, 0);
  leds[x-3].setRGB( 102, 12, 0);
  leds[x-4].setRGB( 51, 6, 0);
//  leds[x-5].setRGB( 0, 0, 0);
  Serial.println(x);
  FastLED.delay(75);
  }
}
}

But if I change “NUM_LEDS+2” to “NUM_LEDS+5”, for example, the serial output (after two cycles) reads:

0
1
2
3
4
5
6
7⸮0
1
2
3
4
5
6
7⸮

Additionally if I enable the line “// leds[x-5].setRGB( 0, 0, 0);” then the loop will iterate to 1 and then freeze.

I’ve been staring at it for hours and I can’t work out what I’m doing wrong, any ideas anyone?

What are you trying to do? Attempting to access beyond the limits of an array will always have unpredictable results.

This animation basically demonstrates what I'm trying to achieve.

I wanted the animation to carry on until that last colour change has passed the last LED.

Google "clipping" or "bounds check"

Unless I'm missing something, I'm not using an array?

CRGB leds[NUM_LEDS];

Pete

McDonutz:
Unless I'm missing something, I'm not using an array?

CRGB leds[NUM_LEDS];

You're definitely missing something

Uh… yes, you are.
You shouldn’t try to access the array with subscripts < 0 or >= NUM_LEDS

Here’s one way to do it:

void loop() {
  if (digitalRead(i) == HIGH)  {
    for(int x = 0; x < NUM_LEDS+5; x++) { 
      if (x < NUM_LEDS)
        leds[x].setRGB( 255, 30, 0); 
      if (x > 0 && x < NUM_LEDS + 1)
        leds[x-1].setRGB( 204, 24, 0);
      if (x > 1 && x < NUM_LEDS + 2)
        leds[x-2].setRGB( 153, 18, 0);
      if (x > 2 && x < NUM_LEDS + 3)
        leds[x-3].setRGB( 102, 12, 0);
      if (x > 3 && x < NUM_LEDS + 4)
        leds[x-4].setRGB( 51, 6, 0);
      if (x > 4)
        leds[x-5].setRGB( 0, 0, 0);
      Serial.println(x);
      FastLED.delay(75);
    }
  }
}

A better way would be to wrap the array accesses in a function, and do a simple less than zero or greater then or equal NUM_LEDS bounds check

C and C++ offer you no protection at all from exceeding an array’s bounds, which if it happens
usually stomps all over other variables and causes weird and unpredictable behaviour. Its your
responsibility basically.

I don’t believe I’ve ever seen anyone write past the end of an array AND in front of the array. Good job.
You are not looking at any actual LEDs are you? I don’t see a .show( ) anywhere. If you do look at a strip, I think you’ll be surprised.

GrooveFlotilla:
A better way would be to wrap the array accesses in a function, and do a simple less than zero or greater then or equal NUM_LEDS bounds check

“greater then or equal NUM_LEDS - 1
Regards.
Ray L.

No, NUM_LEDS minus one is perfectly OK.

(Sorry about the "then" - obviously it should've been "than").

Regards, Whatever.

McDonutz:
This animation basically demonstrates what I’m trying to achieve.

I wanted the animation to carry on until that last colour change has passed the last LED.

something like this (not tested)

void loop() 
{
  if (digitalRead(i) == HIGH) 
  {
    for (int i = 0; i < NUM_LEDS; i++)
    {
      leds[i].setRGB( 255, 30, 0);
      int j = i;
      int dimVal = 1;
      while(j > 0 and j > (i-5))  // edited
      {
        j--;
        leds[j].setRGB(255 - (51 * dimVal), 30 - (8 * dimVal), 0);
        dimVal++;
      }
      FastLED.delay(75);
    }
  }
}
 leds[j].setRGB(255 - (51 * dimVal), 30 - (8 * dimVal), 0);

Clever