Interrupting an LED animation in with an "if" statment

Hi,

I have a project that uses an Ultrasonic sensor and some Neopixel LED strips.
When something comes within the proximity of the Ultrasonic sensor it triggers an LED animation in the Neopixel strips. This is an animation I got from the FastLED Example folder.

What I want to happen is that if there is nothing in the Ultrasonic sensor's proximity that the LED animation completely stops, as it takes about a minute from start to finish.

I have an if statement, where if something is within the sensor's proximity the animation is triggered. But there is an "else" part where if there is nothing in the proximity it should go to black.

This method is working for other LED animations but not this one. I am posting the code below. If anyone has any ideas for how to remedy this please let me know.

// need to fix the  if/else statement
// to turn off
// all LEDs when noting is sensed


#include "FastLED.h"


#define NUM_LEDS      660
#define LED_TYPE   WS2811
#define COLOR_ORDER   GRB
#define DATA_PIN        6
//#define CLK_PIN       4
#define VOLTS          12
#define MAX_MA       500



// constants won't change
const int TRIG_PIN = 7; // Arduino pin connected to Ultrasonic Sensor's TRIG pin
const int ECHO_PIN = 8; // Arduino pin connected to Ultrasonic Sensor's ECHO pin
const int LED_PIN  = 6; // Arduino pin connected to LED's pin
const int DISTANCE_THRESHOLD = 100; // centimeters

// variables will change:
float duration_us, distance_cm;




CRGBArray<NUM_LEDS> leds;

CRGBPalette16 gCurrentPalette;
CRGBPalette16 gTargetPalette;

void setup() {
  Serial.begin (9600);       // initialize serial port
  Serial.println("resetting");
  pinMode(TRIG_PIN, OUTPUT); // set arduino pin to output mode
  pinMode(ECHO_PIN, INPUT);  // set arduino pin to input mode
  pinMode(LED_PIN, OUTPUT);  // set arduino pin to output mode

  delay( 3000 ); //safety startup delay
  FastLED.setMaxPowerInVoltsAndMilliamps( VOLTS, MAX_MA);
  FastLED.addLeds<LED_TYPE, DATA_PIN, COLOR_ORDER>(leds, NUM_LEDS);
  FastLED.setBrightness(255);
  // .setCorrection(TypicalLEDStrip);


}

void fadeall() {
  for (int i = 0; i < NUM_LEDS; i++) {
    leds[i].nscale8(1000);
  }
}

void loop()
{
  // generate 10-microsecond pulse to TRIG pin
  digitalWrite(TRIG_PIN, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG_PIN, LOW);

  // measure duration of pulse from ECHO pin
  duration_us = pulseIn(ECHO_PIN, HIGH);
  // calculate the distance
  distance_cm = 0.017 * duration_us;

  if (distance_cm < DISTANCE_THRESHOLD)

  {

    cylon();
  }

  else
  {
    // leds[0] = CRGB::Black;

    // black();
    // CRGB::Black;

    fill_solid ( leds, 660, CRGB::Black);
    FastLED.show();
    delay(500);


  }
}




void black()
{ for (int i = (NUM_LEDS) - 1; i >= 0; i++) {
    // Set the i'th led to red
    leds[i] = CRGB::Black;
    // Show the leds
    FastLED.show();
    delay(500);
  }
}

void cylon()
{

  static uint8_t hue = 0;
  Serial.print("x");
  // First slide the led in one direction
  for (int i = 0; i < NUM_LEDS; i++) {
    // Set the i'th led to red
    leds[i] = CHSV(hue++, 255, 255);
    // Show the leds
    FastLED.show();
    // now that we've shown the leds, reset the i'th led to black
    // leds[i] = CRGB::Black;
    fadeall();
    // Wait a little bit before we loop around and do it again
    delay(10);
  }
  Serial.print("x");

  // Now go in the other direction.
  for (int i = (NUM_LEDS) - 1; i >= 0; i--) {
    // Set the i'th led to red
    leds[i] = CHSV(hue++, 255, 255);
    // Show the leds
    FastLED.show();
    // now that we've shown the leds, reset the i'th led to black
    // leds[i] = CRGB::Black;
    fadeall();
    // Wait a little bit before we loop around and do it again
    delay(10);

  }
}

cylon() gets control and will not return for it looks like over two minutes.

You must rewrite cylon() so it takes a step each time it is called, and use the fact that now your loop() will run freely to check over and over the value from the distance measurement.

Without measuring again, you would not know to stop.

cylon() taking a step at each call means you get a chance each step to change your mind about continuing with the animation.

The for loops in cylon() will go away; a static variable in the function will inform what step to take next (or finish) the animation.

It's a step towards a popular method of writing non-blocking code, which cylon() currently is (blocking), that method being FSMs or "finite state machines" about which you might google

finite state machine arduino

to get a feel for this way of programming.

Blocking just means code that goes off on its own and deprives you of the processor attention that woukd be needed to do other stuff like check buttons or sensors &c.

HTH

a7

Thanks for the information alto777.

I didn't know about finite state machines. I see a few libraries that deal with this.

But if I understand you correctly, the for loop in cylon is taking over. Maybe instead of having the int i in the for loop I can have a variable that is works in all the functions of the code that advances one time each pass, and everytime that advances, the for loop in cylon advances once.

I'll give that a try. I have tried a few things with this code and just because of all the LEDs certain things really slow down the animation. I'll see what happens.

You seemed to have missed this point.

1 Like

OK I am trying to add some variable outside of the cylon() function to deal with this. And I added some if statements.

It still doesn't work. Maybe someone can tell me what's wrong with this one.

I added a variable called "advance" which is supposed to be the number of the LED being lit up in the LED strip that should advance one number each time through the loop. Advance is also in the cylon() function, but doesn't seem to step through the LEDs, but it does step through the LED color animation ( maybe this is the problem)?

I also added a variable called "updown" that should deal with the LEDs going up the strip and then coming down. That's why that's there.

I also have a feeling that the part with "advance " in the cylon loop isn't worded very well. I'll keep messing around with this.

If anyone has some ideas to try please let me know.

// need to fix the else 
// in the if statement to turn off 
// all LEDs when noting is sensed 

// make a switch to 


#include "FastLED.h"


#define NUM_LEDS      660
#define LED_TYPE   WS2811
#define COLOR_ORDER   GRB
#define DATA_PIN        6
//#define CLK_PIN       4
#define VOLTS          12
#define MAX_MA       500



// constants won't change
const int TRIG_PIN = 7; // Arduino pin connected to Ultrasonic Sensor's TRIG pin
const int ECHO_PIN = 8; // Arduino pin connected to Ultrasonic Sensor's ECHO pin
const int LED_PIN  = 6; // Arduino pin connected to LED's pin
const int DISTANCE_THRESHOLD = 100; // centimeters

// variables will change:
float duration_us, distance_cm;

int advance = 0;
int updown = 0;



CRGBArray<NUM_LEDS> leds;

CRGBPalette16 gCurrentPalette;
CRGBPalette16 gTargetPalette;

void setup() {
  Serial.begin (9600);       // initialize serial port
    Serial.println("resetting");
  pinMode(TRIG_PIN, OUTPUT); // set arduino pin to output mode
  pinMode(ECHO_PIN, INPUT);  // set arduino pin to input mode
  pinMode(LED_PIN, OUTPUT);  // set arduino pin to output mode

  delay( 3000 ); //safety startup delay
  FastLED.setMaxPowerInVoltsAndMilliamps( VOLTS, MAX_MA);
  FastLED.addLeds<LED_TYPE, DATA_PIN, COLOR_ORDER>(leds, NUM_LEDS);
  FastLED.setBrightness(255);
 // .setCorrection(TypicalLEDStrip);


}

void fadeall() { for(int i = 0; i < NUM_LEDS; i++) { leds[i].nscale8(1000); } }

void loop()
{
  // generate 10-microsecond pulse to TRIG pin
  digitalWrite(TRIG_PIN, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG_PIN, LOW);

  // measure duration of pulse from ECHO pin
  duration_us = pulseIn(ECHO_PIN, HIGH);
  // calculate the distance
  distance_cm = 0.017 * duration_us;

  // for cylon LEDs

advance = 0;
updown = 0;



if ( advance == 0 )
{
  updown = 0;
}

if ( advance == NUM_LEDS )
{
  updown = 1;
}

 if (distance_cm < DISTANCE_THRESHOLD && updown == 0)

  {
   ( advance++);

  }

  
if (distance_cm < DISTANCE_THRESHOLD && updown == 1)

 { 
   ( advance--);
  
 }

if (distance_cm > DISTANCE_THRESHOLD )

 { 
   ( advance == -1);
  
 }
 

 //else if (distance_cm > DISTANCE_THRESHOLD)

// {
 // fill_solid ( leds, 660, CRGB::Black);
  // FastLED.show();
  // delay(500);
  
 //}

  if (distance_cm < DISTANCE_THRESHOLD )

  {

  cylon();
  }
/*
  else 
  {
   // leds[0] = CRGB::Black;

  // black();
  // CRGB::Black;

  fill_solid ( leds, 660, CRGB::Black);
   FastLED.show();
   delay(500);

  
  }
  */
}




void black()
{for(int i = (NUM_LEDS)-1; i >= 0; i++) {
   // Set the i'th led to red 
    leds[i] = CRGB::Black;
    // Show the leds
    FastLED.show();
      delay(500);
}
}

void cylon()
{

  static uint8_t hue = 0;
 // Serial.print("x");
  // First slide the led in one direction
 //for( advance = 0; advance < NUM_LEDS; advance++)
 {

  if ( advance > 0)
  {
    // Set the i'th led to red 
    leds[advance] = CHSV(hue++, 255, 255);
    // Show the leds
    FastLED.show(); 
    // now that we've shown the leds, reset the i'th led to black
    // leds[i] = CRGB::Black;
    fadeall();
    // Wait a little bit before we loop around and do it again
    delay(10);
  }

  if (advance < 0)

  {
    
 leds[0] = CRGB::Black;

   black();
  CRGB::Black;

  fill_solid ( leds, 660, CRGB::Black);
   FastLED.show();
   delay(500);
  }
 }
}
 // Serial.print("x");

  // Now go in the other direction.  
    //  for(int i = (NUM_LEDS)-1; i >= 0; i--) {
    // Set the i'th led to red 
  //leds[i] = CHSV(hue++, 255, 255);
    // Show the leds
  // FastLED.show();
    // now that we've shown the leds, reset the i'th led to black
    // leds[i] = CRGB::Black;
 // fadeall();
    // Wait a little bit before we loop around and do it again
  // /delay(10);

// }
//}

I'm without the capability currently to test your code or even read it carefully. Beach.

But recall that loop() loops… if you set advance and up down to zero where you do, it will never get much further in one pass.

Put your finger on the code and trace it like a dumb computer, you will see why this is t satisfying yet.

I'll try a sim L8R if I get home sober enough.

a7

As you say

Well, measure again within the fors that take control and stop them if necessary. The most comfortable thing would be to make a function to measure the distance outside the loop and use it when necessary. Something like this:

#include "FastLED.h"

#define NUM_LEDS      660
#define LED_TYPE   WS2811
#define COLOR_ORDER   GRB
#define DATA_PIN        6
//#define CLK_PIN       4
#define VOLTS          12
#define MAX_MA       500
#define strip_speed  10

// constants won't change
const int TRIG_PIN = 7; // Arduino pin connected to Ultrasonic Sensor's TRIG pin
const int ECHO_PIN = 8; // Arduino pin connected to Ultrasonic Sensor's ECHO pin
const int LED_PIN  = 6; // Arduino pin connected to LED's pin
const int DISTANCE_THRESHOLD = 100; // centimeters

// variables will change:
float duration_us, distance_cm;

CRGBArray<NUM_LEDS> leds;
CRGBPalette16 gCurrentPalette;
CRGBPalette16 gTargetPalette;

void setup() {
  Serial.begin (9600);       // initialize serial port
  Serial.println("resetting");
  pinMode(TRIG_PIN, OUTPUT); // set arduino pin to output mode
  pinMode(ECHO_PIN, INPUT);  // set arduino pin to input mode
  pinMode(LED_PIN, OUTPUT);  // set arduino pin to output mode

  delay( 3000 ); //safety startup delay
  FastLED.setMaxPowerInVoltsAndMilliamps( VOLTS, MAX_MA);
  FastLED.addLeds<LED_TYPE, DATA_PIN, COLOR_ORDER>(leds, NUM_LEDS);
  FastLED.setBrightness(255);
  // .setCorrection(TypicalLEDStrip);


}

void fadeall() {
  for (int i = 0; i < NUM_LEDS; i++) {
    leds[i].nscale8(1000);
  }
}

void loop() {
  if (distance () < DISTANCE_THRESHOLD) {
    cylon();
  }

  else {
    fill_solid ( leds, 660, CRGB::Black);
    FastLED.show();
    delay(500);
  }
}

int distance () {
  // generate 10-microsecond pulse to TRIG pin
  digitalWrite(TRIG_PIN, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG_PIN, LOW);

  // measure duration of pulse from ECHO pin
  duration_us = pulseIn(ECHO_PIN, HIGH);
  // calculate the distance
  distance_cm = 0.017 * duration_us;
  return distance_cm ;
}


void black() {
  for (int i = (NUM_LEDS) - 1; i >= 0; i++) {
    // Set the i'th led to red
    leds[i] = CRGB::Black;
    // Show the leds
    FastLED.show();
    delay(500);
  }
}

void cylon() {
  static uint8_t hue = 0;
  Serial.print("x");
  // First slide the led in one direction
  for (int i = 0; i < NUM_LEDS; i++) {
    if (distance () < DISTANCE_THRESHOLD) {
      break;
    }
    // Set the i'th led to red
    leds[i] = CHSV(hue++, 255, 255);
    // Show the leds
    FastLED.show();
    // now that we've shown the leds, reset the i'th led to black
    // leds[i] = CRGB::Black;
    fadeall();
    // Wait a little bit before we loop around and do it again
    delay(strip_speed);
  }
  Serial.print("x");

  // Now go in the other direction.
  for (int i = (NUM_LEDS) - 1; i >= 0; i--) {
    if (distance () < DISTANCE_THRESHOLD) {
      break;
    }
    // Set the i'th led to red
    leds[i] = CHSV(hue++, 255, 255);
    // Show the leds
    FastLED.show();
    // now that we've shown the leds, reset the i'th led to black
    // leds[i] = CRGB::Black;
    fadeall();
    // Wait a little bit before we loop around and do it again
    delay(strip_speed);

  }
}

No. Well, yes. But it leads soon enough to a real tangle of code if that logic is used in all the animations.

IMO it would be better to come to an understanding of how to write routine such as cylon() as a loop-friendly function that does not keep a hold on the processor resource.

Even if other than watching the sensor is never needed, best to write code like the loop() prefers… called frequently, often doing very little if not nothing.

And focused on doing its one job, not cluttered with responsibilities best handled at a higher level.

a7

Hey gonpezzi

Your code actually worked.

I had to change less than to greater than for the distance, but other than that it works.

from

 for (int i = (NUM_LEDS) - 1; i >= 0; i--) {
    if (distance () < DISTANCE_THRESHOLD) {
      break;

to

for (int i = (NUM_LEDS) - 1; i >= 0; i--) {
    if (distance () > DISTANCE_THRESHOLD) {
      break;

At least I can see what this looks like and if I want to build on it. Thank you alto777 for your suggestion. I'll try and wrap my head around this, but I haven't done much coding in the last 2 years so I am rusty and having some problems knowing the best way to express what I'm trying to do.

here's the whole thing again

#include "FastLED.h"

#define NUM_LEDS      660
#define LED_TYPE   WS2811
#define COLOR_ORDER   GRB
#define DATA_PIN        6
//#define CLK_PIN       4
#define VOLTS          12
#define MAX_MA       500
#define strip_speed  2

// constants won't change
const int TRIG_PIN = 7; // Arduino pin connected to Ultrasonic Sensor's TRIG pin
const int ECHO_PIN = 8; // Arduino pin connected to Ultrasonic Sensor's ECHO pin
const int LED_PIN  = 6; // Arduino pin connected to LED's pin
const int DISTANCE_THRESHOLD = 100; // centimeters

// variables will change:
float duration_us, distance_cm;

CRGBArray<NUM_LEDS> leds;
CRGBPalette16 gCurrentPalette;
CRGBPalette16 gTargetPalette;

void setup() {
  Serial.begin (9600);       // initialize serial port
  Serial.println("resetting");
  pinMode(TRIG_PIN, OUTPUT); // set arduino pin to output mode
  pinMode(ECHO_PIN, INPUT);  // set arduino pin to input mode
  pinMode(LED_PIN, OUTPUT);  // set arduino pin to output mode

  delay( 3000 ); //safety startup delay
  FastLED.setMaxPowerInVoltsAndMilliamps( VOLTS, MAX_MA);
  FastLED.addLeds<LED_TYPE, DATA_PIN, COLOR_ORDER>(leds, NUM_LEDS);
  FastLED.setBrightness(255);
  // .setCorrection(TypicalLEDStrip);


}

void fadeall() {
  for (int i = 0; i < NUM_LEDS; i++) {
    leds[i].nscale8(1000);
  }
}

void loop() {
  if (distance () < DISTANCE_THRESHOLD) {
    cylon();
  }

  else {
    fill_solid ( leds, 660, CRGB::Black);
    FastLED.show();
    delay(100);
  }
}

int distance () {
  // generate 10-microsecond pulse to TRIG pin
  digitalWrite(TRIG_PIN, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG_PIN, LOW);

  // measure duration of pulse from ECHO pin
  duration_us = pulseIn(ECHO_PIN, HIGH);
  // calculate the distance
  distance_cm = 0.017 * duration_us;
  return distance_cm ;
}


void black() {
  for (int i = (NUM_LEDS) - 1; i >= 0; i++) {
    // Set the i'th led to red
    leds[i] = CRGB::Black;
    // Show the leds
    FastLED.show();
    delay(500);
  }
}

void cylon() {
  static uint8_t hue = 0;
  Serial.print("x");
  // First slide the led in one direction
  for (int i = 0; i < NUM_LEDS; i++) {
    if (distance () > DISTANCE_THRESHOLD) {
      break;
    }
    // Set the i'th led to red
    leds[i] = CHSV(hue++, 255, 255);
    // Show the leds
    FastLED.show();
    // now that we've shown the leds, reset the i'th led to black
    // leds[i] = CRGB::Black;
    fadeall();
    // Wait a little bit before we loop around and do it again
    delay(strip_speed);
  }
  Serial.print("x");

  // Now go in the other direction.
  for (int i = (NUM_LEDS) - 1; i >= 0; i--) {
    if (distance () > DISTANCE_THRESHOLD) {
      break;
    }
    // Set the i'th led to red
    leds[i] = CHSV(hue++, 255, 255);
    // Show the leds
    FastLED.show();
    // now that we've shown the leds, reset the i'th led to black
    // leds[i] = CRGB::Black;
    fadeall();
    // Wait a little bit before we loop around and do it again
    delay(strip_speed);

  }
}

This is the code for all the effects in the FastLed examples including cyclone as a state machine. It runs all 5 patterns at the same time on different LEDs of a 64 LED strip depending what patterns are enabled by the values in the patternEnabled [] array.

// Multiple patterns in a state machine format
// using the FastLED library
// by Grumpy_Mike 2017

#include "FastLED.h"

// first set up the parameters to use in the pattern calling
unsigned long patternInterval [] = { 500, 40, 20, 200, 5 }; // how often each pattern updates
unsigned long lastUpdate [5] ;  // for millis() when last update occurred
boolean patternEnabled [] = {true,true,false,true,true}; // should the pattern be called at all
byte patternState[5]; // state machine variable for patterns - this initialises them to zero

// now set up the LEDs to use
#define NUM_LEDS 64
#define DATA_PIN 3
#define CLOCK_PIN 13


CRGB leds[NUM_LEDS];

// Constants for patterns
// for Fire2012
#define COOLING  20
#define SPARKING 50
#define COLOR_ORDER BGR

// now set up the array of pointers to each pattern
void (*patternPtrs[5])(int index,byte state); //the array of pattern pointers

void setup() {
  //initialises the array of pattern pointers
  patternPtrs[0] = blinkOne; 
  patternPtrs[1] = cylon;
  patternPtrs[2] = fire;
  patternPtrs[3] = colorWipe;
  patternPtrs[4] = rainbowCycle;
  //initialises the FastLED driver you want
  //FastLED.addLeds<APA102,leds, NUM_LEDS); // 13 clock  and 11 data
  FastLED.addLeds<APA102, DATA_PIN, CLOCK_PIN, BGR>(leds, NUM_LEDS); // 13 clock  and 11 data
  FastLED.setBrightness(8);
}

void loop() {
  for(int i = 0; i<5; i++) { // go through all the patterns and see if it is time to call one
    if(patternEnabled[i] && millis() - lastUpdate[i] > patternInterval[i]){
      lastUpdate[i] = millis();
      callPatterns(i, patternState[i]);
    }
  }
}

void callPatterns(int index, byte state) {
  (*patternPtrs[index])(index,state); //calls the pattern at the index of `index` in the array
}

// These are the pattern functions written as a state machine
// this is the Blink program in FastLED's example folder
void blinkOne(int index,byte state) {
  if(state == 0){
    leds[3] = CRGB::Blue;
    FastLED.show();
    patternState[index] = 1; // move on the state machine for the next call
  }
  if(state == 1){
     leds[3] = CRGB::Black;
     FastLED.show();
     patternState[index] = 0;
   }
  }

// this is the Cylon program in FastLED's example folder
// we will use LEDs 8 to 15 to show this
void cylon(int index,byte state) {
  static int i = 8; // replaces the loop index
  if(state == 0){
    leds[i] = CRGB::Red;
    FastLED.show();
    patternState[index] = 1; // move on the state machine for the next call
  }
   if(state == 1){
    // now that we've shown the leds, reset the i'th led to black
    leds[i] = CRGB::Black;
    i++; // increment what was the loop variable
    if(i >= 16){ // we have finished one direction
     patternState[index] = 2;
     i--;
    }
    else {
    patternState[index] = 0;
    }
   }
   // Now go in the other direction only green
   if(state == 2){
     leds[i] = CRGB::Green;
    FastLED.show();
    patternState[index] = 3; // move on the state machine for the next call
   }
  if(state == 3){
    // now that we've shown the leds, reset the i'th led to black
    leds[i] = CRGB::Black;
    i--; // decrement what was the loop variable
    if(i < 8){ // we have finished the return, go back to the start
     patternState[index] = 0;
     i= 8; // ready to start again
    }
    else {
    patternState[index] = 2;
    } 
    // note that this could be better implemented but it has been written like this to keep it close to the original example
    // so you can see what changes have been made 
  }
}

// this is the Fire2012 program in FastLED's example folder
void fire(int index,byte state) {
// using LEDs 16 to 32
// Array of temperature readings at each simulation cell
  const byte startLED = 16; // first LED in section
  const byte numLEDs = 16;
  static byte heat[numLEDs];

  random16_add_entropy( random());
  // Step 1.  Cool down every cell a little
    for( int i = 0; i < numLEDs; i++) {
      heat[i] = qsub8( heat[i],  random8(0, ((COOLING * 10) / NUM_LEDS) + 2));
    }
  
    // Step 2.  Heat from each cell drifts 'up' and diffuses a little
    for( int k= numLEDs - 1; k >= 2; k--) {
      heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2] ) / 3;
    }
    
    // Step 3.  Randomly ignite new 'sparks' of heat near the bottom
    if( random8() < SPARKING ) {
      int y = random8(7);
      heat[y] = qadd8( heat[y], random8(160,255) );
    }

    // Step 4.  Map from heat cells to LED colors
    for( int j = 0; j < numLEDs; j++) {
        leds[j+startLED] = HeatColor( heat[j]); // transfer heat array to LEDs
    }
    FastLED.show(); // display this frame
  }

//colorWipe  modified from Adafruit example to make it a state machine
// uses LEDs 32 to 40
void colorWipe(int index,byte state) {
  static int i =0; // used as state variable
  static byte firstLED = 32;
  static byte numLEDs = 8;
    leds[i+firstLED] = CRGB::Yellow;
    FastLED.show();
    i++;
  if(i >= numLEDs){
    i = 0;
    for(int j;j<numLEDs; j++) leds[j+firstLED] = CRGB::Black; // blank out strip
  }
}

 // rainbowCycle modified from Adafruit example to make it a state machine
 // uses LEDs 48 to 64
void rainbowCycle(int index,byte state) {
  static uint16_t j=0; // used as state variable
  static byte firstLED = 48;
  static byte numLEDs = 16;
    for(int i=0; i< numLEDs; i++) {
      leds[i+firstLED].setHSV( (((i * 256 / numLEDs) + j) & 255), 255, 255);
    }
    FastLED.show();
    j++;
    if(j >= 256*5) j=0;
}

1 Like

Hey Grumpy Mike,

Wow this is insane. Thank you so much! I'll try this out.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.