Python 基于值停止函数

Python 基于值停止函数,python,raspberry-pi,Python,Raspberry Pi,我正在raspberry pi上运行python脚本 基本上,我希望相机每5秒拍一张照片,但前提是我将布尔值设置为true,并在物理按钮上切换 最初我将其设置为true,然后在while(true)循环中,我想检查变量是否设置为true,如果设置为true,则每5秒开始拍照。问题是,如果我使用类似timetime.sleep(5),它实际上冻结了一切,包括支票。再加上我对按钮使用去抖动,我就不可能真正切换脚本,因为我必须在5秒的等待时间后按下它,正好用于值检查。。。我一直在四处寻找,我认为可能的

我正在raspberry pi上运行python脚本

基本上,我希望相机每5秒拍一张照片,但前提是我将布尔值设置为true,并在物理按钮上切换

最初我将其设置为true,然后在while(true)循环中,我想检查变量是否设置为true,如果设置为true,则每5秒开始拍照。问题是,如果我使用类似time
time.sleep(5)
,它实际上冻结了一切,包括支票。再加上我对按钮使用去抖动,我就不可能真正切换脚本,因为我必须在5秒的等待时间后按下它,正好用于值检查。。。我一直在四处寻找,我认为可能的解决方案应该包括线程,但我不能对此束手无策。我想到的一种解决方法是查看系统时间,如果秒数是5的倍数,则拍照(全部在主循环内)。这似乎有点粗略

脚本如下:

### Imports
from goprocam import GoProCamera, constants
import board
import digitalio
from adafruit_debouncer import Debouncer
import os
import shutil
import time


### GoPro settings
goproCamera = GoProCamera.GoPro()


### Button settings
pin = digitalio.DigitalInOut(board.D12)
pin.direction = digitalio.Direction.INPUT
pin.pull = digitalio.Pull.UP
switch = Debouncer(pin, interval=0.1)



save = False #this is the variable


while(True):
    switch.update()
    if switch.fell:
        print("Pressed, toggling value")
        save = not save
        
    if save:
        goproCamera.take_photo()
        goproCamera.downloadLastMedia()
        time.sleep(5)

这里有一些东西可以尝试:

while(True):
    switch.update()
    if switch.fell:
        print("Pressed, toggling value")
        save = not save
    if save:
        current_time = time.time()
        if current_time - last_pic_time >= 5:
            goproCamera.take_photo()
            goproCamera.downloadLastMedia() 
            last_pic_time = current_time
根据您想要的行为类型,您可能需要调整调用
time.time()
的时间和频率。

干杯! 也许是这样的

import threading

def set_interval(func, sec):
    def func_wrapper():
        set_interval(func, sec)
        func()
    t = threading.Timer(sec, func_wrapper)
    t.start()
    return t
我们在主循环中调用上面的函数

将while循环内容包装到函数上:

def take_photo:
    goproCamera.take_photo()
    goproCamera.downloadLastMedia()
现在,我们创建一个最初设置为False的标志,以避免创建多个线程。 注意,我在while循环之前做了这个。我们只需要一个起始值

active = False

while(True):
    switch.update()
    if switch.fell:
        print("Pressed, toggling value")
        save = not save

    if save: # we need to start taking photos.
        if not active: # it is not active... so it is the first time it is being called or it has been toggled to save as True again.
            photo_thread = set_interval(take_photo, 5) # grabbing a handle to the thread - photo_thread - so we can cancel it later when save is set to False.
            active = True # marking as active to be skipped from the loop until save is False
    else:
        try: # photo_thread may not exist yet so I wrapped it inside a try statement here.
            photo_thread.cancel() #  if we have a thread we kill it
        active = False #setting to False so the next time the button is pressed we can create a new one.
让我知道它是否有效。=)

我最终做了什么:

### Imports
from goprocam import GoProCamera, constants
import board
import digitalio
from adafruit_debouncer import Debouncer
import os

import time
import threading

### GoPro settings
gopro = GoProCamera.GoPro()


### Button settings
pin = digitalio.DigitalInOut(board.D12)
pin.direction = digitalio.Direction.INPUT
pin.pull = digitalio.Pull.UP
switch = Debouncer(pin, interval=0.1)

### Picture save location
dir_path = os.path.dirname(os.path.realpath(__file__))
new_path = dir_path+"/pictures/"

save = False

### Functions
def takePhoto(e):
    while e.isSet():
        gopro.take_photo()
        gopro.downloadLastMedia()
        fname = '100GOPRO-' + gopro.getMedia().split("/")[-1]
        current_file = dir_path+'/'+fname
        if os.path.isfile(current_file):
            os.replace(current_file, new_path+fname) #move file, would be cleaner to download the file directly to the right folder, but the API doesn't work the way I thought it did
        e.wait(5)
        

### Initial settings
        
e = threading.Event()
t1 = threading.Thread(target=takePhoto, args=([e]))

print("Starting script")
while(True):
    switch.update()
    if switch.fell:
        #toggle value
        save = not save
    if save:
        e.set() #should be taking pictures
    else:
        e.clear() #not taking pictures
        
    if not t1.is_alive(): #start the thread if it hasn't been yet
        if e.is_set():
            t1.start()

一旦您进入
while(save)
块,您就永远不会将
save
的值更改回
False
,因此您永远不会退出代码的该部分,这就是您“冻结”状态的原因。我想第二个while可能是if语句。但问题仍然是,要关闭它,我必须精确地计算按下按钮的时间。我将编辑这个问题。我觉得这是一个正确的方向。出现运行时错误:无法启动新线程错误。然后脚本继续,但按钮不执行任何启动/停止操作。是的,无法启动新线程错误在这里有意义,因为我们正在每个循环中调用set interval。。。我们需要一个旗子或者什么东西来称呼它一次。我会在这里尝试一下,然后再给你回复。我想我已经找到了好办法。很高兴它成功了。出于好奇,我对它的看法是否仍有错误?不幸的是,我没有进一步研究它。。。我确实在下面发布了我的解决方案,这很有效。