Python 基于值停止函数
我正在raspberry pi上运行python脚本 基本上,我希望相机每5秒拍一张照片,但前提是我将布尔值设置为true,并在物理按钮上切换 最初我将其设置为true,然后在while(true)循环中,我想检查变量是否设置为true,如果设置为true,则每5秒开始拍照。问题是,如果我使用类似timePython 基于值停止函数,python,raspberry-pi,Python,Raspberry Pi,我正在raspberry pi上运行python脚本 基本上,我希望相机每5秒拍一张照片,但前提是我将布尔值设置为true,并在物理按钮上切换 最初我将其设置为true,然后在while(true)循环中,我想检查变量是否设置为true,如果设置为true,则每5秒开始拍照。问题是,如果我使用类似timetime.sleep(5),它实际上冻结了一切,包括支票。再加上我对按钮使用去抖动,我就不可能真正切换脚本,因为我必须在5秒的等待时间后按下它,正好用于值检查。。。我一直在四处寻找,我认为可能的
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。。。我们需要一个旗子或者什么东西来称呼它一次。我会在这里尝试一下,然后再给你回复。我想我已经找到了好办法。很高兴它成功了。出于好奇,我对它的看法是否仍有错误?不幸的是,我没有进一步研究它。。。我确实在下面发布了我的解决方案,这很有效。