Python - executing things in parallel? - python

I have a project using two Raspberry Pis, where one should send the control signals to the other one, which should recieve and process them to control some Servomotors accordingly, all done in Python.
Now that is not a problem for me, but the problem lies in recieving the signals:
The method I use to ensure long ranges, needs to be in sync perfectly and has a timeout period. If it is not perfectly in sync, it waits for the signal and can stop the whole program for approx. 5 seconds or so.
Now, is there any possibility to let the checking and the moving be done at the same time, so that the movement stops when the signal says to stop but at the same time the checking does not interrupt the movement?
-Chrono

Related

Interrupting running code and returning to it (Python, PsychoPy, Windows)

I am fairly new to programming with Python, so forgive me if this is trivial.
I know that when programming microcontrollers it is possible to interrupt the main program (e.g. on button press or due to a timer). The interrupt leads to a code outside of the main program that is then executed. Afterwards, the main program is continued to be executed. Hereby, the interrupt handler remembers where it interrupted the main program and returns to that exact point within the code. Is it possible to implement that on Python as well?
I looked into the "threading"-library but it doesn't seem fit, since I don't want several tasks running parallel. There it seems like I have to check for an event on every second line of my main code to ensure that it really interrupts the program immediately.
If you need some context:
I am implementing a program using the "PsychoPy Coder" (PsychoPy v2021.2.3) on Windows 10.
I expect the program (when finished) to run for at least an hour, depending on the user. I want this program to be interrupted every 60 to 90 seconds for a "baseline task" the user has to solve. This baseline task will last for about 6 to 9 seconds and the actual program should continue afterwards. Also, I want the user to be able to abort the program with a specific button at anytime.
I would be very thankful for any hint on an elegant way of programming this :) Have a nice day!

delay in setting 'after' function in python tkinter

I'm writing a short application in python using tkinter. Everything works except for an unexpected pause - it should be generating an event twice a second, but frequently it will pause for 5 or 6 seconds between signals. I've put print statements to find where the delay is, and found it is the following statement:
self.frame.after(ms, self.tick_handler)
ms is 500 so this should send the event at around .5 seconds. Usually it does, but frequently it hangs for as much as 5 or 6 seconds before tick_handler() gets the signal. The program is pretty simple, with a single worker thread receiving all input from a single queue, events coming from a single tkinter frame. The after() statement is in the worker thread. I've tried shutting off gc (gc.disable()) but that makes no difference. There is minimal activity outside this on my computer.
If I send other input during the pause using mouse or keys it is handled immediately, so the worker thread is not blocked. It looks as if the signal request is received but not fired for some time. I know I can't expect real time performance so .6 seconds wouldn't be noteworthy, but 6.0 seconds?
This is the first time I've worked with tkinter. Is there something I am missing about event handling?
I Think You Did Not Include tkinter.mainloop() At The End
PS: I'm Not Sure...
When using the after method in tkinter, instead of doing root.after(function_name,time_delayed) do root.after(function_name(),time_delayed) as this worked for me and the delay disappeared.

Control Multiple Raspberry Pis Remotely / Gameshow Type System

I am trying to set up a gameshow type system where I have 5 stations each having a monitor and a button. The monitor will show a countdown timer and various animations. My plan is to program the timer, animations, and button control through pygame and put a pi at each station each running it's own pygame script, waiting for the start signal (can be keypress or gpio).
I'm having trouble figuring out how to send that signal simultaneously to all stations. Additionally I need to be able to send a 'self destruct' signal to each station to stop the timer. I can ssh into each station but I don't know how to send keypress/gpio signals through the command line to a running pygame script..
I was thinking of putting a rf receiver on each pi, all at the same wavelength and using a common transmitter, but that seems very hacky and not necessarily so simultaneous.
This ought to work ... but it's purely hypothetical:
Use a parallel circuit to set a pin "high" and "low" - "high" means start the timer; "low" means stop the timer. The next "high" resets and restarts the timer.
You could use two circuits. One for start/stop and one for "reset". You'd probably need some code to not reset while running.
The parallel circuit can be controlled manually (for testing) or automatically (perhaps with a master program?).

Having trouble with sleep.time, is there an alternative

I'm writing a program to control GPIO's on my raspberry pi. I would like my program to ask me how long I would like to keep a GPIO on before it turns off.
Is it possible to have it stay on for 1 hour and then turn off. The problem I'm having is that when its on for an hour I cant issue any other commands to turn on other GPIO's because sleep.time is still being processed. I'd like to set multiple GPIO's for different times at the same time.
There are many ways to solve the problem. Conceptually, instead of sleeping 30 seconds and then doing something, you can sleep one second, do a bunch of stuff, check the time, lather, rinse, repeat. And by "sleep one second" it could just as easily be a tenth of a second or five seconds or whatever seems reasonable to me.
Another solution is to create a second thread (or process) for this sleep command so that your main thread (or process) runs unabated.
The choice depends on what all you need to do, how accurate you need the delay to be, what other things are running on the system, and so on.
Your current script only have one thread running, the sleep() will put the current running thread into sleep mode which blocks further commands.
time.sleep(secs) Python Doc
time.sleep(secs)
Suspend execution of the current thread for the given number of seconds.
You will need one more thread on the background which keeps the timer for you. In the mean time, the thread on the foreground can still takes other commands.
I recommend you read this page
threading – Manage concurrent threads

Force Python to run in a single thread

I am using Python with the Rasbian OS (based on Linux) on the Raspberry Pi board. My Python script uses GPIOs (hardware inputs). I have noticed when a GPIO activates, its callback will interrupt the current thread.
This has forced me to use locks to prevent issues when the threads access common resources. However it is getting a bit complicated. It struck me that if the GPIO was 'queued up' until the main thread went to sleep (e.g. hits a time.sleep) it would simplify things considerably (i.e. like the way that javascript deals with things).
Is there a way to implement this in Python?
Are you using RPi.GPIO library? Or you call your Python code from C when a callback fires?
In case of RPi.GPIO, it runs a valid Python thread, and you do not need extra synchronization if you organize the threads interaction properly.
The most common pattern is to put your event in a queue (in case of Python 3 this library will do the job, Python 2 has this one). Then, when your main thread is ready to process the event, process all the events in your queue. The only problem is how you find a moment for processing them. The simplest solution is to implement a function that does that and call it from time to time. If you use a long sleep call, you may have to split it into many smaller sleeps to make sure the external events are processed often enough. You may even implement your own wrapper for sleep that splits one large delay into several smaller ones and processes the queue between them. The other solution is to use Queue.get with timeout parameter instead of sleep (it returns immediately after an event arrives into the queue), however, if you need to sleep exactly for a period you specified, you may have to do some extra magic such as measuring the time yourself and calling get again if you need to wait more after processing the events.
Use a Queue from the multithreading module to store the tasks you want to execute. The main loop periodically checks for entries in the queue and executes them one by one when it finds something.
You GPIO monitoring threads put their tasks into the queue (only one is required to collect from many threads).
You can model your tasks as callable objects or function objects.

Categories

Resources