Hi. Can someone in this forum of expertise explain this ESP32 interrupt behaviour, please? I can work around the problem I have, but I obviously have something misunderstood.
[/code]
- 20181123_070851.jpg (52.86 KiB) Viewed 14863 times
I'm counting fairly slow pulses (a flashing LED which I sense with a light-dependent resistor). My input signal for one pulse is shown at the top trace.
I send some debugging information (a byte counter in range 0-255) to the DAC output on the ESP32. That's shown here on the lower trace.
I trigger an interrupt on the falling edge of my input. I get and clear the interrupt and set my ESP32 DAC level to zero.
Now as my input signal climbs slowly back through the range 1.6v to 1.9v, I get a burst of unwanted interrupts - I count them and reflect the count to the DAC. So the second trace shows the DAC output, which climbs as I get unwanted interrupts. (with modulus 256 wrapping back to zero if I get too many unwanted interrupts - the one attachment below shows about 1500 unwanted interrupts while my source pulse climbs back to its rest voltage).
I've looked at this signal at higher time resolution in case my external source is using some kind of high-frequency PWM, but I cannot find any evidence.
So what exactly does it mean to trigger a GPIO pin interrupt on a "falling edge"? How far does the voltage have to fall, and are there some kind of Schmitt trigger lower and upper bounds? Why am I apparently seeing falling-edge interrupts as my source signal is climbing?
I did swap out the ESP32 just in case - it is not a faulty device
And I checked the argument passed into the ISR handler - all the interrupts are arriving from my source, not elsewhere.
Here is the heart of what I did in the code...
Code: Select all
const byte dacPin = 25;
byte dacCount = 0;
void IRAM_ATTR pulseOccurred(void* arg)
{
int st = GPIO.status;
GPIO.status_w1tc = st; // clear the interrupt
dacCount++; // and count it
dacWrite(dacPin, dacCount); // Make counter externally visible on the scope.
if (ledState) { // ledState is my own time-based window to ignore the noise
pulsesRejected++;
return; // filter these out
}
dacCount = 0; // When I get a valid pulse, reset the dac to its minimum level.
dacWrite(dacPin, dacCount);
pulsesCounted++;
ledState = true;
ledOn();
ledTimeOff = millis() + 50; // leave my BUILTIN LED on for a fixed time. My main loop will
// turn off the led when the time is ripe,
// and it will reset the ledState flag.
}
My setup does this:
Code: Select all
gpio_num_t iPin = (gpio_num_t) interruptPin;
gpio_set_intr_type(iPin, GPIO_INTR_NEGEDGE);
gpio_intr_enable(iPin); // Enable the pin for interrupts
// Bind the pin interrupt to our handler via the interrupt matrix.
// This is potentially many-to-one.
if (gpio_isr_register(&pulseOccurred, (void*)"pulseOccurred",
ESP_INTR_FLAG_INTRDISABLED | ESP_INTR_FLAG_IRAM,
&pulseOccurredHandle) != ESP_OK)
{
sayf("Failed to register interrupt handler!\n");
}
else {
sayf("Interrupt handler registered\n");
}
esp_intr_enable(pulseOccurredHandle);
Any insights or help would be appreciated.