Reputation: 3993
I'm running a cubieboard and accessing the GPIO pins. one GPIO pin has an output to an LED which turns it on and off every 1000ms when running this function:
def testRunning():
while 1:
wiringpi2.digitalWrite(pin3,HIGH)
wiringpi2.delay(1000)
wiringpi2.digitalWrite(pin3,LOW)
wiringpi2.delay(1000)
next I have a function to listen for a button press on another GPIO pin and when this is set to high (1) it causes another red LED to flash 20 times (I'm not sure if this is the best way to go about it):
def stopButton():
while 1:
wiringpi2.pinMode(52,0)
stopBut = wiringpi2.digitalRead(52)
print (stopBut) # this is just for debugging
wiringpi2.delay(500)
if (stopBut == 1):
break
redBlink = int(0)
while (redBlink < int(20)):
wiringpi2.digitalWrite(pin2,HIGH)
wiringpi2.delay(50)
wiringpi2.digitalWrite(pin2,LOW)
wiringpi2.delay(50)
redBlink += int(1)
print redBlink
Both of these work just as excepted when run separately.
Now I want to run both of these at the same time so the testRunning LED is blinking until the stopButton is pressed and the red LED blinks and the program stops. I've tried this:
from multiprocessing import Process
if __name__ == '__main__':
Process(target = stopButton()).start()
Process(target = testRunning()).start()
When running this code the stopButton is executed and sits waiting for the button press as expected but the testRunning code is not executed until the stoButton code has finished running (IE the button is pressed the LED is looped 20times and that function exits).
Upvotes: 1
Views: 1482
Reputation: 18292
You need to use some sort of parallel processing for this to work as well as create a way to interrupt your running thread.
Read up on threading and create and start your two Thread
objects, one for each method. The overall approach I'd take is to read a boolean in your testRunning()
method and to write to it in your stopButton()
method.
if not keepRunning:
return
and insert that just before each of your wiringpi2.digitalWrite()
calls. You can be a little more advanced by using notify()
with a timeout to cause the stopButton()
to end the testRunning()
method instantly instead of on the delay.
Last tricky part: remember to join()
your threads after starting them.
import threading
import sys
checkRunState = threading.Condition()
keepRunning = True
def stopButton():
# since I didn't set up objects, use a global
global keepRunning
# block until the enter key is pressed
sys.stdin.readline()
keepRunning = False
# acquire because that must be done before making an action
# then notify anything that needs to know if we're still supposed
# to keep running
checkRunState.acquire()
checkRunState.notifyAll()
checkRunState.release()
print "HAMMER TIME"
def blinky():
global keepRunning
checkRunState.acquire()
redBlink = int(0)
while (redBlink < int(20)):
redBlink += int(1)
# instead of a sleep(), use this for timing since it will
# be woken up right away if the stop condition changes
checkRunState.wait(.1)
if not keepRunning:
checkRunState.release()
return
print "blinky!"
checkRunState.release()
stopper = threading.Thread(target=stopButton)
stopper.daemon = True
blinker = threading.Thread(target=blinky)
blinker.start()
stopper.start()
blinker.join()
# stopper() never unblocks. Setting it as a daemon thread
# means that python won't keep running because of it and we
# shouldn't try to join it
Upvotes: 1
Reputation: 8910
In Python, you can think of ()
as the call operator. Process(target = stopButton()).start()
calls stopButton()
, waits for it to complete, then passes its return value (None
) to the Process
constructor.
Use Process(target = stopButton).start()
instead.
Upvotes: 1