Array wrap around for fastled ring display

hi guys,

i have a ring of LEDs and I need my pattern to wrap around without overflowing the array.

I have constrained it within the array but if the random led is chosen close to the upper or lower limits of the array the pattern misbehaves.

can anyone please help me understand how to make it wrap so the “paintballs” overlap the led array seamlessly?

thanks in advance :slight_smile:

void Paintball(){
 int randomLED = random8(0,NUM_LEDS-1);
 int randomColor = random8();
 int paintballWidth = 5;
 int paintballBrightness = 255;
 int Fadetime = 40;
 float spreadmultiplier = 0.8;
 
 if (BeatTrigger == true ){ 
   leds[randomLED] = ColorFromPalette(currentPalette,randomColor,paintballBrightness,LINEARBLEND);
     for(int i = 1; i < paintballWidth; i++){
       if ((randomLED-i < 0+paintballWidth) ||(randomLED+i > NUM_LEDS-paintballWidth)){
                   //do nothing so it doesnt overflow leds array 
       }else{
         leds[randomLED-i] = ColorFromPalette(currentPalette,randomColor,paintballBrightness,LINEARBLEND);
         leds[randomLED+i] = ColorFromPalette(currentPalette,randomColor,paintballBrightness,LINEARBLEND);
         paintballBrightness = paintballBrightness*spreadmultiplier ;
       }
     } 
 BeatTrigger = false;
 }
 fadeToBlackBy(leds,NUM_LEDS,Fadetime);
 FastLED.show();
 }

You need to become familiar with the remainder ("%") operator. :+1:

Thanks Paul but I don’t get how to use % in my case. I actually want the values to overlap the bounds of the array and not just be limited within them.

Could you please elaborate further?

this is where I am at now which is closer but not working correctly…

//////////////////////////////////////////////////////////////////////////////
void Paintball(){
  int randomLED = 2;//random8(0,NUM_LEDS-1);
  int randomColor = random8();
  int paintballWidth = 2;
  int paintballBrightness = 255;
  int Fadetime = 40;
  int calc = 0;
  float spreadmultiplier = 0.8;
  
  if (BeatTrigger == true ){ 
    leds[randomLED] = ColorFromPalette(currentPalette,randomColor,paintballBrightness,LINEARBLEND);
      for(int i = 1; i <= paintballWidth; i++){
          paintballBrightness = paintballBrightness*spreadmultiplier ;
        
        if (randomLED-i <= 0) {
          leds[NUM_LEDS-i] = ColorFromPalette(currentPalette,randomColor,paintballBrightness,LINEARBLEND);
        } 
        
        if(randomLED+i > NUM_LEDS-1){
           leds[i-1] = ColorFromPalette(currentPalette,randomColor,paintballBrightness,LINEARBLEND);  
           leds[randomLED-i] = ColorFromPalette(currentPalette,randomColor,paintballBrightness,LINEARBLEND);       
             
        }else{
          leds[randomLED-i] = ColorFromPalette(currentPalette,randomColor,paintballBrightness,LINEARBLEND);
          leds[randomLED+i] = ColorFromPalette(currentPalette,randomColor,paintballBrightness,LINEARBLEND);
                                                      
        }
      } 
  BeatTrigger = false;
  }
  fadeToBlackBy(leds,NUM_LEDS,Fadetime);
  FastLED.show();
}

Hi, I’m testing Wokwi and put your sketch in the Wokwi simulator. You only have to click the start button in the upper-middle of the screen: https://wokwi.com/arduino/projects/298086653731275273.
thumbnail

Thanks heaps… That is amazing!!! I have never seen a simulator that can handle showing real time LEDS and especially in a ring!

it even shows the error as I see it on my LEDS.

I am trying to understand how to solve it using % but im not getting the concept…

Nope, that makes no sense. You always want the array bounds to be constrained. Use “%” to pull (and wrap) the array index into the size of the array whenever you make any reference or modification to it.

So

         leds[i-1] = ColorFromPalette(currentPalette,randomColor,paintballBrightness,LINEARBLEND); 

becomes

         leds[(i-1) % NUM_LEDS] = ColorFromPalette(currentPalette,randomColor,paintballBrightness,LINEARBLEND); 

I cannot say more as you have failed to cite your full code but presume you have used NUM_LEDS to specify the array size. :face_with_raised_eyebrow:

Hi Paul,
Yes NUM_LEDS is the size of the LED array.

you are right and I didn’t mean I wanted to break the code by overflowing an array. I mean that I want it to wrap…

I am struggling to understand Modulo % but ill have a play with your example now.

thanks for the help.

ok so im still pulling my hair out with this…

With my code below only the LEDs at 0,1,2 and 3 light.
I am expecting 59 to light also but it isn’t.

The value of calc is returning -1 when i =2 which I don’t understand.

calc = (randomLED-i)% NUM_LEDS should be 59 = (1-2)%60

I am missing something silly but need help to find it please.

//////////////////////////////////////////////////////////////////////////////
void Paintball(){
 int NUM_LEDS = 60;
 int randomLED = 1;//random8(0,NUM_LEDS-1);
  int randomColor = random8();
  int paintballWidth = 2;
  int paintballBrightness = 50;
  int Fadetime = 40;
  int calc = 0;
  float spreadmultiplier = 0.8;
  int BeatTrigger = true;                    //  <<<<DONT FORGET TO DELETE ME!!!
  
  if (BeatTrigger == true ){ 
    leds[randomLED] = ColorFromPalette(currentPalette,randomColor,paintballBrightness,LINEARBLEND);
      for(int i = 1; i <= paintballWidth; i++){
          paintballBrightness = paintballBrightness*spreadmultiplier ;

        if (randomLED-i < 0){
          calc = (randomLED-i)% NUM_LEDS;
          Serial.print("i = ");
          Serial.print(i);
          Serial.print("    calc = ");
          Serial.println(calc);
          leds[calc] = ColorFromPalette(currentPalette,randomColor,paintballBrightness,LINEARBLEND);
        } 
        
        if(randomLED+i >= NUM_LEDS-1){
          leds[(randomLED+i)%NUM_LEDS] = ColorFromPalette(currentPalette,randomColor,paintballBrightness,LINEARBLEND);  
          leds[randomLED-i] = ColorFromPalette(currentPalette,randomColor,paintballBrightness,LINEARBLEND);

        }else{
          leds[randomLED-i] = ColorFromPalette(currentPalette,randomColor,paintballBrightness,LINEARBLEND);
          leds[randomLED+i] = ColorFromPalette(currentPalette,randomColor,paintballBrightness,LINEARBLEND);
                                                      
        }
      } 
  BeatTrigger = false;
  }
  fadeToBlackBy(leds,NUM_LEDS,Fadetime);
  FastLED.show();
}

It is quite simple. :laughing: And silly.

You need to make the alteration I specified, to every use of the array index.

And you are spouting snippets! :roll_eyes:

Thanks Paul,

Clearly I’m not an expert at this and I don’t fully understand what you are saying.

My full code is 800+ lines so I am supplying the function that is relevant.

However, I have recently learned that a simulator is available and this is exactly simulating my issue:

Hi,
If you have a large program, did you write it in stages, getting each individual stage to work BEFORE combining it.
If you did, then you should have a stand alone code that just drives the LEDs and does what you want it to do.
Forget about your main code and JUST use code to drive the LEDs.
That way we can try your code and do not have to trawl through your entire program.

So can you please produce some code that JUST controls your LEDS.
That way you can alleviate ALL other parts of your code and see just what you are working on.

Tom… :grinning: :+1: :coffee: :australia:

Here is a piece of code that simulates the issue i am having outside the large program.

#include <FastLED.h>

//FASTLED 
#define LEDstripPin 4                          
#define NUM_LEDS 60                    //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;
  Paintball();
}

void Paintball(){
  int randomLED = 2;//random8(0,NUM_LEDS-1);
  int randomColor = random8();
  int paintballWidth = 2;
  int paintballBrightness = 255;
  int Fadetime = 40;
  int calc = 0;
  float spreadmultiplier = 1; //0.8

    if (BeatTrigger == true ){ 
    leds[randomLED] = ColorFromPalette(currentPalette,randomColor,paintballBrightness,LINEARBLEND);
      for(int i = 1; i <= paintballWidth; i++){
          paintballBrightness = paintballBrightness*spreadmultiplier ;

        if (randomLED-i < 0){
          calc = (randomLED-i)% NUM_LEDS;
          calc = NUM_LEDS - abs(calc);
          leds[calc] = ColorFromPalette(currentPalette,randomColor,paintballBrightness,LINEARBLEND);
        } 
        
        if(randomLED+i >= NUM_LEDS-1){
          leds[(randomLED+i)%NUM_LEDS] = ColorFromPalette(currentPalette,randomColor,paintballBrightness,LINEARBLEND);  
          leds[randomLED-i] = ColorFromPalette(currentPalette,randomColor,paintballBrightness,LINEARBLEND);

        }else{
          leds[randomLED-i] = ColorFromPalette(currentPalette,randomColor,paintballBrightness,LINEARBLEND);
          leds[randomLED+i] = ColorFromPalette(currentPalette,randomColor,paintballBrightness,LINEARBLEND);
                                                      
        }
      } 
  BeatTrigger = false;
  }
  fadeToBlackBy(leds,NUM_LEDS,Fadetime);
  FastLED.show();
}

Hi Tom,
Thanks, I thought the function was sufficient without all the fastled confusion.

(Excluding my mistake of not including a reference to what NUM_LEDS was)

I have added a full piece of code now and would really love some help understanding how to improve it. Paul mentions % but I am confused as to how to use it correctly.