[英]With Python, how to prevent two threads from writing simultaneously to display
我正在一個Raspberry Pi項目中,在這里我有一個OLED顯示器,它在True-loop時不斷地用Python中的信息進行更新。 但是,每當我按下按鈕(GPIO 5)時,只要按下按鈕,或者可能在預定的時間段內,我都希望顯示一些其他靜態信息(例如,系統信息)。 釋放按鈕后,“主循環”可能會再次接管。 我試圖使用RPi.GPIO和回調函數來實現此功能以顯示系統信息,但是問題是,即使在執行回調函數期間,主循環仍會繼續寫入OLED,如果按下GPIO 5:兩個“線程”都同時寫入OLED ...
我假設我需要一種在回調函數期間暫停主循環執行的方法,並且我已經嘗試過信號量和獲取/釋放,但是沒有運氣。 我還考慮了將兩個回調函數與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
我正在使用全局varialbe-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
嘗試讓我知道。
根據您的應用程序,我將避免在回調內部進行任何實際工作。 相反,我只設置一個主線程/循環可以處理的標志或將事件添加到由主線程/循環處理的隊列中。
我意識到,對於該特定應用程序而言,中斷並不是走好的路。 取而代之的是,我重新編寫了代碼,以便僅在主循環空閑並等待時才按下按鈕……這當然是大多數時間。 感謝您的輸入!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.