在 GPIO.RPi 回调事件中中断 while 循环
Break while loop in GPIO.RPi callback event
我已经尝试解决这个问题好几个小时了,但无济于事。
所以,我一直在尝试 运行 一个 OLED 屏幕来显示天气、时间等。我用 while 循环编写了脚本,这样它几乎可以永远 运行。但是,我还希望能够以 GPIO 上拉启动脚本,并以另一个高 GPIO 引脚结束脚本。
使用开关脚本启动 OLED 脚本可以完美地处理变量,但脚本似乎对我的“Off-GPIO”试图引入的变量更改视而不见。这是我的代码:
from oledscriptwithfunc import oledfunc
from reset import rstfunc
import RPi.GPIO as GPIO
var = None
def button_callback(channel):
print("Initializing..")
oledfunc(2) # set on-off variable to two so while loop can start (see next block of code)
def offbutton(channel):
print("Ending program..")
oledfunc(1) # set on-off variable as off..
rstfunc() # reset OLED screen
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(10, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(9, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.add_event_detect(10,GPIO.RISING,callback=button_callback) # GPIO on "switch"
GPIO.add_event_detect(9,GPIO.RISING,callback=offbutton) # GPIO off "switch"
message = input("Press enter to quit\n")
GPIO.cleanup()
--------------------------oledscriptwithfunc.py-------------
def oledfunc(var): # function used in previous script, var is set by GPIO
var = var
import digitalio
import threading
import busio
import board
from PIL import Image, ImageDraw, ImageFont
i2c = busio.I2C(board.SCL, board.SDA)
import requests
import adafruit_ssd1306
oled = adafruit_ssd1306.SSD1306_I2C(128, 32, i2c, addr=0x3c)
oled.fill(0)
oled.show()
image = Image.new("1", (128, 32))
draw = ImageDraw.Draw(image)
draw.rectangle((0, 0, 128, 32), outline=255, fill=255)
font = ImageFont.load_default()
import datetime
oled.image(image)
oled.show()
import time
timer1 = time.perf_counter()
while var != 1: # used for on-off toggle
timer2 = time.perf_counter()
if int((timer2 - timer1)) in range(0,1) or int((timer2 - timer1)) % 1800 == 0:
response = requests.get("https://api.openweathermap.org/data/2.5/weather?lat=xxxx&lon=xxxxx&lang=de&units=metric&appid=xxxxxxxxxxxxxxxxxx")
data = response.json()
for weatherdata in data['weather']:
status = weatherdata['description']
redvar = data['main']
temp = redvar['temp']
temptext = "{}C".format(temp)
else:
while var != 1: # on-off toggle variable
t_end = time.time() + 10
while time.time() < t_end:
now = datetime.datetime.now()
testvar = now.strftime("%d-%m-%Y")
vartwo = now.strftime("%M:%S")
newvr = int(now.strftime("%H"))
newervr = newvr + 2
text = testvar + " " + "{}:".format(newervr) + "{}".format(vartwo)
draw.rectangle((0, 0, 128, 32), outline=255, fill=255)
draw.rectangle((6, 6, 122, 26), outline = 0, fill = 0)
(font_width, font_height) = font.getsize(text)
draw.text((oled.width//2 - font_width//2, oled.height//2 - font_height//2),
text, font=font, fill=255)
oled.image(image)
oled.show()
draw.rectangle((0, 0, 128, 32), outline = 0, fill = 0)
(font_width, font_height) = font.getsize(temptext)
draw.text((oled.width//2 - font_width//2, oled.height//2 - font_height//2),
temptext, font=font, fill=255)
oled.image(image)
oled.show()
time.sleep(5)
draw.rectangle((0, 0, 128, 32), outline = 0, fill = 0)
text = status
(font_width, font_height) = font.getsize(text)
draw.text((oled.width//2 - font_width//2, oled.height//2 - font_height//2),
text, font=font, fill=255)
oled.image(image)
oled.show()
time.sleep(5)
如果这里有很多错误代码,我深表歉意,我才刚刚开始编程 Python。我希望我已经很好地解释了这个问题。总结一下:使用“var”变量,我希望能够打开和关闭“oledscriptwithfunc.py”。问题是我只能启动它,但再也不能更改变量,所以我可以将其关闭。我评论了代码中最多 important/non-functional 位。请忽略 OLED setup/weather API 调用,我只是想我应该包括它以显示代码的整个内部工作原理。是否存在冲突,或者我只是使用了错误的方法来完成这项工作?
好吧,经过一番修修补补,我找到了解决办法!
我发现 RPi.GPIO 有一种使用 input.GPIO(channel) 检查引脚状态的简单方法。 [这给我上了宝贵的一课:始终阅读文档] 我只是做了一些简单的 if 和 while 语句来解决我的问题。这种方式有它自己的注意事项,但它做了我想要它做的事情。
我已经尝试解决这个问题好几个小时了,但无济于事。 所以,我一直在尝试 运行 一个 OLED 屏幕来显示天气、时间等。我用 while 循环编写了脚本,这样它几乎可以永远 运行。但是,我还希望能够以 GPIO 上拉启动脚本,并以另一个高 GPIO 引脚结束脚本。 使用开关脚本启动 OLED 脚本可以完美地处理变量,但脚本似乎对我的“Off-GPIO”试图引入的变量更改视而不见。这是我的代码:
from oledscriptwithfunc import oledfunc
from reset import rstfunc
import RPi.GPIO as GPIO
var = None
def button_callback(channel):
print("Initializing..")
oledfunc(2) # set on-off variable to two so while loop can start (see next block of code)
def offbutton(channel):
print("Ending program..")
oledfunc(1) # set on-off variable as off..
rstfunc() # reset OLED screen
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(10, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(9, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.add_event_detect(10,GPIO.RISING,callback=button_callback) # GPIO on "switch"
GPIO.add_event_detect(9,GPIO.RISING,callback=offbutton) # GPIO off "switch"
message = input("Press enter to quit\n")
GPIO.cleanup()
--------------------------oledscriptwithfunc.py-------------
def oledfunc(var): # function used in previous script, var is set by GPIO
var = var
import digitalio
import threading
import busio
import board
from PIL import Image, ImageDraw, ImageFont
i2c = busio.I2C(board.SCL, board.SDA)
import requests
import adafruit_ssd1306
oled = adafruit_ssd1306.SSD1306_I2C(128, 32, i2c, addr=0x3c)
oled.fill(0)
oled.show()
image = Image.new("1", (128, 32))
draw = ImageDraw.Draw(image)
draw.rectangle((0, 0, 128, 32), outline=255, fill=255)
font = ImageFont.load_default()
import datetime
oled.image(image)
oled.show()
import time
timer1 = time.perf_counter()
while var != 1: # used for on-off toggle
timer2 = time.perf_counter()
if int((timer2 - timer1)) in range(0,1) or int((timer2 - timer1)) % 1800 == 0:
response = requests.get("https://api.openweathermap.org/data/2.5/weather?lat=xxxx&lon=xxxxx&lang=de&units=metric&appid=xxxxxxxxxxxxxxxxxx")
data = response.json()
for weatherdata in data['weather']:
status = weatherdata['description']
redvar = data['main']
temp = redvar['temp']
temptext = "{}C".format(temp)
else:
while var != 1: # on-off toggle variable
t_end = time.time() + 10
while time.time() < t_end:
now = datetime.datetime.now()
testvar = now.strftime("%d-%m-%Y")
vartwo = now.strftime("%M:%S")
newvr = int(now.strftime("%H"))
newervr = newvr + 2
text = testvar + " " + "{}:".format(newervr) + "{}".format(vartwo)
draw.rectangle((0, 0, 128, 32), outline=255, fill=255)
draw.rectangle((6, 6, 122, 26), outline = 0, fill = 0)
(font_width, font_height) = font.getsize(text)
draw.text((oled.width//2 - font_width//2, oled.height//2 - font_height//2),
text, font=font, fill=255)
oled.image(image)
oled.show()
draw.rectangle((0, 0, 128, 32), outline = 0, fill = 0)
(font_width, font_height) = font.getsize(temptext)
draw.text((oled.width//2 - font_width//2, oled.height//2 - font_height//2),
temptext, font=font, fill=255)
oled.image(image)
oled.show()
time.sleep(5)
draw.rectangle((0, 0, 128, 32), outline = 0, fill = 0)
text = status
(font_width, font_height) = font.getsize(text)
draw.text((oled.width//2 - font_width//2, oled.height//2 - font_height//2),
text, font=font, fill=255)
oled.image(image)
oled.show()
time.sleep(5)
如果这里有很多错误代码,我深表歉意,我才刚刚开始编程 Python。我希望我已经很好地解释了这个问题。总结一下:使用“var”变量,我希望能够打开和关闭“oledscriptwithfunc.py”。问题是我只能启动它,但再也不能更改变量,所以我可以将其关闭。我评论了代码中最多 important/non-functional 位。请忽略 OLED setup/weather API 调用,我只是想我应该包括它以显示代码的整个内部工作原理。是否存在冲突,或者我只是使用了错误的方法来完成这项工作?
好吧,经过一番修修补补,我找到了解决办法! 我发现 RPi.GPIO 有一种使用 input.GPIO(channel) 检查引脚状态的简单方法。 [这给我上了宝贵的一课:始终阅读文档] 我只是做了一些简单的 if 和 while 语句来解决我的问题。这种方式有它自己的注意事项,但它做了我想要它做的事情。