我正在一个Raspberry Pi项目中,在这里我有一个OLED显示器,它在True-loop中不断地用Python中的信息更新。但是,每当我按下按钮(GPIO 5)时,只要按下按钮,或者可能在预定的时间段内,我都希望显示一些其他静态信息(例如系统信息)。释放按钮后,“主循环”可能会再次接管。 我试图使用RPi.GPIO和回调函数来实现此功能以显示系统信息,但是问题是,即使在执行回调函数期间,主循环仍会继续写入OLED,如果按下GPIO 5:两个“线程”正在同时写入OLED ...
我假设我需要一种在回调函数期间暂停主循环执行的方法,并且我已经尝试了Semaphore和aquire / release,但是没有运气。我还考虑了将两个回调函数与Semaphore结合使用的可能性,但是由于主循环中显示的信息应该不断更新(例如,不是由中断驱动),所以我不确定这是否是我的解决方案。 / p>
在这一点上,我什至不知道接下来要用谷歌搜索什么。也许这里有人可以启发我?这是做这种事情的完全错误的方式吗? (有限的Python使用经验...)
下面是一个简化的代码示例,它模拟了我想做的事情。
import time
import Adafruit_GPIO.SPI as SPI
import RPi.GPIO as GPIO
import Adafruit_SSD1306
from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont
# Initialize
disp = Adafruit_SSD1306.SSD1306_128_64(rst=None)
disp.begin()
disp.clear()
disp.display()
image = Image.new('1', (disp.width, disp.height))
draw = ImageDraw.Draw(image)
font = ImageFont.load_default()
GPIO.setmode(GPIO.BCM)
GPIO.setup(5, GPIO.IN, pull_up_down=GPIO.PUD_UP) # Input with pull-up
def clear_display():
draw.rectangle((0,0,disp.width,disp.height), outline=0, fill=0)
disp.image(image)
disp.display()
# Callback function
def display_system_info(channel):
draw.text((0, 0), "System info displayed", font=font, fill=255)
draw.text((0, 9), "for five seconds.", font=font, fill=255)
disp.image(image)
disp.display()
time.sleep(5)
clear_display()
GPIO.add_event_detect(5, GPIO.RISING, callback=display_system_info, bouncetime=200)
try:
while True:
for counter in range(7):
draw.text((0,counter*9), "Printing line {0:d}".format(counter), font=font, fill=255)
disp.image(image)
disp.display()
time.sleep(1)
clear_display()
except KeyboardInterrupt:
GPIO.cleanup() # clean up GPIO on CTRL+C exit
GPIO.cleanup() # clean up GPIO on normal exit
非常感谢您的帮助。
/ N
答案 0 :(得分:0)
我正在使用全局变量-buttonPressed解决这种情况。 当您按下按钮(GPIO 5)时,buttonPressed设置为True,主循环不执行任何操作。 希望对您很清楚,对您有帮助。
import time
import Adafruit_GPIO.SPI as SPI
import RPi.GPIO as GPIO
import Adafruit_SSD1306
from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont
# Initialize
disp = Adafruit_SSD1306.SSD1306_128_64(rst=None)
disp.begin()
disp.clear()
disp.display()
image = Image.new('1', (disp.width, disp.height))
draw = ImageDraw.Draw(image)
font = ImageFont.load_default()
GPIO.setmode(GPIO.BCM)
GPIO.setup(5, GPIO.IN, pull_up_down=GPIO.PUD_UP) # Input with pull-up
buttonPressed = False
def clear_display():
draw.rectangle((0,0,disp.width,disp.height), outline=0, fill=0)
disp.image(image)
disp.display()
# Callback function
def display_system_info(channel):
global buttonPressed
buttonPressed = True
draw.text((0, 0), "System info displayed", font=font, fill=255)
draw.text((0, 9), "for five seconds.", font=font, fill=255)
disp.image(image)
disp.display()
time.sleep(5)
clear_display()
buttonPressed = False
GPIO.add_event_detect(5, GPIO.RISING, callback=display_system_info, bouncetime=200)
try:
while True:
if(not buttonPressed):
for counter in range(7):
draw.text((0,counter*9), "Printing line {0:d}".format(counter), font=font, fill=255)
disp.image(image)
disp.display()
time.sleep(1)
clear_display()
except KeyboardInterrupt:
GPIO.cleanup() # clean up GPIO on CTRL+C exit
GPIO.cleanup() # clean up GPIO on normal exit
尝试让我知道。
答案 1 :(得分:0)
根据您的应用程序,我将避免在回调内部进行任何实际工作。取而代之的是,我只设置一个主线程/循环可以处理的标志,或者将事件添加到由主线程/循环处理的队列中。
答案 2 :(得分:0)
我意识到对于这个特定的应用程序而言,中断并不是走好的路。取而代之的是,我重新编写了代码,以便仅在主循环空闲并等待时才按下按钮……这当然是大多数时间。感谢您的输入!