How to use while loop to detect one of two events, event a, or event b

Another good suggestion - i did not expect so many replies! Thanks

Reply to
ewholz
Loading thread data ...

Well - C is always good for 1 line! I also plan to look into interrupts, may well be a better way to do the whole thing. Thanks, ewholz

Reply to
ewholz

oldState = None while True: newState = readPin() if newState != oldState: print(newState) oldState = newState sleep(1)

Reply to
A. Dumas

Interrupts have a steeper learning curve, but they are usually a far better way to detect events that do in fact trigger them, than polling a status register.

The problem ytou ahve is that tin a single tasking environment they are no better.

e.g. in pseudocode PIN_STATUS=readpin();

Interrupts-service() { PIN-STATUS-readpin(); // readpin has to be written so it CAN be called from an ISR } will set the status but you haven't really gained anything unless you have a multitasking environment where the task that monitors the pin status and might print it out, has been put to sleep...

Interrupts-service() { PIN-STATUS-readpin(); // readpin has to be written so it CAN be called from an ISR resume(sleeping_task_pin_monitor); //wake up sleepy task to do something in foreground }

That is to say that with a single task using a poll loop to do various things, there is no advantage really to using interrupts to improve the main loop performance: At that level one uses interrupts solely to 'keep up' with asynchronous events that might have happened too fast for the poll loop to detect. E.g. a pin going high and then low between being polled would not be detected. But by using an ISR and a buffer, to stack up pin values it would not be missed.

However Linux does have multi-tasking, and multi-threading and although I am not familiar with the 'Pi' architecture, it should be possible to write a thread that sleeps until an asynchronous event wakes it up. Cf 'Posix threads'

Nit sure if Python would have the tools though.

Oh. yes it does, Some nice tutorials here:

formatting link

--
All political activity makes complete sense once the proposition that  
all government is basically a self-legalising protection racket, is  
fully understood.
Reply to
The Natural Philosopher

Hello A Dumas - Thanks to all who commented and replied. I have implemented a scheme much like the one above from A. Dumas. It works fine. I am considering using an interrupt - but will reply to note below.

Thanks Again,

ewholz

Reply to
ewholz

Greetings Natural Philosopher,

I have been considering using an interrupt for this, but question whether or not it will save any thing. Whether or not I use an interrupt, I still have to run the program using: "python my_interrupt.py" This program will be running all the time. My program called new_monitor.py needs to be invoked the same way. Do I save anything using interrupt vs. the while loop code?

Let me know what you think. I do plan do check the resources used of my inline coded program and then create the same funtionality using the interrupt method.

Again,

Thanks ewholz

Reply to
ewholz

It depends on the length of the scan cycle, how many conditions must be checked and how long a signal persists in comparison with the time for a loop to complete.

Your system will work to monitor your door because its unlikely that the door will be opened and and closed within a second. On the other hand, if you used the same 1 second loop to check for somebody pressing a microswitch or a hand passing through a light beam, then its likely that many events would be missed. The same problem can occur if the action the event triggers takes as long as the loop cycle time to complete, then you'd miss other types of events that the loop is scanning for.

Its better to use interrupts if several events are being monitored and if any of the actions they trigger will take time to complete, but the program structure can become quite a lot more complex. For example, if you're monitoring several interrupt sources and the associated actions are long compared with the maximum rate at which interrupts may occur, then, to avoid missing any interrupts, you may need a multithreaded program which has:

- a set of threads, each waits for a specific interrupt and, when the interrupt fires, the thread adds an action request to an event queue and then waits on the interrupt monitor for the next one to occur. If its not possible to wait on an interrupt then these threads would scan for an interrupt and, if one is not found, wait a short time before scanning again.

If detection is fast and there are only a few interrupt sources then this could be a single loop that scans for interrupts and adds an associated action request to the queue for every interrupt it sees. At the end of the scan list it should wait a short time before repeating the scan.

- there is only one event queue, organised as a first-in / first-out (FIFO) queue so action requests are held in the same order as they arrive

- one or more worker threads. Each grabs the next action request off the event queue, carries out the requested action and discards the request. Then it checks to see if the queue is empty. It there is another action request waiting it handles it. If the queue is empty the thread starts a timer and suspends itself.

- the timer. When this times out, it adds a wakeup action request to the event queue and stops.

- A wakeup action request does nothing: the worker thread grabs it off the queue, discards it and looks for the next request.

As I said above: in the simple case a simple scan loop may do the job, but if there are a lot of things to scan for or dealing with an event takes a long time, then a more complex interrupt handling system may be needed.

A 'short wait' might be in the range of 10 - 100 mS for starters and should be tweaked to suit the tasks the program is being asked to do, i.e. shortened if the program is slow to respond to events and lengthened if the program is just spinning and burning mpu cycles while its waiting for something to do.

--
Martin    | martin at 
Gregorie  | gregorie dot org
Reply to
Kiwi User

It depends if the code could do something else useful during the 99.99% of the time it *isn't* noticing the door become open or closed ...

Reply to
Andy Burns

ewholz,

Nope, not in your case. Than again, its just some example-grade code, and does not do anything actually usable (pardon my crudeness).

But:

Pro:

1) Using interrupts will alert you of something when it actually happens (and not after some delay). 2) you do not need to have a tight loop (with a (very?) small delay) to catch all the open/close events, so the Pi can throttle down its processor speed and draw less power. 3) You can do lengthy operations in the main loop (or in another task/process !) and still catch *all* the open and close events (how you deal with them is another matter). Which could matter when you are thinking of any kind of alarm system ...

Con: When both the interrupt routine and the main loop are modifying the same variable you need to do extra work to make sure that that will keep working.

Just imagine the interrupt routine incrementing a counter, with the main routine reading and clearing it. But an interrupt could have occurred between the reading and clearing commands, which means that the later would make the jotting-down of that event disappear ...

(The above is easy to solve though: Do not clear the variable, but just subract the just-read value from it - and loop if the value does not reach Zero).

The same goes for *any* kind of operation which involves multiple statements. (hint: look up "atomic operations")

Regards, Rudy Wieser

Reply to
R.Wieser

...and on how easy, or hard, it is to do that ?something else? while maintaining a polling rate adequate to the application.

--
-michael - NadaNet 3.1 and AppleCrate II:  http://michaeljmahon.com
Reply to
Michael J. Mahon

Well that is the point of interrupts.

Your foreground polling rate then represents how often you want to

*know* that it's happened, not how often it HAS happened, or for how long.
--
"In our post-modern world, climate science is not powerful because it is  
true: it is true because it is powerful." 

Lucas Bergkamp
Reply to
The Natural Philosopher

y

Well thanks for this scholarly reply. I have implemented a test program usi ng an interrupt on a GPIO pin - but have noticed that I was getting "interr upts" when the door was not being opened or closed. I have since discovered (complemnts of the internet) that Linux interrupts here and there, and thu s may cause the bogus messages I was getting. The python program does take up some resources, but the Pi is used only for door open/close events. I h ave concluded after reading your treatise, that an interrupt implementation is not really practical for my "bush league" program, and checking, saving , and comparing the newState and lastState is plenty good enough.

Thanks for all the replies! ewholz

Reply to
ewholz

%

? while

.

Every One! Well thanks for this scholarly reply. I have implemented a test program usi ng an interrupt on a GPIO pin - but have noticed that I was getting "interr upts" when the door was not being opened or closed. I have since discovered (complemnts of the internet) that Linux interrupts here and there, and thu s may cause the bogus messages I was getting. The python program does take up some resources, but the Pi is used only for door open/close events. I h ave concluded after reading your treatise, that an interrupt implementation is not really practical for my "bush league" program, and checking, saving , and comparing the newState and lastState is plenty good enough.

Thanks for all the replies! ewholz

Reply to
ewholz

On Sun, 25 Feb 2018 12:32:49 -0800 (PST), snipped-for-privacy@gmail.com declaimed the following:

was getting. The python program does take up some resources, but the Pi is used only for door open/close events. I have concluded after reading your treatise, that an interrupt implementation is not really practical for my "bush league" program, and checking, saving, and comparing the newState and lastState is plenty good enough.

An interrupt handler, tied to a specific interrupt, should only be getting activated by that particular interrupt. If other system interrupts are also triggering it, there would seem to be something wrong in the interrupt system.

After all, Linux uses a clock interrupt to handle time-slicing of programs -- suspending the active program and giving time to some other.

Out of curiosity, how well de-bounced is the door sensor? Even a magnetic reed switch will be subject to bouncing during transitions between open and closed, and an interrupt handler on that sensor will see many transitions.

formatting link
""" You may also notice, depending on how cleanly you press the second button, that sometimes you get more than one message for just one button press. This is called ?switch bounce?. """ and """ Update ? RPi.GPIO 0.5.2 onwards includes this debounce algorithm

Ben has included the above debounce algorithm in 0.5.2 onwards. This article was originally written for 0.5.1. So the above debounce code has been superseded by adding bouncetime=xxx, where xxx is a time in milliseconds. e.g.

GPIO.add_event_detect(channel, GPIO.RISING, callback=my_callback, bouncetime=200) """

--
	Wulfraed                 Dennis Lee Bieber         AF6VN 
    wlfraed@ix.netcom.com    HTTP://wlfraed.home.netcom.com/
Reply to
Dennis Lee Bieber

Good.

Handling events isn't always simple. I haven't run across a source I could point you at that explains why this is so.

Hence the 'treatise', which turned out to be a bit longer than I thought it would. I'd normally choose to do it in C or Java because I know that their standard libraries have decent support for both approaches, but YMMV.

--
Martin    | martin at 
Gregorie  | gregorie dot org
Reply to
Kiwi User

if it is important not to miss an event (Ie the door is opened & closed before you are able to read it) you may want to consider adding a latch of some type (S-r or D type flip flop) to the circuit that you then reset once the state change has been processed. This would be the same way a pin change interrupt in a microcontroler such as an Audrino would normally operate.

--
A journey of a thousand miles begins with a cash advance.
Reply to
alister

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.