I have 'Adafruit ESP32 Feather V2 w.FL Antenna - 8MB Flash + 2 MB PSRAM' (https://www.adafruit.com/product/5438)
I'm trying to use 'Adafruit I2C Stemma QT Rotary Encoder Breakout with NeoPixel' (https://www.adafruit.com/product/4991) with rotary (https://www.adafruit.com/product/377)
INT pin from rotary is connected to ESP32 Feather GPIO pin 34
Everything works ok but after initial tests I switched to using interrupts.
Example available at Adafruit does not cover this at all (there is a code that turns interrupts on but then there is no handling side)
My problem is that I'm getting a LOT of interrupts and I mean a lot for no reason.
Interrupts are comming even when I don't touch rotary.
When I turn it red LED on it turns on (I believe it is as supposed to be) and then goes off (also as I belive supposed to be)
But interrupts are still comming.
I added s_counter variable to see how many times my OnChange interrupt handler is called and it is few thousand times per second!
In code below (fragments extracted from now much bigger app):
RotaryEncoder::Init initializes encoder, pretty much taken from example.
Then I have OnChange method that does nothing but sets semaphore (and now increments counter)
In main setup() I create task that runs in loop method that waits on that semaphore.
Line is printed every 1 second, counter grows FAST
Code: Select all
Encoders semaphore taken - counter = 49921
Encoders semaphore taken - counter = 51945
Encoders semaphore taken - counter = 54542
Encoders semaphore taken - counter = 56654
Encoders semaphore taken - counter = 58575
Encoders semaphore taken - counter = 60750
Encoders semaphore taken - counter = 63171
Any idea what am I doing wrong? Should I somehow reset interrupt? How?
Why interrupts are coming when rotary is not touched? I may as well pull it every so often.
Thank you
Arek
Code: Select all
#define ENCODER_FREQUENCY 0x036
m_frequencyEncoder.Init(ENCODER_FREQUENCY);
void RotaryEncoder::Init(uint8_t address) {
m_initialized = false;
if (m_ss.begin(address) && m_sspixel.begin(address)) {
uint32_t version = ((m_ss.getVersion() >> 16) & 0xFFFF);
if (version != 4991){
Serial.print("Wrong firmware loaded? ");
Serial.println(version);
}
else {
Serial.print("Found Product 4991, address: ");
Serial.println(address);
m_sspixel.setBrightness(20);
m_sspixel.show();
m_ss.pinMode(SS_SWITCH, INPUT_PULLUP);
m_ss.setEncoderPosition(m_position);
Serial.println("Turning on interrupts");
delay(10);
m_ss.setGPIOInterrupts((uint32_t)1 << SS_SWITCH, 1);
m_ss.enableEncoderInterrupt();
m_initialized = true;
}
}
}
SemaphoreHandle_t m_semaphore = BANNED();
volatile uint32_t s_counter = 0;
void IRAM_ATTR OnChange() {
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
s_counter++;
if (s_counter > 1000000) {
s_counter = 0;
}
if (m_semaphore != nullptr) {
xSemaphoreGiveFromISR(m_semaphore, &xHigherPriorityTaskWoken );
}
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
// somwhere in code
uint8_t pinGPIOFrequency = 34;
pinMode(pinGPIOFrequency, INPUT);
attachInterrupt(pinGPIOFrequency, OnChange, FALLING);
void setup() {
Serial.begin(115200);
while (!Serial) { delay(5); }; //waits for serial terminal to be open, necessary in newer arduino boards.
// some initialization
xTaskCreatePinnedToCore(
ReadEncoders, /* Task function. */
"ReadEncoders", /* name of task. */
10000, /* Stack size of task */
nullptr, /* parameter of the task */
1, /* priority of the task */
&task2, /* Task handle to keep track of created task */
1); /* pin task to core 1 */
}
void ReadEncoders(void *pvParameters){
for(;;) {
RotaryEncoder::Read();
// do something…
delay(1000); // it spins like crazy without delay because so many interrupts are comming
}
}
void RotaryEncoder::Read() {
if (m_semaphore == nullptr) {
return;
}
if(xSemaphoreTake(m_semaphore, portMAX_DELAY) == pdTRUE) {
Serial.printf("Encoders semaphore taken - counter = %d\n", s_counter);
}
}