python - 用Python,如何防止两个线程同时写入显示
问题描述
我正在研究一个 Raspberry Pi 项目,我有一个 OLED 显示屏,它在 Python 中不断更新信息,而 True-loop。但是,每当我按下按钮(GPIO 5)时,只要按下按钮,或者可能在预定义的时间段内,我都希望显示一些其他静态信息(例如系统信息)。当按钮被释放时,“主循环”可能会再次接管。我尝试使用 RPi.GPIO 和用于显示系统信息的回调函数来实现这一点,但问题当然是即使在回调函数执行期间,主循环也会继续写入 OLED,如果GPIO 5 被抑制:两个“线程”同时写入 OLED...
我假设我需要一种方法来在回调函数期间暂停主循环的执行,并且我已经尝试过 Semaphore 和 aquire/release 但没有运气。我还考虑过将两个回调函数与 Semaphore 结合使用的可能性,但由于主循环中显示的信息应该不断更新(例如,不是中断驱动的),我不太确定这对我来说是否是一个解决方案。
在这一点上,我什至不确定接下来要谷歌什么。也许这里有人可以启发我?这可能是做这种事情的完全错误的方式吗?(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
解决方案
根据您的应用程序,我会避免在回调中做任何实际工作。相反,我只会设置一个主线程/循环可以处理的标志,或者将事件添加到由主线程/循环处理的队列中。
推荐阅读
- tensorflow - 烧瓶服务器启动后自动加载
- binary-tree - 关于二叉搜索树的问题(如何计算followers)
- php - laravel 同步无法保存数据
- c++ - OpenGL 只是渲染一个黑色方块
- python - 如何在pygame中调整图像大小以到达屏幕的顶部/底部?
- c++ - 在 C++20 中,在一个范围内计算相邻对的最简洁明了的方法是什么?
- javascript - 如何包装发射器.on(eventName)?
- android - 如何使用 C# SDK 为 Google Assistant 创建一个简单的“播放歌曲”意图
- php - 使用电子邮件地址从 MySQL 数据库中获取行的键值
- python - 为什么非常大的斐波那契数会创建椭圆形?