User avatar
Grumpy Mike
Posts: 900
Joined: Sat Sep 10, 2011 7:49 pm
Location: Manchester (England England)
Contact: Website

Wait for edge - false timeout

Tue Oct 02, 2018 9:34 am

I am having trouble with the wait_for_edge function in the RPi.GPIO libiary.
I have a bunch of inputs which are being hit with 80uS pulses every 1.3mS. If they stop being hit like this I want to know.

To this end I am using a wait_for_edge with a time out of 4ms and detecting when a timeout occurs.

This works fine as long as their is no other Pi activity. However, if I do things like scroll another window in the IDE editor I get a time out flagged.

I think this is due to the operating system going off and doing something else, ( like scrolling the window ) but it is unpredictable. I don't want to push up the timeout parameter as I am monitoring 16 lines and this will slow things down considerably for the lines that are disconnected.
Does anyone know a way round this? It looks like the calculation of time out is based only on the time the OS hands back control to Python not on if a pulse has occurred in the interim.
I did try looking again for a time out if I got a first one on a pin but it did not seem to help.

I think if I could do a direct read to the edge detection registers this would avoid the problem, but last time I asked if there was a libiary that would do that I was told here that there wasn't and to use the wait_for_edge function instead.

Thanks for reading
Last edited by Grumpy Mike on Tue Oct 02, 2018 9:45 am, edited 1 time in total.

scotty101
Posts: 3178
Joined: Fri Jun 08, 2012 6:03 pm

Re: Wait for edge - false timeout

Tue Oct 02, 2018 9:39 am

Might be worth trying pigpiod. It accesses the GPIO registers in a different way which may be more tolerant to this.

Another suggestion would be to use an external device such as a microcontroller to monitor these pulses and then the Pi only needs to monitor for the "lost signal" situation.
Electronic and Computer Engineer
Pi Interests: Home Automation, IOT, Python and Tkinter

User avatar
Grumpy Mike
Posts: 900
Joined: Sat Sep 10, 2011 7:49 pm
Location: Manchester (England England)
Contact: Website

Re: Wait for edge - false timeout

Tue Oct 02, 2018 10:09 am

Thanks for that.

Unfortunately the pigpoid documentation for edge detection says:-
Do not use this function for precise timing purposes, the edge is only checked 20 times a second. Whenever you need to know the accurate time of GPIO events use a callback function.
And as we know the call back function will not work at this speed.
Another suggestion would be to use an external device such as a microcontroller to monitor these pulses
Problem is twofold:-
1) The hardware is already designed and built and can not be changed.
2) Also microcontrollers with a pin change latch register are few and far between and are normally expensive, way beyond the cost of a Pi.
I think the Pi should be up to doing this task, it is just Linux getting in the way.

scotty101
Posts: 3178
Joined: Fri Jun 08, 2012 6:03 pm

Re: Wait for edge - false timeout

Tue Oct 02, 2018 11:26 am

Grumpy Mike wrote:
Tue Oct 02, 2018 10:09 am
2) Also microcontrollers with a pin change latch register are few and far between and are normally expensive, way beyond the cost of a Pi.
I think the Pi should be up to doing this task, it is just Linux getting in the way.
There are loads of microcontrollers that cost only a few dollars that would be more than capable of doing this. Even some very small 8 pin devices can have an interrupt connected to the rising/falling edge of a GPIO pin.
Electronic and Computer Engineer
Pi Interests: Home Automation, IOT, Python and Tkinter

User avatar
Grumpy Mike
Posts: 900
Joined: Sat Sep 10, 2011 7:49 pm
Location: Manchester (England England)
Contact: Website

Re: Wait for edge - false timeout

Tue Oct 02, 2018 12:35 pm

Even some very small 8 pin devices can have an interrupt connected to the rising/falling edge of a GPIO pin.
Yes but they don't have 16 interrupt capable pins. And then you have the trouble of communicating the results back to the Pi. Using an external microprocessor is not an option. The processor in the Pi is quite capable of doing this if the software could allow it. I am looking for a solution that just uses the processing power of the Pi, which is quite considerable.

Andyroo
Posts: 434
Joined: Sat Jun 16, 2018 12:49 am
Location: Side of the hill in Lincolnshire

Re: Wait for edge - false timeout

Tue Oct 02, 2018 12:54 pm

Been a long time since I’ve done things like this :D :oops: but I came across these that may help

https://www.stevebate.net/chibios-rpi/G ... arted.html

https://emlid.com/raspberry-pi-real-time-kernel/

One other thought:

a) The Arduino Mega has 24 interrupt capable lines - not possible in your case but included for completeness
b) A programmable interrupt controller (8259 or similar) - also not possible for you
c) Patch the kernel https://lemariva.com/blog/2018/07/raspb ... nel-4-14-y

Feeling is though the GUI chip may stuff you in all these cases :(
Need Pi spray - these things are breeding in my house...

User avatar
Grumpy Mike
Posts: 900
Joined: Sat Sep 10, 2011 7:49 pm
Location: Manchester (England England)
Contact: Website

Re: Wait for edge - false timeout

Tue Oct 02, 2018 1:52 pm

Thanks. However
a) The Arduino Mega has 24 interrupt capable lines - not possible in your case but included for completeness
Well you can have all the pins on an Uno generate an interrupt with the pin change interrupt if I was thinking of going down that route.

Sadly I am not looking to change the OS for this as it has to work with a standard system. I don't see how the GUI chip is going to change things.

There is a falling edge and rising edge GPIO register, these should work independently of anything else going on. If the RPi.GPIO software was written properly it would detect the state of these registers after a specific time and avoid this problem. Maybe it is written the way it is to avoid some other problem, I don't know.

If I could read these registers the I could do this in code myself. Unfortunately there is no way as I see it to get at these registers without rewriting the RPi.GPIO libiary or something similar.

Thanks for your interest so far.

User avatar
joan
Posts: 13578
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Wait for edge - false timeout

Tue Oct 02, 2018 5:43 pm

There are several ways of doing this with pigpio. One example follows.

Code: Select all

#!/usr/bin/env python

import pigpio
import time

WATCH=4
TIMEOUT_MICROS=1300

count=0

pi = pigpio.pi()
if not pi.connected:
   exit()

def cbf(gpio, level, tick):
   global count
   count += 1
   print("level steady too long: {}".format(count))

pi.set_glitch_filter(WATCH, TIMEOUT_MICROS)

cb = pi.callback(WATCH, pigpio.EITHER_EDGE, cbf)

time.sleep(600)

cb.cancel()
pi.set_glitch_filter(WATCH, 0)
pi.stop()
The wait_for_edge method is for simple needs. Callbacks should be used for more serious purposes.

PhilBr
Posts: 48
Joined: Tue Oct 31, 2017 5:28 pm

Re: Wait for edge - false timeout

Tue Oct 02, 2018 6:18 pm

Hi Mike,

If you are looking for a warning of a single missed pulse on any one of a number of inputs then it looks tough challenge for a pi without external hardware.

If however you are asking for an alert to be generated within a few seconds if one of the lines stops pulsing completely then I’d try using interrupts rather than polling:

1. Set each pin up with a callback function on rising edge (See GPIO.add_event_detect).
2. have a single very short fast callback function which simply increments a counter in a global array (indexed by device number) and returns. A single routine can be common to all lines.
3. Have your main loop check and clear those counters then sleep for a second. You'd expect the counters to be around 770 so any with a value under (say) 300 indicates a pin which has stopped pulsing.

I honestly do not know how well this will keep up with all your 1.3mS interval pulses. It needs (callback time * number of lines) < 1.3mS which might be do-able.

You might experiment with the ‘bouncetime’ parameter to the add_event_detect which might coalesce a number of pulses into one callback activation and reduce time spent in the callback function (and you'd modify the 300 figure above accordingly). Conversely, the ‘behind the scenes’ time checking may make it far worse; I just don’t know.

Have fun and let us know how it works. Thanks for the intellectual challenge!
Phil

User avatar
joan
Posts: 13578
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Wait for edge - false timeout

Tue Oct 02, 2018 8:08 pm

To monitor multiple GPIO you could do something like the following:

Code: Select all

#!/usr/bin/env python

import pigpio
import time

WATCH=[4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]
cb=[None] * 32

TIMEOUT_MICROS=1300

pi = pigpio.pi()
if not pi.connected:
   exit()

def cbf(gpio, level, tick):
   print("GPIO {} level steady too long".format(gpio))

for i in WATCH:
   pi.set_glitch_filter(i, TIMEOUT_MICROS)
   cb[i] = pi.callback(i, pigpio.EITHER_EDGE, cbf)

time.sleep(600)

for i in WATCH:
   cb[i].cancel()
   pi.set_glitch_filter(i, 0)

pi.stop()

Idahowalker
Posts: 372
Joined: Wed Jan 03, 2018 5:43 pm

Re: Wait for edge - false timeout

Tue Oct 02, 2018 8:46 pm

Just me, but I would look at getting rid of the RPi overhead and dedicate a RPi to the project or switch to using a ESP32, but the stated reasons rule that our for you; too bad.
Without knowing why you are deleting my postings, I will not know how...

User avatar
Grumpy Mike
Posts: 900
Joined: Sat Sep 10, 2011 7:49 pm
Location: Manchester (England England)
Contact: Website

Re: Wait for edge - false timeout

Tue Oct 02, 2018 9:19 pm

If you are looking for a warning of a single missed pulse on any one of a number of inputs then it looks tough challenge for a pi without external hardware.
Well no that is not quite the situation. I have 16 inputs, some of them will be receiving no pulses, others will be receiving a continuous stream of pulses. I just want to distinguish which the case is for each input. I want to know this with a minimum of waiting, possibly within 200mS of wanting to know.

I agree that callback will not cut it and it is not actually what I want. I just need to see if there is a stream of pulses or not. I can't believe that the Pi is not capable of this.

Code: Select all

TIMEOUT_MICROS=1300
As I said before the 20 times a second is not acceptable for my application. And using an external processor for this, with all that power in the Pi is just silly.

User avatar
joan
Posts: 13578
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Wait for edge - false timeout

Tue Oct 02, 2018 10:08 pm

As I said wait_for_edge is only used for simple needs. The code I posted does not use wait_for_edge.

User avatar
Grumpy Mike
Posts: 900
Joined: Sat Sep 10, 2011 7:49 pm
Location: Manchester (England England)
Contact: Website

Re: Wait for edge - false timeout

Wed Oct 03, 2018 1:32 pm

Thank you for the code you posted. I shortened the time you had to wait to see if a button had a stream or not, from one hour to 10 seconds. Unfortunately all the code did was to report random pins as being steady for too long. It occasionally reported the one pin that was not receiving pulses but also reported lots of others that were.

I did try a 25 second delay and that also made no change.

Thank you for your efforts.

Idahowalker
Posts: 372
Joined: Wed Jan 03, 2018 5:43 pm

Re: Wait for edge - false timeout

Wed Oct 03, 2018 6:51 pm

Are the pulses synchronized? Meaning if all the pulses are there those pulses are all in the same state at the same time?

Do you care that the pulses are there or is the concern is if the pulses are not there?
Without knowing why you are deleting my postings, I will not know how...

User avatar
Grumpy Mike
Posts: 900
Joined: Sat Sep 10, 2011 7:49 pm
Location: Manchester (England England)
Contact: Website

Re: Wait for edge - false timeout

Wed Oct 03, 2018 8:00 pm

Are the pulses synchronized?
No they are all displaced in time from each other.
Do you care that the pulses are there or is the concern is if the pulses are not there?
I want to know the state pulses or not as they represent the state of switches being pressed to transfer the pulses to the GPIO or not.

@ joan - I am getting somewhere with the pigpio code. Not fully working but it is a lot more stable than it was. Still working on it. Thanks.

User avatar
joan
Posts: 13578
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Wait for edge - false timeout

Thu Oct 04, 2018 7:49 am

I'd guess the 1300 microseconds is too short a timeout. Perhaps add a 100 micros or so. In practice you probably want to know when a link recovers as well as when it fails. For that I would remove the glitch stuff and just use set_watchdog with a 2 millisecond timeout (it only works in milliseconds, the glitch filter works in microseconds).

http://abyz.me.uk/rpi/pigpio/python.html#set_watchdog

User avatar
Grumpy Mike
Posts: 900
Joined: Sat Sep 10, 2011 7:49 pm
Location: Manchester (England England)
Contact: Website

Re: Wait for edge - false timeout

Thu Oct 04, 2018 4:55 pm

I'd guess the 1300 microseconds is too short a timeout.
On the contrary, I have it working down to 80 microseconds. Although I think this might be milliseconds, which would make sense.

However I am now attempting to put the code in to a class libiary and I am having trouble with defining the call back function:-

Code: Select all

    self.cb[i] = self.pi.callback(self.buttonPins[i], pigpio.EITHER_EDGE, cbf)
NameError: name 'cbf' is not defined


I am not too good with Python 3 classes, it is probably something stupid I am missing.
Last edited by Grumpy Mike on Thu Oct 04, 2018 4:59 pm, edited 1 time in total.

User avatar
joan
Posts: 13578
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Wait for edge - false timeout

Thu Oct 04, 2018 4:57 pm

If cbf is a member of the class you refer to it as self.cbf within the class.

User avatar
Grumpy Mike
Posts: 900
Joined: Sat Sep 10, 2011 7:49 pm
Location: Manchester (England England)
Contact: Website

Re: Wait for edge - false timeout

Thu Oct 04, 2018 5:05 pm

If cbf is a member of the class you refer to it as self.cbf within the class.
Yes but it is not a member of the class I took it from the line on your original code

Code: Select all

cb[i] = pi.callback(i, pigpio.EITHER_EDGE, cbf)
If I do use self.cbf then the whole thing goes into a loop spewing the callback print message over the screen. The only way I can break from this is by quitting Python, and then other stuff does not work and I have to reboot the pi.

User avatar
Grumpy Mike
Posts: 900
Joined: Sat Sep 10, 2011 7:49 pm
Location: Manchester (England England)
Contact: Website

Re: Wait for edge - false timeout

Fri Oct 05, 2018 7:50 am

Thanks guys - it's a wrap. Got it going as a class libiary.

The trick was the glitch_filter settings, it seems to work slightly faster in the class code.

I was getting what the filter does wrong. It turns out the setting in the filter gives you the pulse size to ignore, so I had to take it to the time of the pulse was low, not high. So by having it at 80 uS I was on the limit as the pulse actually goes low for 88uS. Odd that a value of 80 was fine when working in "normal" code but not as a class. It might have something to do with the semi compiled nature of a class.

Anyway pigpio is acting like I expect now so on wards and upwards.

For anyone reading this at a later data the full code and its context, can be found in my column in The MagPi No.76 December 2018

Return to “Python”