Raspberry Pi Python Pause A Loop Sequence, When Button Pushed
Solution 1:
When monitoring a real time event such as sensors or your button your best solution will be setting up a separate thread or process that contains nothing but an infinite loop that watches the resource and sets a flag when something interesting happens.
The example below sets up a process that automatically takes a picture on the RPI aprox. every minute.
#!/usr/bin/python#Threading Prototype - Running a background thread that will take# pictures at the appropriate time#------------------------------------------------------------------from multiprocessing import Queue
from multiprocessing import Process
from time import sleep
from datetime import datetime
from datetime import timedelta
from subprocess import call
#Doing the work ---------------------------------------------------#Global Variables ---
messages = Queue()
start_time = datetime.now()
#Returns number of Milliseconds since start of programdefmilliSinceStart():
global start_time
dt = datetime.now() - start_time
ms = (dt.days * 24 * 60 * 60 + dt.seconds) * 1000 + dt.microseconds / 1000.0return ms
#Process Methods --------------------------------------------------defprocessMessages():
print"Message Processor Launched"whileTrue:
print messages.get() #should halt until message in queue
sleep(0.1) #sleep for a tick just to avoid a run away processdefprocessPicutres():
print"Picture Taker Launched"
pictureCycleStart = milliSinceStart()
index = 0whileTrue:
if milliSinceStart() - pictureCycleStart > 10000: #once a minute
a = "blip" + str(index) + ".jpg"
b = "raspistill -n -t 100 -o " + a
messages.put("Click")
call ([b], shell=True)
messages.put("picture taken - " + b)
index = index + 1
pictureCycleStart = milliSinceStart()
sleep(0.1) #wait a tick -- don't hog processor timedefmain():
print"MultiProcessing Prototype"print"Launching message process"
Process(target=processMessages).start()
print"Back from launch"print"Launching picture taking process"
Process(target=processPicutres).start()
print"Back from launch"
cycleStart = milliSinceStart()
index = 0whileTrue:
if milliSinceStart() - cycleStart > 1000:
messages.put("Tick " + str(index))
cycleStart = milliSinceStart()
index = index + 1if __name__ == "__main__":
main()
The main method launches the Messaging and Picture processes and then sets up its own little infinite loop that does nothing more that display the message "Tick" every second. The picture process sets up a separate infinite loop, watching the clock and taking a picture periodically. The Message process monitors the picture process (again, an infinite loop) and when it detects that a picture has been taken, it outputs the fact to the screen.
The important part of this for your purpose is the message queue. The process queue is what is allowing the Picture and Message processes to communicate.
And because the task take place in different processes, it matters not if one process pauses as the others are always active. If you set up a button monitor process you can be checking message queue for this fact and halting your main program when the button is pressed. This pause in the main program would not effect the button process which could then pick up on the fact that the button is pressed again.
Solution 2:
If the button is the GPIO switch as you mentioned at the end of the question, instead of the webpage button, then you can make use of an inbuilt GPIO interrupt function that saves your computer the resouces of constant polling:
import RPi.GPIO as GPIO
from threading import Event # We'll use it like time.sleep, but we can interrupt it.
GPIO_nek=11
GPIO_schouder=12
GPIO_rug1=8
GPIO_ONOFF=18
interval1 = 2
interval2 = 4
GPIO.setup(GPIO_ONOFF, GPIO.IN, pull_up_down=GPIO.PUD_UP)
done = False# loop control
timer = Event()
defquit_loop(): # Called by inbuilt threaded interruptglobal done
done = True
timer.set() # Interrupt the waiting
GPIO.add_event_detect(GPIO_ONOFF, GPIO.FALLING, callback=quit_loop, bouncetime=300) # Setup interrupt to call quit_loop
Because you're using this to break out of a loop, you want to shorten that loop to a single process:
tasks = [
(GPIO_nek, GPIO.LOW, interval1),
(GPIO_schouder, GPIO.LOW, interval1),
(GPIO_nek, GPIO.HIGH, interval1),
(GPIO_rug1, GPIO.LOW, interval2),
(GPIO_schouder, GPIO.HIGH, 0) ]
for pin, level, interval in tasks * 20: # Above you ran it 20 times, this notation keeps it in a single loop to break our oif not done:
GPIO.digitalWrite(pin, level)
timer.wait(interval)
else:
timer.clear()
break
By using the threading Event().wait() and .set() instead of the standard time.sleep() you won't even have to wait for the sleep interval to finish.
Post a Comment for "Raspberry Pi Python Pause A Loop Sequence, When Button Pushed"