// Rotary Encoder - XIAO ESP32-S3
// Interrupt-driven A/B channels
const int PIN_A = D1;
const int PIN_B = D2;
const int PIN_BTN = D3;
volatile long encoderPos = 0;
volatile unsigned long lastTime = 0;
void IRAM_ATTR handleEncoderA() {
unsigned long now = micros();
if (now - lastTime > 1000) { // debounce
if (digitalRead(PIN_A) == digitalRead(PIN_B)) {
encoderPos++;
} else {
encoderPos--;
}
lastTime = now;
}
}
void setup() {
Serial.begin(115200);
pinMode(PIN_A, INPUT_PULLUP);
pinMode(PIN_B, INPUT_PULLUP);
pinMode(PIN_BTN, INPUT_PULLUP);
attachInterrupt(PIN_A, handleEncoderA, CHANGE);
}
void loop() {
static long lastReported = 0;
if (encoderPos != lastReported) {
Serial.print("Encoder: ");
Serial.println(encoderPos);
lastReported = encoderPos;
}
if (digitalRead(PIN_BTN) == LOW) {
Serial.println("Button Pressed");
delay(200);
}
}