新手:又一个非阻塞延迟:延迟LED开启而没有睡眠()

时间:2017-10-05 04:43:37

标签: python raspberry-pi

我有一个运行Flask框架的Raspberry Pi来创建一个非常特定于应用程序的http服务器。在Pi服务器上执行特定页面的HTTP GET会触发GPIO操作(例如:检查是否按下按钮,LED亮起,LED熄灭等)。因为我将轮询 / status 页面以查看按钮是否以250毫秒间隔按下,我不希望轮询 / unlock 页面使用timer.sleep( 0.25)关闭继电器250ms。

我想设置一个动作,当被叫时,将等待250ms,关闭LED然后悄悄地离开。我尝试了线程和sched。线程工作ONCE并在我第二次传递代码时抛出错误(引发RuntimeError(“线程只能启动一次”))。

#
# lots of other defines and includes
#
import threading
# set up function to turn de-energize relay (and Green LED)
def LED_Off_Wait():
    GPIO.output(GREEN, False)

# set up timed thread
LED_Off = threading.Timer(0.25, LED_Off_Wait)

#
# flask framework page definitions go here
#

# unlock page where we energize and de-energize a lock
@app.route('/unlock')
def thing_unlock():
    GPIO.output(GREEN, True) # energize the relay (and green LED)
#    time.sleep(0.25) # don't want to do this
#    GPIO.output(GREEN, False) #don't want to do this
    LED_Off.start() # trigger the non-blocking thread to turn off 
                    #  the GPIO pin in 0.25s
# more flask stuff...
    response = make_response(render_template('body.html', response='unlocked'))
    response.headers['Access-Control-Allow-Origin'] = '*'
    return response

我也尝试了sched,它对我不起作用,虽然可能是因为我从内到外编程,边做边学:

import sched

def LED_Off():
    GPIO.output(GREEN, False)

# set up scheduled action, as nearly as I can determine from my reading
LED_ON_Delay = sched.scheduler(time.time, time.sleep) # set up scheduler (no sleep!)
LED_ON_Delay.enter( 1, 1, LED_Off,()) # schedule LED_Off for 0.25s in the future

#
# again, more Flask stuff here
#

@app.route('/unlock')
def thing_unlock():
    GPIO.output(GREEN, True)
#    time.sleep(0.25) # don't want to do this
#    GPIO.output(GREEN, False) # don't want to do this
    LED_ON_Delay.run()  #trigger "non-blocking sleep"
    response = make_response(render_template('body.html', response='unlocked'))
    response.headers['Access-Control-Allow-Origin'] = '*'
    return response

# more Flask stuff...

结论:如果我尝试两次做错,如何在一段时间后关闭GPIO(或做任何其他事情)而没有错误的任务?

1 个答案:

答案 0 :(得分:0)

在朋友的帮助下,答案比我预期的要简单:Lambda功能。首先,import threading然后在使用threading.Timer()的时间间隔后声明将执行您想要的功能(关闭LED):

def LED_Off_Wait( wait_time,IO_port ):
    threading.Timer(wait_time, lambda: GPIO.output(IO_port, False)).start()

在这种情况下,我需要在多个地方使用它,所以我将延迟时间和它所需的GPIO引脚传递给它。

当我需要在另一个功能内部延迟后关闭LED时,我称之为:

@app.route('/unlock')
def prop_unlock():
    GPIO.output(GREEN, True)
    LED_Off_Wait( 0.5, GREEN )
    response = make_response(render_template('body.html', response='unlocked'))
    response.headers['Access-Control-Allow-Origin'] = '*'
    return response

为了完整起见,GREEN之前已定义如下:

GREEN = 24
# Use GPIO pin numbers
GPIO.setmode(GPIO.BCM)
GPIO.setup(GREEN, GPIO.OUT)

像魅力一样。