Python 按下按钮时,树莓皮蟒蛇暂停一个循环序列

Python 按下按钮时,树莓皮蟒蛇暂停一个循环序列,python,raspberry-pi,gpio,webiopi,Python,Raspberry Pi,Gpio,Webiopi,我有一个树莓皮2。有了一个中继板,我用它来控制开关序列(比如交通灯)。 我使用一个叫做“webiopi”的工具在网站上创建按钮。单击该按钮后,下面python脚本的功能将启动 我想要的是在单击另一个按钮时打破循环(或暂停循环)。但是,只要这个循环在运行,工具就不会查看网页 这里会问一个类似的问题,但这是针对单个事件的,解决方案在我的案例中不起作用 问题是。如何使此脚本在循环运行时查看单击的按钮(也可以是gpio开关) GPIO_nek=11 GPIO_schouder=12 GPIO_rug1

我有一个树莓皮2。有了一个中继板,我用它来控制开关序列(比如交通灯)。 我使用一个叫做“webiopi”的工具在网站上创建按钮。单击该按钮后,下面python脚本的功能将启动

我想要的是在单击另一个按钮时打破循环(或暂停循环)。但是,只要这个循环在运行,工具就不会查看网页

这里会问一个类似的问题,但这是针对单个事件的,解决方案在我的案例中不起作用

问题是。如何使此脚本在循环运行时查看单击的按钮(也可以是gpio开关)

GPIO_nek=11 
GPIO_schouder=12
GPIO_rug1=8
GPIO_ONOFF=18
interval1 = 2
interval2 = 4
for x in range(0, 20):
    GPIO.digitalWrite(GPIO_nek, GPIO.LOW)
    time.sleep(interval1)
    GPIO.digitalWrite(GPIO_schouder, GPIO.LOW)
    time.sleep(interval1)
    GPIO.digitalWrite(GPIO_nek, GPIO.HIGH)
    time.sleep(interval1)
    GPIO.digitalWrite(GPIO_rug1, GPIO.LOW)
    time.sleep(interval2)
    GPIO.digitalWrite(GPIO_schouder, GPIO.HIGH)
    if (GPIO.digitalRead(GPIO_ONOFF) == GPIO.LOW):
        GPIO.digitalWrite(GPIO_ONOFF, GPIO.HIGH)
        break

当监控实时事件(如传感器或按钮)时,最好的解决方案是设置一个单独的线程或进程,该线程或进程只包含一个无限循环,用于监视资源并在发生有趣的事件时设置标志

下面的示例设置了一个在RPI aprox上自动拍照的过程。每一分钟

#!/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 program
def milliSinceStart():
    global start_time
    dt = datetime.now() - start_time
    ms = (dt.days * 24 * 60 * 60 + dt.seconds) * 1000 + dt.microseconds / 1000.0
    return ms

#Process Methods --------------------------------------------------
def processMessages():
    print "Message Processor Launched"
    while True:
        print messages.get()  #should halt until message in queue
        sleep(0.1) #sleep for a tick just to avoid a run away process

def processPicutres():
    print "Picture Taker Launched"
    pictureCycleStart = milliSinceStart()
    index = 0

    while True:
        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 time




def main():
    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 = 0
    while True:
        if milliSinceStart() - cycleStart > 1000:
            messages.put("Tick " + str(index))
            cycleStart = milliSinceStart()
            index = index + 1


if __name__ == "__main__":
      main()
main方法启动消息传递和图片处理,然后建立自己的小无限循环,它不做更多的事情,每秒显示消息“嘀嗒”。图片处理建立了一个独立的无限循环,观察时钟并定期拍照。消息进程监视图片进程(同样是一个无限循环),当它检测到已拍摄图片时,它将事实输出到屏幕

对于您来说,这其中的重要部分是消息队列。进程队列允许图片和消息进程进行通信


由于任务发生在不同的进程中,因此一个进程是否暂停并不重要,因为其他进程始终处于活动状态。如果您设置了一个按钮监视器进程,您可以检查消息队列中是否存在此事实,并在按下按钮时停止主程序。主程序中的这种暂停不会影响按钮过程,当再次按下按钮时,按钮过程可能会出现。

如果按钮是问题末尾提到的GPIO开关,而不是网页按钮,然后,您可以使用内置的GPIO中断功能,以节省计算机的持续轮询资源:

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()
def quit_loop():  # Called by inbuilt threaded interrupt
    global 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
因为您正在使用它来打破循环,所以希望将该循环缩短为单个进程:

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 o
    if not done:
        GPIO.digitalWrite(pin, level)
        timer.wait(interval)
    else:
        timer.clear()
        break

通过使用threading Event().wait()和.set()而不是标准的time.sleep(),您甚至不必等待睡眠时间间隔结束。

感谢您发送这封有详细文档记录的回复。我将与您的输入一起工作,并将在准备好时发布最终解决方案。请给我检查答案,我将不胜感激。:-)保罗,这是解决这个问题的好办法。非常感谢你的建议。我会试试这个,把最后的解决方案放在这里。