Pin interrupts and getting the value of the PIN state WHEN the ISR occurred

General discussions and questions abound development of code with MicroPython that is not hardware specific.
Target audience: MicroPython Users.
yogotech
Posts: 15
Joined: Tue Feb 25, 2020 5:11 am

Re: Pin interrupts and getting the value of the PIN state WHEN the ISR occurred

Post by yogotech » Tue Apr 28, 2020 9:11 pm

kevinkk525 wrote:
Tue Apr 28, 2020 9:07 pm
The way the signal is captured still applies. But I see that it isn't explained as well as I remember because I was messaging Peter a lot..
Basically you have to poll a 433MHz signal because interrupts are way too slow. at least on the ESPs.
It's not though. I looked at the code, and it's a very different solution to a very different problem than what I'm facing.

So, if the issue is interrupts being too slow on MicroPython on the ESPs, then I'll switch to using C code, which works, but is less fun, because interrupts in C are MORE than fast enough on the ESPs.



Nate

User avatar
dhylands
Posts: 3821
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: Pin interrupts and getting the value of the PIN state WHEN the ISR occurred

Post by dhylands » Tue Apr 28, 2020 10:00 pm

Just to reiterate what others have said. You can't really sample the level inside the ISR Handler (even on the pyboard). Noisy contacts can create very fast edges, so you need to rely on either knowing the previous state and assume that the edge is a transition, or you wait for some period of time after the edge and poll. Or you just poll. On many of my robots, I have a main loop that runs 100 times/second, and I just poll every time through the loop.

Some debouncers will poll multiple times (say once every 10 msec) and not give an answer until you get N consecutive results that are the same. For most modern switches.

Waiting for that 10 msec should be done with a timer and not from within the edge-detected ISR.The edge detected ISR should start the timer, but not wait for it to complete.

Strategy 1:
- know the previous state
- assume that any edge is a change in state
- disable the ISR when the edge is detected. Set a one-shot timer to re-enable after a debounce period. This prevents a flurry of ISRs due to a single press.

Strategy 2:
- don't care about the previous state
- disable the ISR when the edge is detected. Set a timer to fire periodically. after N (say 3) polls that you've got the same value, re-enable the ISR and report the polled value.

Strategy 3:
- poll the button periodically (You still probably want to wait for N consecutive results to eliminate electrical noise).

Strategy 1 gives the fastest response. Strategy 2 gives a more robust response (less likely to be triggered by electrical noise). Strategy 3 works well when your code had a periodic main loop, and may be simpler than using ISRs.

yogotech
Posts: 15
Joined: Tue Feb 25, 2020 5:11 am

Re: Pin interrupts and getting the value of the PIN state WHEN the ISR occurred

Post by yogotech » Tue Apr 28, 2020 10:32 pm

dhylands wrote:
Tue Apr 28, 2020 10:00 pm
Just to reiterate what others have said. You can't really sample the level inside the ISR Handler (even on the pyboard).
Unfortunately, due the nature of the data I'm capturing all the time, this means I really can't use MicroPython for my this particular project, which is too bad.

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

433MHz, switch debouncing

Post by pythoncoder » Wed Apr 29, 2020 5:47 am

Re capturing signals from 433MHz devices: I wanted to capture data from remote controls. These are relatively easy. They send a repeated pulse train and you can achieve a strong signal by holding the remote close while you perform the capture. Yet I found the signals to be too fast to use interrupts (on a Pyboard) and polled the pin in a tight loop. Even then I found that the jitter introduced by the receiver led to significant errors. I ended up capturing multiple frames and averaging to get a list of timings which could successfully be retransmitted.

I considered the issue of decoding data from a sensor and concluded that, owing to the jitter, it was probably impossible without a better receiver than the two I tried. Given a signal with accurate timings a Pyboard is capable of adequate timing accuracy if you use polling. If RMT input mode lands, an ESP32 would also work.

Re switch debouncing: a response in "human" timescales is usually all that's required. I use a uasyncio coroutine to poll the switch. If a state change occurs, run the user callback immediately then ignore all further state changes for the debounce period. It's easy to have a separate callback for contact open and contact closure.
Peter Hinch
Index to my micropython libraries.

User avatar
tve
Posts: 216
Joined: Wed Jan 01, 2020 10:12 pm
Location: Santa Barbara, CA
Contact:

Re: Pin interrupts and getting the value of the PIN state WHEN the ISR occurred

Post by tve » Wed Apr 29, 2020 6:49 am

Quick FYI: on the ESP32 all the python ISR handlers are "soft", which means that the actual C interrupt handler just enqueues the python ISR using mp_sched_schedule, which means that it will run when the interpreter reaches the next python statement boundary IIUC.

User avatar
jcw
Posts: 37
Joined: Sat Dec 21, 2019 12:08 pm
Location: CET/CEST

Re: Pin interrupts and getting the value of the PIN state WHEN the ISR occurred

Post by jcw » Thu Apr 30, 2020 12:06 pm

My guess is that getting accurate level information is tricky, maybe even impossible in some cases.

Say there are 4 interrupts in very quick succession (1 us apart), up-down-up-down. The interrupt for the first "up" will fire and the next "down" interrupt will be pending in h/w (probably, depends on how irqs get cleared). But unless the ISR exits immediately, the 3rd and 4th may be lost (since "pending" does not keep track of a count). And if there were 3 or 5 transitions, you could end up with a level change, without having seen an odd number of interrupts.

If the interrupt handler only resumes a background task, then that would again allow transitions to get missed.

I'm not 100% certain of my above reasoning, it's just a hunch. The only way out I can think of, would be to use a h/w counter, then you could test for even/odd. But there would still be the uncertainty of when the timer readout is actually done.

User avatar
dhylands
Posts: 3821
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: Pin interrupts and getting the value of the PIN state WHEN the ISR occurred

Post by dhylands » Fri May 01, 2020 12:07 am

jcw - that's pretty much how things could happen. You can look at some of the scope captures in this article: http://www.ganssle.com/debouncing.htm to see what happens with some switches.

Post Reply