-
Notifications
You must be signed in to change notification settings - Fork 7.6k
Slow Rise/Fall Times on GPIO inputs result in Spurious Interrupts #4172
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Bjarne, Again thanks for the work on this. Best |
[STALE_SET] This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 14 days if no further activity occurs. Thank you for your contributions. |
WOW, just WOW. I started a year ago to build a bike computer for my home trainer. After months of procrastination and no idea how BT works, I managed to learn a minimal BT stack to implement some device. Well, I guess nothing beats a Trigger Schmitt. |
[STALE_CLR] This issue has been removed from the stale queue. Please ensure activity to keep it openin the future. |
[STALE_SET] This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 14 days if no further activity occurs. Thank you for your contributions. |
[STALE_DEL] This stale issue has been automatically closed. Thank you for your contributions. |
Awesome analysis @BjarneBitscrambler, thanks! Certainly helps understand what's happening with all these interrupt issues people are having. I've just created another issue in the ESP-IDF repo about this, and I'm going to give Espressif a few days after the weekend to reply - and if they don't, I'll keep bugging them until they do. It's ridiculous that they seem to be avoiding what is a serious issue, especially since I imagine almost every project uses an interrupt attached to a button in some form or other. |
I personally found it working better if I use CHANGE type instead of falling. |
Summary
I was having trouble getting one, and only one, interrupt per transition on a digital input pin. I noticed that there are at least 5 other issues ( #955, #1111, #1229, #1250, #2941 - all presently CLOSED) that report the same or similar difficulty.
I have figured out the cause in my situation, and believe the same explanation applies to the majority of the other reports. Since it crops up so frequently, I thought I would document my observations to help forestall future frustration. The 'scope shots are particularly good at illustrating why the problem occurs.
Briefly, in order for the rising- or falling-edge interrupts to function correctly on the ESP32 GPIO pins, both the rise and fall times of the input waveform must be short enough. My testing so far suggests that a 2 us (microsecond) or shorter transition between 10% and 90% logic levels avoids false triggering.
Background
I use an ESP32-WROVER-KIT, programmed with Platform.io using the latest Arduino code framework. I wish to measure the frequency of an AC waveform coming from an alternator. With a resistor-divider I bring the nominal 12V signal level down to 3V3 logic level. Since the signal travels several metres from the alternator, I also included some series resistance and parallel capacitance to protect against transients and filter out high-freq noise. What I wanted was a single interrupt each time the input waveform went positive. By counting the rate of the interrupts, I could determine the frequency of the alternator's output.
Problem
The reported frequency was between 1.5 to 3 times higher than it should have been. This suggested that multiple interrupts were occurring per single waveform cycle. Further, the error factor varied with the speed of the alternator, decreasing when the alternator speed was increased.
Investigation
I'll skip the deadend avenues... The setup that clearly reproduced the problem was feeding a signal from a waveform generator (GW model GFG8015G) to a GPIO pin on the ESP32. Using a waveform generator permitted varying the shape and frequency of the applied signal. ESP32 software configured the pin to trigger an interrupt on the rising edge of the input. The interrupt routine incremented a counter each time it was invoked, and set an output pin either high or low depending on whether the count was even or odd. By monitoring the input and output pins with an oscilloscope, it was easy to determine the relationship between the input signal and the resulting interrupts.
Here's the code snippet of the interrupt handler:
Observations
Proper Triggering
Here's a scope shot showing proper interrupt behaviour. The Yellow trace is the input signal, a square wave of amplitude about 3.2 V and frequency about 100 Hz. The Blue trace is the output from the interrupt routine; each transition represents one invocation of the interrupt handler. As expected, a single interrupt occurs at each rising edge of the input waveform. Not shown, but verified, is that when the software is changed to call for interrupts on the falling edge, the output toggles on the expected falling edge of the input.

Erratic Triggering
Without changing the ESP32 software or hardware, the applied waveform was switched to a triangle wave, thus extending the rise- and fall-times of the transitions (to about 4 ms in this example). Here's the observed output: interrupts happen on both the rising and falling edges. Sporadically there are even two interrupts on a single rising or falling edge (e.g. the first triangle shows 2 triggers on its falling edge, and the second triangle shows 2 triggers on its rising edge).

By adjusting the waveform's rise and fall times, I observed the following two points (with the software configured to rising-edge interrupt):
When the rise-time was reduced to about 60 us, and the fall-time was reduced to about 4 us, the trigger behaviour was almost perfect (though not shown in the below scope shot, I did observe two instances of false triggering on the falling edge, over several hundreds of waveform cycles).

Conclusions
Discussion
Signal Conditioning
It's usually desirable to condition signals that originate off-board before applying them to microcontrollers/CPUs. One wants to attenuate external noise and transients surges, while still allowing the desired signal through. In a manual switch application for example (issues #955, #1111, and #1229) one commonly sees a parallel capacitor used to 'debounce' the signal. Unfortunately while that may successfully merge multiple quick bounces into a single pulse, at least one of the edges on that pulse will be quite slow - in the millisecond range.
Similarly, when triggering on AC mains, the sinewave input has a long duration rise and fall time. Since the frequency is known (i.e. 50 or 60 Hz), it is possible (as I believe was done in issue #2941) to workaround the triggering problem by referencing subsequent software actions off the first interrupt, and using a timeout to keep from re-tripping during the remainder of the input cycle.
Schmitt Trigger Inputs
I didn't find in either the ESP32 Datasheet nor Technical Reference Manual any specification on maximum signal transition times. It seems clear that they are not using Schmitt trigger logic for the GPIO interrupts. To allow for this, when using signals that are slow-changing they should be fed through an external logic gate such as the 74LVC1G17 or many other similar ICs.
I2C Signals
Issue #1250, I believe, was not running afoul of the rise/fall-time problem (at least not entirely), but it did remind me of another situation in which one sees slowly-changing signals. The I2C protocol allows multiple devices to listen to the same bus, through the use of open-drain drivers together with pull-up resistors. This can result in rise-times that may be slow enough that the ESP32 records a double transition when there really is only one. I haven't delved into the ESP32 specs for their I2C module to see whether they have allowed for this or not, but it would be worth being aware of if using I2C.
Conclusion
Thanks to the other folks like @stickbreaker, @usmanshahid001, @ddieffen, @MacLeod-D, and @404-baitnotfound for posting your problems and solutions - it helps to know what others have tried. I hope I have summarized everyone's observations accurately. For sure, slow rise/fall times are not the only reason for unreliable interrupts, but are a big piece of the puzzle.
Comments & feedback are welcome!
The text was updated successfully, but these errors were encountered: