ESP32 Crashes when turning rotary encoder too many time consecutively

Using this guide (Build the Muffsy Relay Input Selector - Muffsy Phono Kits) I built a ESP32 based relay switch selector using the "ESP-WROOM-32" specifically I just modified the code that was provided a bit to incorporate an LCD screen to Display the selected input. I will say I am a bit of a novice so any help will be greatly appreciated ! When turning the rotary encoder too many times it present me with this crash in the serial monitor:

Rotational encoder turned clockwise
E (18906) timer_group: timer_enable_intr(382): HW TIMER NEVER INIT ERROR
E (18906) timer_group: timer_get_config(329): HW TIMER NEVER INIT ERROR
E (18907) timer_group: timer_get_alarm_value(167): HW TIMER NEVER INIT ERROR
E (18914) timer_group: timer_isr_callback_add(227): HW TIMER NEVER INIT ERROR
Guru Meditation Error: Core  1 panic'ed (LoadProhibited). Exception was unhandled.

Core  1 register dump:
PC      : 0x40081652  PS      : 0x00060033  A0      : 0x400846e4  A1      : 0x3ffbef4c  
A2      : 0x3ffb8ee8  A3      : 0x3ffbdcb4  A4      : 0x00000000  A5      : 0x400880f0  
A6      : 0x00000003  A7      : 0x00060c23  A8      : 0x00000001  A9      : 0x3ffbef0c  
A10     : 0x00000001  A11     : 0x3ffc1c08  A12     : 0x3ffc1c0c  A13     : 0x00060023  
A14     : 0x00060021  A15     : 0x00000001  SAR     : 0x00000020  EXCCAUSE: 0x0000001c  
EXCVADDR: 0x000000a1  LBEG    : 0x400861a4  LEND    : 0x400861af  LCOUNT  : 0xffffffff  


Backtrace:0x4008164f:0x3ffbef4c |<-CORRUPTED

ELF file SHA256: 0000000000000000

Rebooting...
ets Jun  8 2016 00:22:57

rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0030,len:1344
load:0x40078000,len:13516
load:0x40080400,len:3604
entry 0x400805f0

I will also include the code to help with finding the issue, I do apologize if the formatting of this post is off.

/*  Relay Input Selector
 *      
 *  Control relays using IR and rotary encoder
 *  Control external power to amp using IR and push button
 *  
 */

 /*
  * powerState:
  * 
  *   0: Boot
  *     powerOn()
  *       startup procedure
  *       read NVRAM (relayCount)
  *       set relays to off (previousRelay = relayCount)
  *       set power amp to off, SSR = LOW
  *       
  *   1: Powered ON
  *       turn on power button LED
  *       set power amp to on, SSR = HIGH
  *       trigger relayOn(): previousRelay = relayCount + 1
  *     rotaryEncoder()
  *       increases or decreases relayCount depending on rotational direction
  *       pushbutton: Power ON/OFF
  *       does only Power ON if powerState == 2
  *     irRemote()
  *       input up/down
  *       input direct (buttons 1-5)
  *       power on/off
  *       does only Power ON if powerState == 2
  *     relayOn()
  *       activates relays based on the relayCount
  *       handles relayCount too high or low
  *     powerControl()
  *       read power button, set powerState accordingly
  *       
  *    2: Powered OFF
  *     turn off all relays
  *     set power amp to off (SSR = LOW)
  *     powerControl()
  *       read power button, set powerState == 1 if pushed
  *     irRemote()
  *       read power button, set powerState == 1 if pushed
  */

 // Libraries
 #include <IRremote.h> // IR Remote Library
 #include <EEPROM.h> // EEPROM Library
 #include <Wire.h> // I2C Connection 
#include <LiquidCrystal_I2C.h> 



LiquidCrystal_I2C lcd(0x27, 16, 2);//Setting LCD up 

 //  Size: 1 (relayCount)
 #define EEPROM_SIZE 1

 // Variables, pin definitions

 // Onboard LED/Power LED
 #define LED 2

 // IR Receiver pin and setup
#define IR_Recv 36
IRrecv irrecv(IR_Recv);
 decode_results results;
  
 // Power button
 #define poweronButton 5

 // Pins for the rotary encoder:
 #define rotaryA 35 // DT
 #define rotaryB 34 // CLK

 // Relays
 #define R1 16
 #define R2 12
 #define R3 27
 #define R4 33
 #define R5 32

 //Solid State Relay
 #define SSR 17

 // Mute LED
 #define muteLed 4

 // Rotary Encoder variables
 int counter = 0; 
 int previous = 0;
 int aState;
 int aPreviousState;  

 // Relay Array
 int relays[] = {16, 12, 27, 33, 32};

 // Relay variables
 int relayCount;
 int previousRelay;
 int relayNumber;

 // Power/Mute variables
 int powerState;
 int buttonState = 1;       // the current reading from the input pin
 int lastButtonState = 1;   // the previous reading from the input pin
 unsigned long lastDebounceTime = 0;  // the last time the output pin was toggled
 unsigned long debounceDelay = 50;    // the debounce time; increase if the output flickers
 int mute = 0; // Mute on/off (1/0)

 // Setup
 void setup() { 

 // Initializing LCD
  lcd.init();

  

// Clearing anything on the LCD
  lcd.clear();

   // Power button
   pinMode (poweronButton,INPUT_PULLUP);
   
   // Onboard LED
   pinMode (LED,OUTPUT);

   // Mute LED
   pinMode (muteLed,OUTPUT);
   
   // Rotary Encoder
   pinMode (rotaryA,INPUT);
   pinMode (rotaryB,INPUT);

   // Reads the initial state of the rotaryA
   aPreviousState = digitalRead(rotaryA); 

   // Relays
   pinMode (R1,OUTPUT);
   pinMode (R2,OUTPUT);
   pinMode (R3,OUTPUT);
   pinMode (R4,OUTPUT);
   pinMode (R5,OUTPUT);
   pinMode (SSR,OUTPUT);

   // Relay variables
   EEPROM.begin(EEPROM_SIZE);
   relayCount = EEPROM.read(0);
   previousRelay = relayCount + 1; // Start out not matching relayCount???

    //Start the IR Receiver
  pinMode(IR_Recv, INPUT_PULLDOWN);
  irrecv.enableIRIn(true); // Starts the receiver
   
   /*
    * powerStates:
      * 0: Powering on
      * 1: Powered on
      * 2: Powered off
    */
   powerState = 0;
   mute = 0; // Mute on/off (1/0)

   // Serial monitor
   Serial.begin (115200);
 } 

 /*
 * Main program
 */
 void loop() {
  if (powerState == 0) {
    powerOn();
  } else if (powerState == 1){
    relayOn();
    rotaryEncoder();// Include Push = MUTE
    LCD(); //Display input source 
    //lcd.backlight();
    powerControl(); // Read power button
    irRemote(); // Up, Down, Direct, Volume, MUTE, Power
  } else {
    rotaryEncoder(); // Rotary push button is temporarily power button???
    powerControl(); // Read power button
    irRemote(); // Power on/off only
  }
 }

 /*
  * Turn on current relay
  */
void relayOn() {
  
  // If relayCount has changed: Turn on the selected relay (next, previous, direct)
  // If previousRelay has changed: Turn on the last selected relay
  if (relayCount != previousRelay) {

    // Rollover 3 or 0
    if (relayCount > 3) {
      relayCount = 0;
    } else if (relayCount < 0) {
      relayCount = 3;
    }

    // Turn off all relays, then turn on relayCount
    relayOff();
    digitalWrite(relays[relayCount], HIGH);

    // Stop IR, write relayCount to memory, start IR
    irrecv.enableIRIn(false);
    EEPROM.write(0,relayCount);
    EEPROM.commit();
    irrecv.enableIRIn(true);
    Serial.print(" Written \"relayCount = ");
    Serial.print(relayCount);
    Serial.println("\" to save slot 0");
      
   // Reset counters, output relayNumber
   previousRelay = relayCount;
   relayNumber = relayCount + 1;
   Serial.print("Activated relay #");
   Serial.println(relayNumber);
   Serial.println();

   // If circuit is muted, unmute
   if (mute == 1) {
    digitalWrite(muteLed,HIGH);
    Serial.println("Waiting 1.5 seconds before turning off mute");
    delay(1500);
    toggleMute();

   }
  }
}

/*
 * Power on amplifier
 */
void powerOn() { // Only called if powerState is 0 (Powering on)
    Serial.println("The Relay Input Selector has woken up!\n");
    Serial.print(" ** Reading saved relay state from NVRAM: ");
    Serial.println(relayCount);
    digitalWrite(relays[4],LOW);
    mute = 1;
    Serial.println("\n ** Mute Relay turned ON");
    Serial.println(" ** All input relays are turned OFF");
    relayOff();
    Serial.println(" ** Solid State Relay is turned OFF\n");
    digitalWrite (SSR,LOW);
    Serial.println(" ** Startup completed - waiting for Power ON\n");
    Serial.println("       -------------------------\n");
    
    // Set powerState to 2 (Powered off):
    powerState = 2;
}

/*
 * Read powerbutton, turn on or off
 */
void toggleMute() {
    if (mute == 0) {
      Serial.println(" Mute relay turned ON\n");
      digitalWrite(relays[4],LOW);
      if (powerState == 1){
        digitalWrite(muteLed,HIGH);
      }
      mute = 1;
    } else {
      Serial.println(" Mute relay turned OFF\n");
      digitalWrite(relays[4],HIGH);
      digitalWrite(muteLed,LOW);
      mute = 0;
    }
}


/*
 * Read powerbutton, turn on or off
 */
void powerControl() {
    int reading = digitalRead(poweronButton);

    if (reading != lastButtonState) {
      lastDebounceTime = millis();
    }

    if ((millis() - lastDebounceTime) > debounceDelay) {
    // whatever the reading is at, it's been there for longer than the debounce
    // delay, so take it as the actual current state:

    // if the button state has changed:
    if (reading != buttonState) {
      buttonState = reading;

      // only toggle the LED if the new button state is HIGH
      if (buttonState == 1) {
        Serial.println(" Power button pushed");
        
        if (powerState == 1) { // Turning power OFF: All relays OFF, power amp OFF
          powerState = 2;
          digitalWrite (SSR,LOW);
          digitalWrite (LED,LOW);
          lcd.noBacklight();
          relayOff();
          if (mute == 0) {
            toggleMute();
          }
          Serial.println(" Solid State Relay OFF");
          Serial.println(" Power OFF\n");
          
        } else if (powerState == 2) { // Turning power ON: Last selected relay ON, power amp ON
          powerState = 1;
          digitalWrite (SSR,HIGH);
          lcd.backlight();
          digitalWrite (LED,HIGH);
          previousRelay = relayCount + 1; // Trigger relayOn()
          Serial.println(" Power ON");
          Serial.println(" Solid State Relay ON\n");
        } 
      } 
    }
  }
  lastButtonState = reading;
}

 /*
  * IR Remote
  */
void irRemote() { // Start irRemote function

    // Decode the infrared input
      // Decodes the infrared input
  if (irrecv.decode(&results)) {
    long int decCode = results.value;
    Serial.print(" Received IR code: ");
    Serial.print(decCode);
    Serial.println();
    // Switch case to use the selected remote control button
    switch (results.value) { // Start switch/case
      
      case 16724175: // Relay 1
        {
          Serial.println(" Button \"1\"");
          if (powerState == 1) {
            relayCount = 0;
          } else {
            Serial.println(" Powered off, doing nothing...\n");
          }
          break;
        }

      case 16718055: // Relay 2
        {
          Serial.println(" Button \"2\"");
          if (powerState == 1) {
            relayCount = 1;
          } else {
            Serial.println(" Powered off, doing nothing...\n");
          }
          break;
        }

      case 16743045: // Relay 3
        {
          Serial.println(" Button \"3\"");
          if (powerState == 1) {
            relayCount = 2;
          } else {
            Serial.println(" Powered off, doing nothing...\n");
          }
          break;
        }

      case 16716015: // Relay 4
        {
          Serial.println(" Button \"4\"");
          if (powerState == 1) {
            relayCount = 3;
          } else {
            Serial.println(" Powered off, doing nothing...\n");
          }
          break;
        }

      case 16769565: // Mute
        {
          Serial.println(" Button \"Mute\"");
          if (powerState == 1) {
            toggleMute();
          } else {
            Serial.println(" Powered off, doing nothing...\n");
          }
          break;
        }

      case 16748655: // Channel UP
        {
          Serial.println(" Button \"UP\"");
          if (powerState == 1) {
            relayCount++;
          } else {
            Serial.println(" Powered off, doing nothing...\n");
          }
          break;
        }

      case 16754775: // Channel DOWN
        {
          Serial.println(" Button \"DOWN\"");
          if (powerState == 1) {
            relayCount--;
          } else {
            Serial.println(" Powered off, doing nothing...\n");
          };
          break;
        }

      case 16753245: // Power button
        {
          Serial.println("Button \"POWER\"");
          if (powerState == 1) {
            powerState = 2;
            digitalWrite (SSR,LOW);
            digitalWrite (LED,LOW);
            lcd.noBacklight();
            relayOff();
            if (mute == 0) {
              toggleMute();
            }
            Serial.println(" Solid State Relay OFF");
            Serial.println(" Power OFF\n");
            
          } else {
            powerState = 1;
            digitalWrite (SSR,HIGH);
            digitalWrite (LED,HIGH);
            lcd.backlight();
            previousRelay = relayCount + 1; // Trigger relayOn()
            Serial.println(" Power ON");
            Serial.println("Solid State Relay ON\n");
          }
          break;
        }

      default:
      {
        Serial.println("Going back to waiting for IR remote keypress\n");
      }
    } // End switch/case
    irrecv.resume(); // Receives the next value from the button you press
  }
    
  } // End irRemote function

  
 /*
  * Mute (turn off all relays)
  */
   void relayOff() {
    for (int off = 0; off <= 3; off++) {
      digitalWrite(relays[off], LOW);
      }
   }
void LCD(){
if (relayCount == 0){
 // Serial.println("Bluetooth Input");
  lcd.clear(); 
  lcd.setCursor(4,0);
  lcd.print("BLUETOOTH");
  //delay(10);
 
}
if (relayCount == 1){
  //Serial.println("Optical 1 Input ");
  lcd.clear();  
  lcd.setCursor(7,0);
  lcd.print("OPT1");
  //delay(10);
  
}
if (relayCount == 2){
  //Serial.println("Optical 2 Input ");
  lcd.clear();  
  lcd.setCursor(7,0);
  lcd.print("OPT2");
  //delay(10);
  
}
if (relayCount == 3){
  //Serial.println("RCA Input ");
  lcd.clear();
  lcd.setCursor(7,0);
  lcd.print("RCA");
  //delay(10);
  
  }   
}

 /*
 * Rotary Encoder Control of Relays
 */
 void rotaryEncoder() { 
   aState = digitalRead(rotaryA); // Reads the "current" state of the rotaryA
   
   // If the previous and the current state of the rotaryA are different, that means a Pulse has occured
   if (aState != aPreviousState){  

     // If the rotaryB state is different to the rotaryA state, that means the encoder is rotating clockwise
     if (digitalRead(rotaryB) != aState) { 
       counter ++;
     } else {
       counter --;
     }
    }

   // What to do if rotating Right of Left 
   if (previous != counter) {
     if (counter > 1) { // Since the encoder gives two signals when turning
       Serial.print(" Rotational encoder turned ");
       Serial.println("clockwise");

       if (powerState == 1) {
        // Increase relayCount
        relayCount++;
       } else {
        Serial.println(" Powered off, doing nothing...\n"); // Powered off???
       }
       
     } else if (counter < -1) { // Since the encoder gives two signals when turning
       Serial.print(" Rotational encoder turned ");
       Serial.println("counter-clockwise");
       
       if (powerState == 1) {
        // Increase relayCount
        relayCount--;
       } else {
        Serial.println("Powered off, doing nothing...\n"); // Powered off???
       }
     }
   }

   // Reset counters
   previous = counter; 
   if (counter < -1) {
    counter = 0;
    previous = 0;
   } else if (counter > 1){
    counter = 0;
    previous = 0;
   }
    
   // Updates the previous state of the rotaryA with the current state
   aPreviousState = aState; 
 }

The relayCount variable is shared between an interrupt service routine and the main program, but it is not protected correctly. It should be an std::atomic_int, or at least carry a volatile qualifier. And you should make a copy for use in your main program: Right now, an interrupt can alter its value between the bounds checking and the usage of relayCount.

Thanks for the reply! To be honest I don't really know how to proceed, I haven't had much experience but from what it sounds like should I make the "int relayCount" volatile or declare it as an atomic_int before the Void setup ()?

so far i see that GPIO_NUM_32 and GPIO_NUM_33 are being set as outputs., For sure GPIO_NUM_33 s onthe ESP32's portB which is input only.

At this point it would be best to recode the use of EEPROM and use ESP32 Save Data Permanently using Preferences Library | Random Nerd Tutorials instead.

Put the backtrace info the ESP Exception Decoder, post the decoded message.

Where has the ISR been defined at?

What was the last thing you were working on with the code?

I looked and the GPIO 32 and 33 on the wroom32 esp32 are both input/output (ESP32 Pinout Reference: Which GPIO pins should you use? | Random Nerd Tutorials). I'll look into the link you sent thank you ! I decoded the message and once I changed "int relays" and "relaycounter" to volatile int's the crashing stopped. I switched from a 16x2 screen to a oled 128 x 32 I changed the code a bit to include the right libraries and upon testing the rotary encoders responsiveness to turning went down and it doesn't register every step.

The current code is:

/*  Relay Input Selector
 *      
 *  Control relays using IR and rotary encoder
 *  Control external power to amp using IR and push button
 *  
 */

 /*
  * powerState:
  * 
  *   0: Boot
  *     powerOn()
  *       startup procedure
  *       read NVRAM (relayCount)
  *       set relays to off (previousRelay = relayCount)
  *       set power amp to off, SSR = LOW
  *       
  *   1: Powered ON
  *       turn on power button LED
  *       set power amp to on, SSR = HIGH
  *       trigger relayOn(): previousRelay = relayCount + 1
  *     rotaryEncoder()
  *       increases or decreases relayCount depending on rotational direction
  *       pushbutton: Power ON/OFF
  *       does only Power ON if powerState == 2
  *     irRemote()
  *       input up/down
  *       input direct (buttons 1-5)
  *       power on/off
  *       does only Power ON if powerState == 2
  *     relayOn()
  *       activates relays based on the relayCount
  *       handles relayCount too high or low
  *     powerControl()
  *       read power button, set powerState accordingly
  *       
  *    2: Powered OFF
  *     turn off all relays
  *     set power amp to off (SSR = LOW)
  *     powerControl()
  *       read power button, set powerState == 1 if pushed
  *     irRemote()
  *       read power button, set powerState == 1 if pushed
  */

 // Libraries
 #include <IRremote.h> // IR Remote Library
 #include <Adafruit_SSD1306.h>
 #include <EEPROM.h> // EEPROM Library
 #include <Wire.h> // I2C Connection 
 //#include <LiquidCrystal_I2C.h> 
 #include <SPI.h> 

 

#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);//Setting LCD up 

 //  Size: 1 (relayCount)
 #define EEPROM_SIZE 1

 // Variables, pin definitions

 // Onboard LED/Power LED
 #define LED 2

 // IR Receiver pin and setup
#define IR_Recv 36
IRrecv irrecv(IR_Recv);
 decode_results results;
  
 // Power button
 #define poweronButton 5

 // Pins for the rotary encoder:
 #define rotaryA 35 // DT
 #define rotaryB 34 // CLK

 // Relays
 #define R1 16
 #define R2 12
 #define R3 27
 #define R4 33
 #define R5 32

 //Solid State Relay
 #define SSR 17

 // Mute LED
 #define muteLed 4

 // Rotary Encoder variables
 int counter = 0; 
 int previous = 0;
 int aState;
 int aPreviousState;  

 // Relay Array
 volatile int relays[] = {16, 12, 27, 33, 32};

 // Relay variables
 volatile int relayCount;
 int previousRelay;
 int relayNumber;

 // Power/Mute variables
 int powerState;
 int buttonState = 1;       // the current reading from the input pin
 int lastButtonState = 1;   // the previous reading from the input pin
 unsigned long lastDebounceTime = 0;  // the last time the output pin was toggled
 unsigned long debounceDelay = 50;    // the debounce time; increase if the output flickers
 int mute = 0; // Mute on/off (1/0)

 // Setup
 void setup() { 

 // Initializing LCD
  
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);// Turningn on LCD Backlight
  //lcd.backlight();

display.clearDisplay();// Clearing anything on the LCD
 

   // Power button
   pinMode (poweronButton,INPUT_PULLUP);
   
   // Onboard LED
   pinMode (LED,OUTPUT);

   // Mute LED
   pinMode (muteLed,OUTPUT);
   
   // Rotary Encoder
   pinMode (rotaryA,INPUT);
   pinMode (rotaryB,INPUT);

   // Reads the initial state of the rotaryA
   aPreviousState = digitalRead(rotaryA); 

   // Relays
   pinMode (R1,OUTPUT);
   pinMode (R2,OUTPUT);
   pinMode (R3,OUTPUT);
   pinMode (R4,OUTPUT);
   pinMode (R5,OUTPUT);
   pinMode (SSR,OUTPUT);

   // Relay variables
   EEPROM.begin(EEPROM_SIZE);
   relayCount = EEPROM.read(0);
   previousRelay = relayCount + 1; // Start out not matching relayCount???

    //Start the IR Receiver
  pinMode(IR_Recv, INPUT_PULLDOWN);
  irrecv.enableIRIn(true); // Starts the receiver
   
   /*
    * powerStates:
      * 0: Powering on
      * 1: Powered on
      * 2: Powered off
    */
   powerState = 0;
   mute = 0; // Mute on/off (1/0)

   // Serial monitor
   Serial.begin (115200);
 } 

 /*
 * Main program
 */
 void loop() {
  if (powerState == 0) {
    powerOn();
  } else if (powerState == 1){
    relayOn();
    rotaryEncoder();// Include Push = MUTE
    LCD(); //Display input source 
    //lcd.backlight();
    powerControl(); // Read power button
    irRemote(); // Up, Down, Direct, Volume, MUTE, Power
  } else {
    rotaryEncoder(); // Rotary push button is temporarily power button???
    powerControl(); // Read power button
    irRemote(); // Power on/off only
  }
 }

 /*
  * Turn on current relay
  */
void relayOn() {
  
  // If relayCount has changed: Turn on the selected relay (next, previous, direct)
  // If previousRelay has changed: Turn on the last selected relay
  if (relayCount != previousRelay) {

    // Rollover 3 or 0
    if (relayCount > 3) {
      relayCount = 0;
    } else if (relayCount < 0) {
      relayCount = 3;
    }

    // Turn off all relays, then turn on relayCount
    relayOff();
    digitalWrite(relays[relayCount], HIGH);

    // Stop IR, write relayCount to memory, start IR
    irrecv.enableIRIn(false);
    EEPROM.write(0,relayCount);
    EEPROM.commit();
    irrecv.enableIRIn(true);
    Serial.print(" Written \"relayCount = ");
    Serial.print(relayCount);
    Serial.println("\" to save slot 0");
      
   // Reset counters, output relayNumber
   previousRelay = relayCount;
   relayNumber = relayCount + 1;
   Serial.print("Activated relay #");
   Serial.println(relayNumber);
   Serial.println();

   // If circuit is muted, unmute
   if (mute == 1) {
    digitalWrite(muteLed,HIGH);
    Serial.println("Waiting 1.5 seconds before turning off mute");
    delay(1500);
    toggleMute();

   }
  }
}

/*
 * Power on amplifier
 */
void powerOn() { // Only called if powerState is 0 (Powering on)
    Serial.println("The Relay Input Selector has woken up!\n");
    Serial.print(" ** Reading saved relay state from NVRAM: ");
    Serial.println(relayCount);
    digitalWrite(relays[4],LOW);
    mute = 1;
    Serial.println("\n ** Mute Relay turned ON");
    Serial.println(" ** All input relays are turned OFF");
    relayOff();
    Serial.println(" ** Solid State Relay is turned OFF\n");
    digitalWrite (SSR,LOW);
    Serial.println(" ** Startup completed - waiting for Power ON\n");
    Serial.println("       -------------------------\n");
    
    // Set powerState to 2 (Powered off):
    powerState = 2;
}

/*
 * Read powerbutton, turn on or off
 */
void toggleMute() {
    if (mute == 0) {
      Serial.println(" Mute relay turned ON\n");
      digitalWrite(relays[4],LOW);
      if (powerState == 1){
        digitalWrite(muteLed,HIGH);
      }
      mute = 1;
    } else {
      Serial.println(" Mute relay turned OFF\n");
      digitalWrite(relays[4],HIGH);
      digitalWrite(muteLed,LOW);
      mute = 0;
    }
}


/*
 * Read powerbutton, turn on or off
 */
void powerControl() {
    int reading = digitalRead(poweronButton);

    if (reading != lastButtonState) {
      lastDebounceTime = millis();
    }

    if ((millis() - lastDebounceTime) > debounceDelay) {
    // whatever the reading is at, it's been there for longer than the debounce
    // delay, so take it as the actual current state:

    // if the button state has changed:
    if (reading != buttonState) {
      buttonState = reading;

      // only toggle the LED if the new button state is HIGH
      if (buttonState == 1) {
        Serial.println(" Power button pushed");
        
        if (powerState == 1) { // Turning power OFF: All relays OFF, power amp OFF
          powerState = 2;
          digitalWrite (SSR,LOW);
          digitalWrite (LED,LOW);
          //lcd.noBacklight();
          relayOff();
          if (mute == 0) {
            toggleMute();
          }
          Serial.println(" Solid State Relay OFF");
          Serial.println(" Power OFF\n");
          
        } else if (powerState == 2) { // Turning power ON: Last selected relay ON, power amp ON
          powerState = 1;
          digitalWrite (SSR,HIGH);
          //lcd.backlight();
          digitalWrite (LED,HIGH);
          previousRelay = relayCount + 1; // Trigger relayOn()
          Serial.println(" Power ON");
          Serial.println(" Solid State Relay ON\n");
        } 
      } 
    }
  }
  lastButtonState = reading;
}

 /*
  * IR Remote
  */
void irRemote() { // Start irRemote function

    // Decode the infrared input
      // Decodes the infrared input
  if (irrecv.decode(&results)) {
    long int decCode = results.value;
    Serial.print(" Received IR code: ");
    Serial.print(decCode);
    Serial.println();
    // Switch case to use the selected remote control button
    switch (results.value) { // Start switch/case
      
      case 16724175: // Relay 1
        {
          Serial.println(" Button \"1\"");
          if (powerState == 1) {
            relayCount = 0;
          } else {
            Serial.println(" Powered off, doing nothing...\n");
          }
          break;
        }

      case 16718055: // Relay 2
        {
          Serial.println(" Button \"2\"");
          if (powerState == 1) {
            relayCount = 1;
          } else {
            Serial.println(" Powered off, doing nothing...\n");
          }
          break;
        }

      case 16743045: // Relay 3
        {
          Serial.println(" Button \"3\"");
          if (powerState == 1) {
            relayCount = 2;
          } else {
            Serial.println(" Powered off, doing nothing...\n");
          }
          break;
        }

      case 16716015: // Relay 4
        {
          Serial.println(" Button \"4\"");
          if (powerState == 1) {
            relayCount = 3;
          } else {
            Serial.println(" Powered off, doing nothing...\n");
          }
          break;
        }

      case 16769565: // Mute
        {
          Serial.println(" Button \"Mute\"");
          if (powerState == 1) {
            toggleMute();
          } else {
            Serial.println(" Powered off, doing nothing...\n");
          }
          break;
        }

      case 16748655: // Channel UP
        {
          Serial.println(" Button \"UP\"");
          if (powerState == 1) {
            relayCount++;
          } else {
            Serial.println(" Powered off, doing nothing...\n");
          }
          break;
        }

      case 16754775: // Channel DOWN
        {
          Serial.println(" Button \"DOWN\"");
          if (powerState == 1) {
            relayCount--;
          } else {
            Serial.println(" Powered off, doing nothing...\n");
          };
          break;
        }

      case 16753245: // Power button
        {
          Serial.println("Button \"POWER\"");
          if (powerState == 1) {
            powerState = 2;
            digitalWrite (SSR,LOW);
            digitalWrite (LED,LOW);
            //lcd.noBacklight();
            relayOff();
            if (mute == 0) {
              toggleMute();
            }
            Serial.println(" Solid State Relay OFF");
            Serial.println(" Power OFF\n");
            
          } else {
            powerState = 1;
            digitalWrite (SSR,HIGH);
            digitalWrite (LED,HIGH);
            //lcd.backlight();
            previousRelay = relayCount + 1; // Trigger relayOn()
            Serial.println(" Power ON");
            Serial.println("Solid State Relay ON\n");
          }
          break;
        }

      default:
      {
        Serial.println("Going back to waiting for IR remote keypress\n");
      }
    } // End switch/case
    irrecv.resume(); // Receives the next value from the button you press
  }
    
  } // End irRemote function

  
 /*
  * Mute (turn off all relays)
  */
   void relayOff() {
    for (int off = 0; off <= 3; off++) {
      digitalWrite(relays[off], LOW);
      }
   }


 /*
 * Rotary Encoder Control of Relays
 */
 void rotaryEncoder() { 
   aState = digitalRead(rotaryA); // Reads the "current" state of the rotaryA
   
   // If the previous and the current state of the rotaryA are different, that means a Pulse has occured
   if (aState != aPreviousState){  

     // If the rotaryB state is different to the rotaryA state, that means the encoder is rotating clockwise
     if (digitalRead(rotaryB) != aState) { 
       counter ++;
     } else {
       counter --;
     }
    }

   // What to do if rotating Right of Left 
   if (previous != counter) {
     if (counter > 1) { // Since the encoder gives two signals when turning
       Serial.print(" Rotational encoder turned ");
       Serial.println("clockwise");

       if (powerState == 1) {
        // Increase relayCount
        relayCount++;
       } else {
        Serial.println(" Powered off, doing nothing...\n"); // Powered off???
       }
       
     } else if (counter < -1) { // Since the encoder gives two signals when turning
       Serial.print(" Rotational encoder turned ");
       Serial.println("counter-clockwise");
       
       if (powerState == 1) {
        // Increase relayCount
        relayCount--;
       } else {
        Serial.println("Powered off, doing nothing...\n"); // Powered off???
       }
     }
   }

   // Reset counters
   previous = counter; 
   if (counter < -1) {
    counter = 0;
    previous = 0;
   } else if (counter > 1){
    counter = 0;
    previous = 0;
   }
    
   // Updates the previous state of the rotaryA with the current state
   aPreviousState = aState; 
 }

 void LCD(){
if (relayCount == 0){
 // Serial.println("Bluetooth Input");
  display.clearDisplay();
  display.setTextSize(2);
 display.setTextColor(WHITE);
  display.setCursor(20,8);
  display.println("BLUETOOTH");
  display.display();
  
 
}
if (relayCount == 1){
  //Serial.println("Optical 1 Input ");
  display.clearDisplay();
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(32,8);
  display.println("OPT  1");
  display.display();

  
}
if (relayCount == 2){
  //Serial.println("Optical 2 Input ");
  display.clearDisplay();
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(32,8);
  display.println("OPT  2");
  display.display();

}
if (relayCount == 3){
  //Serial.println("RCA Input ");
  display.clearDisplay();
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(32,8);
  display.println("RCA");
  display.display();
   
  
  }   
}

Any ideas would be greatly appreciated !

cool, so issue solved.

Yes it is. The for the help! I'll create a separate post for the other issue

You haven't addressed this ↑

Also, volatility doesn't imply atomicity!

Oh I see, did you mean literally make a copy like this:

 * Main program
 */
 void loop() {
  if (powerState == 0) {
    powerOn();
  } else if (powerState == 1){
    relayOn();
    rotaryEncoder();// Include Push = MUTE
    LCD(); //Display input source 
    //lcd.backlight();
    powerControl(); // Read power button
    irRemote(); // Up, Down, Direct, Volume, MUTE, Power
  } else {
    rotaryEncoder(); // Rotary push button is temporarily power button???
    powerControl(); // Read power button
    irRemote(); // Power on/off only
  }
    if (relayCount > 3) {
      relayCount = 0;
    } else if (relayCount < 0) {
      relayCount = 3;
    }
 }

No, like this:

auto localRelayCount = relayCount; // local copy, assuming atomic integer

// Rollover 3 or 0
if (localRelayCount > 3) {
    localRelayCount = 0;
} else if (localRelayCount < 0) {
    localRelayCount = 3;
}

// Turn off all relays, then turn on localRelayCount
relayOff();
digitalWrite(relays[localRelayCount], HIGH);
1 Like

Oh, I see. Thank you for your help !

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