首页 > 解决方案 > 用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

标签: pythoncallbackinterrupt

解决方案


根据您的应用程序,我会避免在回调中做任何实际工作。相反,我只会设置一个主线程/循环可以处理的标志,或者将事件添加到由主线程/循环处理的队列中。


推荐阅读