#define CLK_PIN 12 // BTN ENC1 #define DT_PIN 14 // BTN ENC2 #define SW_PIN 13 // BTN ENC #define DIRECTION_NONE 0 // no change #define DIRECTION_CCW 1 // counter-clockwise direction #define DIRECTION_CW 2 // clockwise direction #define BUTTON_PRESSED_EVENT 1 #define BUTTON_UNPRESSED_EVENT 2 #define BUTTON_NO_CHANGE_EVENT 0 volatile uint8_t rotaryDirection = DIRECTION_NONE; volatile uint8_t rotaryDirectionPrev = DIRECTION_NONE; volatile uint32_t rotaryLastTick; volatile int rotaryCounter = 0; volatile int rotaryCounterPrev = 0; volatile int rotaryCounterPrevDebug = 0; volatile bool buttonPressed = false; volatile bool buttonPressedPrev = false; volatile bool buttonPressedPrevDebug = false; volatile uint32_t buttonLastTick = 0; volatile int16_t rotaryPosition = 0; volatile int16_t rotaryLastPosition = 0; //volatile int16_t rotaryEncodedPrev = 0; // Debounce time in milliseconds const int debounceTime = 2;//2; //default is 2 (best) volatile unsigned long lastInterruptTimeA = 0; volatile unsigned long lastInterruptTimeB = 0; volatile unsigned long lastInterruptTimeButton = 0; // Variables to keep track of encoder state volatile int lastEncoded = 0; volatile long encoderValue = 0; long lastEncoderValue = 0; // ISR for encoder A pin void IRAM_ATTR handleEncoderA() { unsigned long currentTime = millis(); if ((currentTime - lastInterruptTimeA) > debounceTime) { int MSB = digitalRead(CLK_PIN); int LSB = digitalRead(DT_PIN); int encoded = (MSB << 1) | LSB; int sum = (lastEncoded << 2) | encoded; if (sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011){ encoderValue--; rotaryDirection = DIRECTION_CCW; } if (sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000){ encoderValue++; rotaryDirection = DIRECTION_CW; } lastEncoded = encoded; lastInterruptTimeA = currentTime; rotaryCounter=encoderValue; //copy to rotaryCounter } } // ISR for encoder B pin void IRAM_ATTR handleEncoderB() { unsigned long currentTime = millis(); if ((currentTime - lastInterruptTimeB) > debounceTime) { handleEncoderA(); // Call handleEncoderA to handle B changes in the same way lastInterruptTimeB = currentTime; } } void InitButtonRotaryHandler(){ Serial.print("Initializing Button and Rotary Encoder: "); buttonPressedPrev = false; buttonPressedPrevDebug = false; rotaryCounter = 0; rotaryCounterPrev = 0; rotaryCounterPrevDebug = 0; rotaryDirection = DIRECTION_NONE; rotaryDirectionPrev = DIRECTION_NONE; rotaryLastTick = millis(); buttonLastTick = millis(); pinMode(DT_PIN, INPUT_PULLUP); pinMode(CLK_PIN, INPUT_PULLUP); pinMode(SW_PIN, INPUT_PULLUP); // button.setDebounceTime(5); attachInterrupt(digitalPinToInterrupt(CLK_PIN), handleEncoderA, CHANGE); attachInterrupt(digitalPinToInterrupt(DT_PIN), handleEncoderB, CHANGE); // Initialize button pin //pinMode(SW_PIN, INPUT_PULLUP); // Assuming the button is active low //attachInterrupt(digitalPinToInterrupt(SW_PIN), ButtonInterrupt, CHANGE); Serial.println("OK"); } bool ButtonIsPressed(){ if (millis() - buttonLastTick < 10 ) return buttonPressed; //debounce buttonPressed = digitalRead(SW_PIN) == LOW; buttonLastTick = millis(); return buttonPressed; } //return 0 = no change, 1 = pressed, 2 = unpressed uint8_t ButtonSwitchedEvent(){ //Serial.println("A"); if (millis() - buttonLastTick < 10 ) return BUTTON_NO_CHANGE_EVENT; //debounce //Serial.println("B"); buttonPressed = digitalRead(SW_PIN) == LOW; buttonLastTick = millis(); if (buttonPressed!=buttonPressedPrev){ buttonPressedPrev = buttonPressed; if (buttonPressed) return BUTTON_PRESSED_EVENT; return BUTTON_UNPRESSED_EVENT; }else{ return BUTTON_NO_CHANGE_EVENT; //no change } } //Reset Button flag for event void ButtonResetEvent(){ buttonPressed = digitalRead(SW_PIN) == LOW; buttonPressedPrev = buttonPressed; buttonLastTick = millis(); } //Reset Rotary flag for event void RotaryResetEvent(){ rotaryCounter = 0; rotaryCounterPrev = 0; encoderValue = 0; rotaryDirection = DIRECTION_NONE; rotaryDirectionPrev = DIRECTION_NONE; } //Get rotary last direction then clear flag uint8_t RotaryEvent(){ if (rotaryDirection!=DIRECTION_NONE) lastInterruptTimeB = millis(); //debounce it again from last consume uint8_t v = rotaryDirection; rotaryDirection = DIRECTION_NONE; rotaryDirectionPrev = DIRECTION_NONE; return v; } //for debug testing void ButtonRotaryDebugRoutine(){ if (buttonPressedPrevDebug!=buttonPressed){ buttonPressedPrevDebug = buttonPressed; Serial.print("Button: "); Serial.println((buttonPressed?"1":"0")); } if (rotaryCounter!=rotaryCounterPrevDebug){ rotaryCounterPrevDebug = rotaryCounter; if (rotaryDirection!=DIRECTION_NONE){ Serial.print("Rotary: "); Serial.print((rotaryDirection==DIRECTION_CW?">":"<")); Serial.print(" ("); Serial.print(rotaryCounterPrevDebug); Serial.println(")"); } } }