Multiple LEDs w/out delay with Potentiometer

I've posted about this before and haven't been able to solve this problem. I've taken some time off from the code and gotten everything running except one part.

I've modified some example code so that my programming blinks 4 LEDs individually in sequence, the speed of the blinking controlled by a potentiometer and a digital input that shuts off the LED blinking loop until the button is released.

In the end I would like both the digital (button) and analog (potentiometer) to be running outside the LED sequence so that they can be adjusted/activated and immediately be read (rather than at the end of the loop).

Right now I have a delay(sensorValue) but I need it to be swapped with a blinkWithoutDelay style option.... the problem is that I can't figure it out and I'm sure it's asininely stupid and I'm just not seeing it from all the head to wall pounding.

The code is included below and any help with this would be hugely appreciated... Thank you in advance.

const int buttonPin = 2; // pin that the sensor is attached to
const int ledPin = 13; // pin that the LED is attached to
int buttonState = 0;
int sensorPin = 0;
int sensorValue = 0;

void setup() {
pinMode(ledPin, OUTPUT);
for (int thisPin = 2; thisPin < 8; thisPin++) {
pinMode(thisPin, OUTPUT);
}
}

void loop() {

sensorValue = analogRead(sensorPin);
buttonState = digitalRead(buttonPin);
if (buttonState == HIGH) {
digitalWrite(ledPin, HIGH);

}

else {
digitalWrite(ledPin,LOW);
for (int thisPin = 3; thisPin < 7; thisPin++) {
digitalWrite(thisPin, HIGH);

delay(sensorValue); // The delay timer section needs to be replaced
// with a sensor reading from the potentiometer
// so that this can vary and be a blink w/out delay
// format...

digitalWrite(thisPin, LOW);
}
}
}

Please see Blink Led Without Delay sample in learning section:

The procedure is very simple. In loop insted of delaying you check if time has come to do some action all the time:

long time = 0;
boolean timeHasCome = false;
void setup() {
      pinMode(0, INPUT);
}
void loop() {

      doReadings();
      
      timeHasCome = millis() - time >= 1000; // 1000 milliseconds equals 1 second
      if (timeHasCome) {
            // update timer
            time = millis();
            doSomething();
      }
      else {
            doSomethingElse();
      }

}

In this my example you can replace this 1000 milliseconds with your potentiometer value to do tests.

millis() returns a value how many milliseconds has passed away since your arduino booted up.

Thanks for the help, I've managed to pull my code apart and put it back together with your help... I've now successfully got one LED blinking with the potentiometer reading controlling timing of the blink.

Now I've just got to figure out how to make it go from one LED to 4 LEDs with the For Loop (knightryder code)-esque structure so that they blink sequentially rather than simultaneously.

In any case, thanks again... and here's the corrected code.

int sensorPin = 0; //Pot Pin
int sensorValue = 0; //Pot Sensor Value

const int ledPin = 4; //LED Pin
int ledState = LOW; //LED State

long time = 0;
boolean timeHasCome = false;

void setup() {
pinMode(0, INPUT);
pinMode(ledPin, OUTPUT);
}

void loop() {

sensorValue = analogRead(sensorPin);

timeHasCome = millis() - time >= sensorValue;
if (timeHasCome) {
time = millis();
digitalWrite(ledPin, HIGH);
}

else {
digitalWrite(ledPin, LOW);
}
}

Try such scenario:
enable led if millis() - time >= sensorValue / [number of led]
in code this could look like this (say, leds will be attached to pins 2; 3; 4; 5):
digitalWrite(2, (millis() - time >= sensorValue / 1));
digitalWrite(3, (millis() - time >= sensorValue / 2));
digitalWrite(4, (millis() - time >= sensorValue / 3));
digitalWrite(5, (millis() - time >= sensorValue / 4));

And don't forget to update variable of holding time each time when sensorValue / 1 <= millis() - time;

Thanks Zandis, I will try this out tonight when I get home.... sorry to be dense, I'm looking at the structure you posted and I'm a bit confused about where the, "update variable of holding time each time when sensorValue / 1 <= millis() - time;" portion would sit within the overall programming. Anyway, I'll take a look and see if I can finish this off before the day ends. Thanks again!!

So, the below code is what I put together tonight... I'm realizing it's not doing what I need, but I'm hoping it might be a step in the right direction.... The problem with this iteration of code is that all four LEDs flash at the same time.... while I need them to flash one after another in a loop, the speed of the step/flash being controlled by the analog sensor reading.

I'm not sure what to do next... I'm admittedly a bit lost with this as of tonight.

int sensorPin = 0; //Pot Pin
int sensorValue = 0; //Pot Sensor Value

int ledPins[] = {
3, 4, 5, 6 }; // an array of pin numbers to which LEDs are attached
int pinCount = 4; // the number of pins

long time = 0;
boolean timeHasCome = false;

void setup() {

int thisPin;
for (int thisPin = 0; thisPin < pinCount; thisPin++) {
pinMode(ledPins[thisPin], OUTPUT);
}
}

void loop() {

sensorValue = analogRead(sensorPin);

timeHasCome = millis() - time >= sensorValue;
if (timeHasCome) {
time = millis();
for (int thisPin = 0; thisPin < pinCount; thisPin++) {
digitalWrite(ledPins[thisPin], HIGH);
}
}
else {
for (int thisPin = 0; thisPin < pinCount; thisPin++) {
digitalWrite(ledPins[thisPin], LOW);
}
}
}

try such code and see if it works:

long time = 0;
int sensorPin = 0;
int sensorValue = 0;
int ledPins[] = { 3, 4, 5, 6 };

void setup() {

      pinMode(sensorPin, INPUT);
      
      for (int i = 0; i < sizeof(ledPins)/sizeof(ledPins[0]); i++)
            pinMode(ledPins[i], OUTPUT);
}

void loop() {

      // map analog reading to 0..1000 to be more accurate on delays
      sensorValue = map(analogRead(sensorPin), 0, 1023, 0, 1000);
      
      // turn leds on and off
      for (int i = 0; i < sizeof(ledPins)/sizeof(ledPins[0]); i++)
            digitalWrite(ledPins[i], millis() - time >= sensorValue / (i+1));
      
       // check if second has passed to update "timer"
      if (millis() - time >= sensorValue)
            time = millis();
            
}

Hi Zandis... thanks for the help... the code idea that you shared works halfway, but unfortunately not all the way, I've managed to mangle together code before that's similar in behavior, but never managed to get it working fully.

The snag is that the LEDs turn on sequentially, but unfortunately they all remain on until the last LED has been lit, then they all turn off together. With something like a ForLoop I can have the LEDs turn on and off, on after another, like a sequencer.....

I'm going to work a bit on the code today to see if I can get something running... Thank you again so much for the insight, I hate that I've managed to get myself all turned around on this, so I really appreciate the help immensely.

Nico

You might want to get the sequence right before considering this suggestion.

There are two timers in the Aduino which can generate interrupts roughly every 2mSec (e.g Timer/Counter2 Overflow).

You could write an "interrupt service routine" (ISR) or signal handler which is a function which gets called, in this case, when a timer is reset.

It would look like:
SIGNAL(TIMER2_OVF_vect) { ... }
or
ISR(TIMER2_OVF_vect) { ... }
where { ... } is the code you want to execute every 2 mSec.

You could use this to change the state of the LEDs.

This is reasonably quick, so the difference between holding a LED on for 100mSec and 102mSec is probably acceptable.

Every time you come into the ISR, the code decides what to do next. It is a bit like a flick-book, or sequence of frames, and you don't worry (much) about monitoring anything because that is in loop().

So, loop() monitors the button and potentiometer, and sets some variables (preferably boolean, char or byte) to values it derives from the button and analogue input.

Then your
ISR(TIMER2_OVF_vect) { ... }
uses those values to decide what to do.

A nice thing about this approach is monitoring the button and potentiometer is mostly independent of the LEDs sequence.

You can invent new, complex sequencing for the LEDs, and it won't change the buttons or potentiometer monitoring. You could change what is monitored, for example, reading values from a host PC. The changes that the LED sequencing would see are limited to the values that are set up for it.

If you become interested, post again. But I'd recommend you get the LED sequence working in a way that you like.

HTH
GB

The snag is that the LEDs turn on sequentially, but unfortunately they all remain on until the last LED has been lit

I thought this is the way knight rider does. :smiley:
Anyway, you can see the way it can be done now.

Thanks again Zandis, it's becoming clear, I'll sort it out tonight... is it a cultural crime to admit that I've never actually seen the show? TV-less childhood limits pop-culture references... I'd confused that being in the array example with the forloop example I was trying to tear apart for my uses.

@gbulmer... that's actually really interesting and helpful... and it's certainly likely to be something I try out in this round of programming (once things are sorted out and a bit clearer) and see what I can get. I'll post when I have a result from it all.

A useful way to think about animating some LEDs is to think of it as a sequence of frames, or as a flick book. Each frame is a still picture of which LEDs you want light and dark.

This may sound a bit bulky, and hard to program, but it is very flexible.

If you have a frame-count, the state of the LEDs will correspond to the frame within the sequence; the page within the flick-book.

Once you get the hang of this idea, you'll be able to make it much less code by using an array to hold the state (HIGH or LOW) for each LED, at each frame.
Then you can invent new LED effects by changing a few numbers.

the program will be roughly something like:

int leds[] = {3, 4, 5, 6};
#define NUMBER_OF_LEDS (sizeof(leds)/sizeof(int))

boolean flickbook[][NUMBER_OF_LEDS] = {
{ HIGH, LOW, LOW, LOW}, // one frame
{ HIGH, HIGH, LOW, LOW},
{ LOW, HIGH, HIGH, LOW},
{ LOW, LOW, HIGH, LOW},
{ LOW, LOW, HIGH, HIGH},
{ LOW, LOW, LOW, HIGH}
};
#define FRAMES (sizeof(flickbook)/(sizeof(flickbook[0])))

int sensorPin = 0;

void setup() {
for (int led=0; led<NUMBER_OF_LEDS; led++) { // set output pins for LEDs
pinMode(leds[led], OUTPUT);
}
}

void loop()
{
long time = millis();

for (int frame=0; frame<FRAMES; frame++) {
for (int led=0; led<NUMBER_OF_LEDS; led++) { // paint one frame
digitalWrite(leds[led], flickbook[frame][led]);
}
// completed one 'frame'
int sensorValue = analogRead(sensorPin);
while (sensorValue >= (millis() - time)) { // could be do .. while
sensorValue = analogRead(sensorPin); // keep checking
}
time = millis();
}
}

This can be easily expanded to many leds, and many frames, just expand the flickbook array.

Each time through loop() plays the entire 'movie'.

The flickbook can be compressed to be small (8x smaller), so you can get huge sequences within a program. It can even be stored as part of the program, allowing for 100's or even 1000's of frames.

Notes: I didn't use map() to adjust sensor values; the 2% error seemed acceptable, and trying to be simpler seemed preferable.
I didn't use "do { ... } while (...);" in case folks are unfamiliar with it (I normally would).
I didn't handle the button. You need some fun :wink:

HTH
GB

PS - WARNING, I've just typed this code in, and not run it. It likely contains bugs.
[edit]But, I have written this style of LED animation several times before, so it isn't likely a long way wrong ... :slight_smile:

Also, the body of the "for (int frame=0; ...) {}" would be lifted, and put into an interrupt service routine, and the handling of the sensor left in loop() [/edit]

Thanks GB... I worked out your version later in the day and it definitely performs the tasks needed, and in an especially effective manner. I've added into the code the mapping element and some other things.... Now to sort out the button code for turning off all LEDs and resetting the code to the first frame of the "flickbook" and I'll really have something that's performing the tasks I need it to. Thank you again for the insight and direction, it is greatly appreciated since LED behavior/performance with arduino is not my strong suit. One quick question, I've tried putting in the button with an if/else setup in the void loop(), but it doesn't go into effect until the full flickbook frame loop has run and then it activates and "freezes" the final flickbook frame. How do you get the button to immediately be read and acted upon? I've included the new code below...

const int buttonPin = 2;
const int ledPin1 = 13;
int buttonState = 0;

int leds[] = {3, 4, 5, 6, 7, 8, 9, 10};
#define NUMBER_OF_LEDS (sizeof(leds)/sizeof(int))

boolean flickbook[][NUMBER_OF_LEDS] = {
{ HIGH, LOW, LOW, LOW, LOW, LOW, LOW, LOW},
{ LOW, HIGH, LOW, LOW, LOW, LOW, LOW, LOW},
{ LOW, LOW, HIGH, LOW, LOW, LOW, LOW, LOW},
{ LOW, LOW, LOW, HIGH, LOW, LOW, LOW, LOW},
{ LOW, LOW, LOW, LOW, HIGH, LOW, LOW, LOW},
{ LOW, LOW, LOW, LOW, LOW, HIGH, LOW, LOW},
{ LOW, LOW, LOW, LOW, LOW, LOW, HIGH, LOW},
{ LOW, LOW, LOW, LOW, LOW, LOW, LOW, HIGH}
};

#define FRAMES (sizeof(flickbook)/(sizeof(flickbook[0])))

int sensorPin = 0;

void setup() {

pinMode(ledPin1, OUTPUT);
pinMode(buttonPin, INPUT);

for (int led=0; led<NUMBER_OF_LEDS; led++) {
pinMode(leds[led], OUTPUT);
}
}

void loop(){

buttonState = digitalRead(buttonPin);
if (buttonState == HIGH) {
digitalWrite(ledPin1, HIGH);
}
else {

long time = millis();

for (int frame=0; frame<FRAMES; frame++) {
for (int led=0; led<NUMBER_OF_LEDS; led++) {
digitalWrite(leds[led], flickbook[frame][led]);
}
int sensorValue = map(analogRead(sensorPin), 0, 1023, 0, 1000);
while (sensorValue >= (millis() - time)) {
sensorValue = analogRead(sensorPin);
}
time = millis();
}
}
}

nico

nicodemus - when you think about what is happening, you would probably like is to stop after each frame.
You probably don't want to stop part way through a frame as that could look a bit odd.

 for (int frame=0; frame<FRAMES; frame++) {
   for (int led=0; led<NUMBER_OF_LEDS; led++) {  
     digitalWrite(leds[led], flickbook[frame][led]);
   }
   int sensorValue = map(analogRead(sensorPin), 0, 1023, 0, 1000);
   while (sensorValue >= (millis() - time)) { 
       sensorValue = analogRead(sensorPin);   
   }
   time = millis();
 }
}

The code which draws each flickbook 'frame' is the

  for (int led=0; led<NUMBER_OF_LEDS; led++) {  
     digitalWrite(leds[led], flickbook[frame][led]);
  }

loop

You probably want to check the button before the sensorValue (from the potentiometer) is read, because reading the potentiometer could delay for as much as a second.

So, I'd suggest checking the button in between the two parts.

HTH
GB

Thanks GB! That makes perfect sense and it works really well in the code. Thank you again.

I'm trying to have the button value suspend/restart the led sequence. Right now I have the button lighting an LED on digital pin 12, but I don't have it interacting with the LEDs or the LED sequence pattern. Is there a way to have this button suspend the LED movement and then "restart" the LEDs in their pattern?

Also, when I'm looking at the code I can't help but wonder if there isn't a way to shift the code from looking for 8 frames to 4 frames, or 6 frames or 2... or what have you... basically adjusting the number of steps/frames/size of flickbook.... is that something that can be variable? I'm thinking it is... but I might be wrong about that.

Anyway, thanks again... it's great to have what was initially an idea actually looking like it can be a possibility/reality.

Thanks
nico

I'm trying to have the button value suspend/restart the led sequence. Right now I have the button lighting an LED on digital pin 12, but I don't have it interacting with the LEDs or the LED sequence pattern. Is there a way to have this button suspend the LED movement and then "restart" the LEDs in their pattern?

It might be worth looking at something simpler for a little.

It might be worth experimenting with the Blink example

You want something to:

  • stop the program going any further when a button is pressed
  • remain at the same place waiting for the button to be released

So, you could try to do that in the blink program, which looks like:

void loop()
{
digitalWrite(ledPin, HIGH); // set the LED on
delay(1000); // wait for a second

/* ------- try holding the program from going any further here ---- */

digitalWrite(ledPin, LOW); // set the LED off
delay(1000); // wait for a second
}

You know how to detect a pressed button.

So you need to detect when it is released.
One way to do that is something like

buttonState = digitalRead(buttonPin);
while (buttonState == HIGH) {
buttonState = digitalRead(buttonPin);
}

This keeps checking the pin, and stays checking, until the button is released.

This might have a little glitch with button bounce, where the button makes contact. So if this doesn't seem to stop, look at the Debounce example.

Once it is clear how to stop and hold, just cut and past that piece into your whole program.

Also, when I'm looking at the code I can't help but wonder if there isn't a way to shift the code from looking for 8 frames to 4 frames, or 6 frames or 2... or what have you... basically adjusting the number of steps/frames/size of flickbook.... is that something that can be variable?

What do you want to happen? Do you want to add or remove some frames in the code, or somehow tell the program to change the number of frames it plays while it is running?

This bit of code controls how many frames are displayed for (int frame=0; frame<FRAMES; frame++)
the value of FRAMES sets the last frame shown. So if you use a variable here, and change its value, that will change the number of frames shown before starting again.

HTH
GB

Thanks again!! I've got everything working in the code now... including the stepping sequence length adjustment (via a switch code using a potentiometer value). I've just got one snag left in the code, and that lies in having a button that turns off all leds when pushed down and restarts the led sequence back at step one when it is released. I'm not really sure how to sort that out though, I've been stabbing around at it all morning and it doesn't seem to be clicking for me. Also, is there any chance that the timing is off in the sequence (of the last LED)? Or is it just a bit of visual trickery of my eyes?

Anyway, this is what I've got now running, any final help would be hugely appreciated and thank you again for everything, it's been really amazing these last 24 hours to have this click into place.

Nico

Ooops... here's the code....

const int buttonPin = 2;     
const int ledPin =  12;     
int buttonState = 0; 

int leds[] = {3, 4, 5, 6, 7, 8, 9, 10};
#define NUMBER_OF_LEDS (sizeof(leds)/sizeof(int))

boolean flickbook[][NUMBER_OF_LEDS] = {
{  HIGH,  LOW,  LOW,  LOW,  LOW,  LOW,  LOW,  LOW},       
{  LOW,  HIGH,  LOW,  LOW,  LOW,  LOW,  LOW,  LOW},
{  LOW,  LOW,  HIGH,  LOW,  LOW,  LOW,  LOW,  LOW},
{  LOW,  LOW,  LOW,  HIGH,  LOW,  LOW,  LOW,  LOW},
{  LOW,  LOW,  LOW,  LOW,  HIGH,  LOW,  LOW,  LOW},      
{  LOW,  LOW,  LOW,  LOW,  LOW,  HIGH,  LOW,  LOW},
{  LOW,  LOW,  LOW,  LOW,  LOW,  LOW,  HIGH,  LOW},
{  LOW,  LOW,  LOW,  LOW,  LOW,  LOW,  LOW,  HIGH}
};

#define FRAMES (sizeof(flickbook)/(sizeof(flickbook[0])))

int sensorPin = 0;

const int sensorMin = 0;      
const int sensorMax = 1023;    

void setup()   {                
    for (int led=0; led<NUMBER_OF_LEDS; led++) {  
    pinMode(leds[led], OUTPUT);
    pinMode(ledPin, OUTPUT);  
    pinMode(buttonPin, INPUT); 
  }    
}

void loop(){
  int sensorReading1 = analogRead(2);
  int range1 = map(sensorReading1, sensorMin, sensorMax, 0, 7);
  
   switch (range1) {
   case 0:    {
    long time = millis();
  
    for (int frame=0; frame<1; frame++) {
    for (int led=0; led<NUMBER_OF_LEDS; led++){  
    digitalWrite(leds[led], flickbook[frame][led]);
}
   (buttonState = digitalRead(buttonPin));
   while (buttonState == HIGH) {
   buttonState = digitalRead(buttonPin);
   digitalWrite(ledPin, LOW);
} 
   int sensorValue = map(analogRead(sensorPin), 0, 1023, 0, 1000);
   while (sensorValue >= (millis() - time)) { 
   sensorValue = analogRead(sensorPin);   
   }
   time = millis();
    }
   }
   break;
   
   case 1:    {
   long time = millis();
  
   for (int frame=0; frame<2; frame++) {
   for (int led=0; led<NUMBER_OF_LEDS; led++){  
   digitalWrite(leds[led], flickbook[frame][led]);
   }
      (buttonState = digitalRead(buttonPin));
   while (buttonState == HIGH) {
   buttonState = digitalRead(buttonPin);
   digitalWrite(ledPin, LOW);
} 
   int sensorValue = map(analogRead(sensorPin), 0, 1023, 0, 1000);
   while (sensorValue >= (millis() - time)) { 
   sensorValue = analogRead(sensorPin);   
   }
   time = millis();
   }
   }
   break;
   
   case 2:    {
   long time = millis();
  
   for (int frame=0; frame<3; frame++) {
   for (int led=0; led<NUMBER_OF_LEDS; led++){  
   digitalWrite(leds[led], flickbook[frame][led]);
   }
      (buttonState = digitalRead(buttonPin));
   while (buttonState == HIGH) {
   buttonState = digitalRead(buttonPin);
   digitalWrite(ledPin, LOW);
} 
   int sensorValue = map(analogRead(sensorPin), 0, 1023, 0, 1000);
   while (sensorValue >= (millis() - time)) { 
   sensorValue = analogRead(sensorPin);   
   }
   time = millis();
   }
   }
   break;
   
      case 3:    {
   long time = millis();
  
   for (int frame=0; frame<4; frame++) {
   for (int led=0; led<NUMBER_OF_LEDS; led++){  
   digitalWrite(leds[led], flickbook[frame][led]);
   }
      (buttonState = digitalRead(buttonPin));
   while (buttonState == HIGH) {
   buttonState = digitalRead(buttonPin);
   digitalWrite(ledPin, LOW);
} 
   int sensorValue = map(analogRead(sensorPin), 0, 1023, 0, 1000);
   while (sensorValue >= (millis() - time)) { 
   sensorValue = analogRead(sensorPin);   
   }
   time = millis();
   }
   }
   break;
   
      case 4:    {
   long time = millis();
  
   for (int frame=0; frame<5; frame++) {
   for (int led=0; led<NUMBER_OF_LEDS; led++){  
   digitalWrite(leds[led], flickbook[frame][led]);
   }
      (buttonState = digitalRead(buttonPin));
   while (buttonState == HIGH) {
   buttonState = digitalRead(buttonPin);
   digitalWrite(ledPin, LOW);
} 
   int sensorValue = map(analogRead(sensorPin), 0, 1023, 0, 1000);
   while (sensorValue >= (millis() - time)) { 
   sensorValue = analogRead(sensorPin);   
   }
   time = millis();
   }
   }
   break;
   
      case 5:    {
   long time = millis();
  
   for (int frame=0; frame<6; frame++) {
   for (int led=0; led<NUMBER_OF_LEDS; led++){  
   digitalWrite(leds[led], flickbook[frame][led]);
   }
      (buttonState = digitalRead(buttonPin));
   while (buttonState == HIGH) {
   buttonState = digitalRead(buttonPin);
   digitalWrite(ledPin, LOW);
} 
   int sensorValue = map(analogRead(sensorPin), 0, 1023, 0, 1000);
   while (sensorValue >= (millis() - time)) { 
   sensorValue = analogRead(sensorPin);   
   }
   time = millis();
   }
   }
   break;
   
         case 6:    {
   long time = millis();
  
   for (int frame=0; frame<7; frame++) {
   for (int led=0; led<NUMBER_OF_LEDS; led++){  
   digitalWrite(leds[led], flickbook[frame][led]);
   }
      (buttonState = digitalRead(buttonPin));
   while (buttonState == HIGH) {
   buttonState = digitalRead(buttonPin);
   digitalWrite(ledPin, LOW);
} 
   int sensorValue = map(analogRead(sensorPin), 0, 1023, 0, 1000);
   while (sensorValue >= (millis() - time)) { 
   sensorValue = analogRead(sensorPin);   
   }
   time = millis();
   }
   }
   break;
   
         case 7:    {
   long time = millis();
  
   for (int frame=0; frame<8; frame++) {
   for (int led=0; led<NUMBER_OF_LEDS; led++){  
   digitalWrite(leds[led], flickbook[frame][led]);
   }
      (buttonState = digitalRead(buttonPin));
   while (buttonState == HIGH) {
   buttonState = digitalRead(buttonPin);
   digitalWrite(ledPin, LOW);
} 
   int sensorValue = map(analogRead(sensorPin), 0, 1023, 0, 1000);
   while (sensorValue >= (millis() - time)) { 
   sensorValue = analogRead(sensorPin);   
   }
   time = millis();
   }
   }
   break;
    
   }
  }

Goodness, you have been busy!

There is a very regular pattern in the program:

int range1 = map(sensorReading1, sensorMin, sensorMax, 0, 7);

switch (range1) {
case 0: { ... for (int frame=0; frame<1; frame++) { ...
...
case 1: { ... for (int frame=0; frame<2; frame++) { ...
...
case 2: { ... for (int frame=0; frame<3; frame++) { ...
...

The number in the case part of the switch statement, e.g. 'case 1:' is the value of range1.

The value which controls the for loop, e.g.
for (int frame=0; frame<2; ...
is range1+1.
It is okay to use arithmetic when comparing stuff, so
frame<(range1+1)
is okay.

So all of the for loops could be rewritten as
for (int frame=0; frame<(range1+1); frame++)
This makes them all the same.

Having a ponder on this, and make sure there is a copy of the working program before changing anything. I think the program can be made much shorter, while still doing everything needed, which will also help for the next bit ... answering your other questions.

HTH
GB

nicodemus, would you do a small favour?

Please modify your longer post, select all the code and click the # icon in the editor. This turns it into a shorter block, called Code. It makes the post shorter, and easier for folks to read within the thread. Is that okay?

GB