2 Different 8x8 MAX7219 Animations assigned to different buttons - Big Delay

Hi,
I am making a project with MAX7219 that essentially needs to show two different animations according to the button that is pressed. To achieve this I used a Switch Case. While it works I am having a significant amount of delay. Is there any solution?

void loop() {
  int buttonState1 = digitalRead(buttonPin1);  // Read the state of the first button
  int buttonState2 = digitalRead(buttonPin2);  // Read the state of the second button

  // Check the state of the first button
  switch (buttonState1) {
    case LOW:  // Button is pressed
      Serial.println("Button 1 pressed");
      runLoop1 = true;  // Set the flag to run Loop 1
      while (runLoop1 && buttonState2) {
        loop1();  // Execute Loop 1
        buttonState2 = digitalRead(buttonPin2);  // Update the state of the second button
      }
      runLoop1 = false;  // Reset the flag when the loop is done
      break;
    default:
      // Add your code for handling other states of button 1 here
      break;
  }

  // Check the state of the second button
  switch (buttonState2) {
    case LOW:  // Button is pressed
      Serial.println("Button 2 pressed");
      runLoop2 = true;  // Set the flag to run Loop 2
      while (runLoop2 && buttonState1) {
        loop2();  // Execute Loop 2
        buttonState1 = digitalRead(buttonPin1);  // Update the state of the first button
      }
      runLoop2 = false;  // Reset the flag when the loop is done
      break;
    default:
      // Add your code for handling other states of button 2 here
      break;
  }

  // Add a small delay to debounce the buttons
  delay(10);
}

Where is the rest of the code?

1 Like

That is not the correct way to use the switch() statement, use if() instead.

1 Like

in 97% of all cases the bug is caused outside that part of the code what a user thinks.
This is the reason why you should always post your complete sketch.

Without seeing your complete sketch all is just guessing.
It is most likely that your loop1() / loop2() are blocking
But we can't really say because it is unkown how your functions loop()1 / loop()2 look like

2 Likes

Here is the full code:

#include <LedControl.h>

const int buttonPin1 = 2;  // Pin for the first button
const int buttonPin2 = 3;  // Pin for the second button
const int DIN_PIN = 11;
const int CS_PIN = 10;
const int CLK_PIN = 13;
bool runLoop1 = false;  // Flag to indicate whether to run Loop 1
bool runLoop2 = false; 

const uint64_t sev[] = {/* Removed */};
const int sev_LEN = sizeof(sev)/8;

const uint64_t ok[] = {/* Removed */};
const int ok_LEN = sizeof(ok)/8;

const uint64_t ada[] = {/* Removed */};
const int ada_LEN = sizeof(ada)/8;

const uint64_t kalp[] = {/* Removed */};
const int kalp_LEN = sizeof(kalp)/8;

const uint64_t IMAGES[] = {/* Removed */};
const int IMAGES_LEN = sizeof(IMAGES) / 8;

LedControl display = LedControl(DIN_PIN, CLK_PIN, CS_PIN);

void setup() {
  display.clearDisplay(0);
  display.shutdown(0, false);
  display.setIntensity(0, 2);
  pinMode(buttonPin1, INPUT_PULLUP); // Set the first button pin as input with internal pull-up resistor
  pinMode(buttonPin2, INPUT_PULLUP); // Set the second button pin as input with internal pull-up resistor
}

void loop() {
  int buttonState1 = digitalRead(buttonPin1);  // Read the state of the first button
  int buttonState2 = digitalRead(buttonPin2);  // Read the state of the second button

  // Check the state of the first button
  switch (buttonState1) {
    case LOW:  // Button is pressed
      Serial.println("Button 1 pressed");
      runLoop1 = true;  // Set the flag to run Loop 1
      while (runLoop1 && buttonState2) {
        loop1();  // Execute Loop 1
        buttonState2 = digitalRead(buttonPin2);  // Update the state of the second button
      }
      runLoop1 = false;  // Reset the flag when the loop is done
      break;
    //default:
      // Add your code for handling other states of button 1 here
      break;
  }

  // Check the state of the second button
  switch (buttonState2) {
    case LOW:  // Button is pressed
      Serial.println("Button 2 pressed");
      runLoop2 = true;  // Set the flag to run Loop 2
      while (runLoop2 && buttonState1) {
        loop2();  // Execute Loop 2
        buttonState1 = digitalRead(buttonPin1);  // Update the state of the first button
      }
      runLoop2 = false;  // Reset the flag when the loop is done
      break;
    //default:
      // Add your code for handling other states of button 2 here
      break;
  }

  // Add a small delay to debounce the buttons
  delay(10);
}


void displayImage(uint64_t image) {
  for (int i = 0; i < 8; i++) {
    byte row = (image >> i * 8) & 0xFF;
    for (int j = 0; j < 8; j++) {
      display.setLed(0, i, j, bitRead(row, j));
    }
  }
}
int i = 0;

void loop1() {
  displayImage(sev[i]);
  if (++i >= sev_LEN ) {
    i = 0;
    delay(1000); // Add a delay after displaying SEVILION
    for (int j = 0; j < ok_LEN; j++) {
      displayImage(ok[j]);
      delay(200);
    }
    for (int j = 0; j < ada_LEN; j++) {
      displayImage(ada[j]);
      delay(200);
    }
    for (int j = 0; j < kalp_LEN; j++) {
      displayImage(kalp[j]);
      delay(500);
    }
  } else {
    delay(500);
  }
}

void loop2() {
  heartbeatEffect();
}

void heartbeatEffect() {
  for (int brightness = 0; brightness <= 15; brightness++) {
    display.setIntensity(0, brightness); // Adjust the brightness
    displayImage(IMAGES[0]);
    delay(50);
  }

  for (int brightness = 14; brightness >= 0; brightness--) {
    display.setIntensity(0, brightness); // Adjust the brightness
    displayImage(IMAGES[0]);
    delay(50);
  }
}

You are using for-loops with delay() both are blocking.

This means the for-loop must run completely through before other code can be executed.

You have to replace the for-loops by that natural loop that is always there:

void loop() itself.
The basic principle how you do this is explained here

If you are a beginner you will still have questions how to write this for your code.
Make a first attempt and in case it does not yet work ask again by always posting your complete sketch.

best regards Stefan

I managed to fix the issue partially. But now every loop works only once:

#include <LedControl.h>

const int buttonPin1 = 2, buttonPin2 = 3, DIN_PIN = 11, CS_PIN = 10, CLK_PIN = 13;
bool runLoop1 = false, runLoop2 = false;
const uint64_t sev[] = {/* Removed */};
const int sev_LEN = sizeof(sev) / 8;

const uint64_t ok[] = {/* Removed */};
const int ok_LEN = sizeof(ok) / 8;

const uint64_t ada[] = {/* Removed */};
const int ada_LEN = sizeof(ada) / 8;

const uint64_t kalp[] = {/* Removed */};
const int kalp_LEN = sizeof(kalp) / 8;

const uint64_t IMAGES[] = {/* Removed */};
const int IMAGES_LEN = sizeof(IMAGES) / 8;

enum AnimationState { IDLE, LOOP1, LOOP2, HEARTBEAT };
AnimationState currentState = IDLE;

LedControl display = LedControl(DIN_PIN, CLK_PIN, CS_PIN);

void setup() {
  display.clearDisplay(0);
  display.shutdown(0, false);
  display.setIntensity(0, 2);
  pinMode(buttonPin1, INPUT_PULLUP);
  pinMode(buttonPin2, INPUT_PULLUP);
}

void loop() {
  int buttonState1 = digitalRead(buttonPin1);
  int buttonState2 = digitalRead(buttonPin2);

  switch (currentState) {
    case IDLE:
      if (buttonState1 == LOW)
        currentState = LOOP1;
      else if (buttonState2 == LOW)
        currentState = LOOP2;
      break;

    case LOOP1:
      loop1();
      currentState = IDLE;
      break;
    case LOOP2:
      loop2();
      currentState = IDLE;
      break;
    case HEARTBEAT:
      heartbeatEffect();
      currentState = IDLE;
      break;
    default:
      currentState = IDLE;
      break;
  }

  delay(50);
}

void displayImage(uint64_t image) {
  for (int i = 0; i < 8; i++)
    for (int j = 0; j < 8; j++)
      display.setLed(0, i, j, bitRead((image >> i * 8) & 0xFF, j));
}

void loop1() {
  const uint64_t *loops[] = {sev, ok, ada, kalp};
  const int lens[] = {sev_LEN, ok_LEN, ada_LEN, kalp_LEN};
  const int delays[] = {500, 200, 200, 500};

  for (int l = 0; l < 4; l++) {
    for (int j = 0; j < lens[l]; j++) {
      displayImage(loops[l][j]);
      delay(delays[l]);
      if (digitalRead(buttonPin2) == LOW) {
        runLoop1 = false;
        return;
      }
    }
  }
}

void loop2() { heartbeatEffect(); }

void heartbeatEffect() {
  for (int brightness = 0; brightness <= 15; brightness++) {
    display.setIntensity(0, brightness);
    displayImage(IMAGES[0]);
    delay(50);
  }

  for (int brightness = 14; brightness >= 0; brightness--) {
    display.setIntensity(0, brightness);
    displayImage(IMAGES[0]);
    delay(50);
  }
}

No, there are still delay()s within for-loops. You don't seem to have fixed anything. Did you read the link posted by @StefanL38 ? Were you able to understand it?

As long as you are using for-loops the code

stays blocking

Sorry for inconvience. When I use the while loop I can't switch between different animations unless the while loop is finished. I tried multiple methods including one that I attached but none of them helped.

void heartbeatEffect2() {
  unsigned long startTime = millis();
  unsigned long elapsedTime = 0;

  const unsigned long duration = 30 * 60 * 1000; 
  while (digitalRead(buttonPin1) == HIGH){
    while (elapsedTime < duration) {
    // Check if button1 is pressed, and exit the loop if true


    for (int brightness = 0; brightness <= 15; brightness++) {
      display.setIntensity(0, brightness);
      displayImage(IMAGES[0]);
      delay(50);
    }

    for (int brightness = 14; brightness >= 0; brightness--) {
      display.setIntensity(0, brightness);
      displayImage(IMAGES[0]);
      delay(50);
    }

    // Update elapsed time
    elapsedTime = millis() - startTime;
  }
}

  }

Here is the last version of my code:

#include <LedControl.h>

const int buttonPin1 = 2, buttonPin2 = 3, DIN_PIN = 11, CS_PIN = 10, CLK_PIN = 13,buttonPin3 = 4;
bool runLoop1 = false, runLoop2 = false;
const uint64_t dakik[] = {
 //removed
};
const int dakik_LEN = sizeof(dakik)/8;

const uint64_t sev[] = {
   //removed
};
const int sev_LEN = sizeof(sev)/8;

const uint64_t ok[] = {
   //removed
};
const int ok_LEN = sizeof(ok)/8;

const uint64_t ada[] = {
   //removed
};
const int ada_LEN = sizeof(ada)/8;


const uint64_t kalp[] = {
  //removed
};
const int kalp_LEN = sizeof(kalp)/8;

const uint64_t IMAGES[] = {
   //removed
};
const int IMAGES_LEN = sizeof(IMAGES) / 8;
enum AnimationState { IDLE, LOOP1, LOOP2, LOOP3, HEARTBEAT }; // Added LOOP3
AnimationState currentState = IDLE;

LedControl display = LedControl(DIN_PIN, CLK_PIN, CS_PIN);

void setup() {
  display.clearDisplay(0);
  display.shutdown(0, false);
  display.setIntensity(0, 2);
  pinMode(buttonPin1, INPUT_PULLUP);
  pinMode(buttonPin2, INPUT_PULLUP);
  pinMode(buttonPin3, INPUT_PULLUP);
}

void loop() {
  int buttonState1 = digitalRead(buttonPin1);
  int buttonState2 = digitalRead(buttonPin2);
  int buttonState3 = digitalRead(buttonPin3);

  switch (currentState) {
    case IDLE:
      if (buttonState1 == LOW) currentState = LOOP1;
      else if (buttonState2 == LOW) currentState = LOOP2;
      else if (buttonState3 == LOW) currentState = LOOP3; // Check for button3 press
      break;

    case LOOP1: loop1(); currentState = IDLE; break;
    case LOOP2: loop2(); currentState = IDLE; break;
    case LOOP3: loop3(); currentState = IDLE; break; // Added case for LOOP3
    case HEARTBEAT: heartbeatEffect(); currentState = IDLE; break;
    default: currentState = IDLE; break;
  }

  delay(50);
}

void displayImage(uint64_t image) {
  for (int i = 0; i < 8; i++)
    for (int j = 0; j < 8; j++)
      display.setLed(0, i, j, bitRead((image >> i * 8) & 0xFF, j));
}

void loop1() {
  const uint64_t* loops[] = {sev, ok, ada, kalp};
  const int lens[] = {sev_LEN, ok_LEN, ada_LEN, kalp_LEN};
  const int delays[] = {500, 200, 200, 500};
  const int intensities[] = {10, 8, 8, 10}; // Adjust intensities as needed

  for (int l = 0; l < 4; l++) {
    display.setIntensity(0, intensities[l]); // Set intensity for the specific loop
    for (int j = 0; j < lens[l]; j++) {
      displayImage(loops[l][j]);
      delay(delays[l]);
      if (digitalRead(buttonPin2) == LOW) {
        runLoop1 = false;
        return;
      }
    }
  }
}

void loop2() { heartbeatEffect(); }
void loop3() { heartbeatEffect2(); }

void heartbeatEffect() {
  int i= 0;
  int buttonState2 = digitalRead(buttonPin2);
  while (i<5){
    for (int brightness = 0; brightness <= 15; brightness++) {
    display.setIntensity(0, brightness);
    displayImage(IMAGES[0]);
    delay(50);
  }

  for (int brightness = 14; brightness >= 0; brightness--) {
    display.setIntensity(0, brightness);
    displayImage(IMAGES[0]);
    delay(50);
  }
  i++;

  }
}

void heartbeatEffect2() {
  unsigned long startTime = millis();
  unsigned long elapsedTime = 0;
  //display.setIntensity(0, brightness);
  //isplayImage(dakik[0]);
  //delay(100);
  //display.clearDisplay(0);
  const unsigned long duration = 60 * 1000; 
  while (elapsedTime < duration) {
    for (int brightness = 0; brightness <= 15; brightness++) {
      display.setIntensity(0, brightness);
      displayImage(IMAGES[0]);
      delay(50);
    }

    for (int brightness = 14; brightness >= 0; brightness--) {
      display.setIntensity(0, brightness);
      displayImage(IMAGES[0]);
      delay(50);
    }

    elapsedTime = millis() - startTime;
  }
}

For example when switching to loop1 while loop3 is active, waiting one minute is necessary for the loop to finish. Unless I can't switch between animations.

Yes of course because while-loops are blocking too.
The loop runs through until the condition inside the parenthesis are no longer true
think word for word about the meaning of

while the IO-pin detects HIGH
stay inside the while-loop

while value of variable elapsedTime is smaller than value of variable duration
stay inside the while-loop

count up variable brightness starting from value 0 up to value 15
stay inside the for-loop

What is so hard about looking at this picture and read line by line?
including reading the added comments?

What is so hard about reading this picture


including reading the added comments?

the for-loop and the while-loop are

commented out

.
.
the for-loop and the while-loop are

deactivated

but instead there are lines of code
that demontrate how you can loop
including counting up non-blocking

best regards Stefan

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