Python 3.11树莓派4激光计数器程序无法显示计数问题
问题分析与修复方案
核心问题
- Pygame事件循环缺失:未处理Pygame事件队列,导致窗口无法响应系统事件,出现黑屏无更新的情况。
- 渲染逻辑位置错误:显示更新代码嵌套在GPIO信号检测的else分支中,仅在特定GPIO状态下才可能执行,60秒定时更新逻辑无法正常触发。
- TimeE计算时机错误:时间差判断使用的是陈旧的TimeE值,导致计数逻辑可能不准确。
- 重复初始化Pygame:代码中两次调用
pygame.init(),属于冗余操作。
修复后的代码
import RPi.GPIO as GPIO import time import pygame import sys from pygame.locals import * # 初始化Pygame(仅调用一次) pygame.init() # 显示器参数 display_width = 1060 display_height = 700 sizefont = int((display_width + display_height) / 4.25) # 颜色定义 black = (0, 0, 0) blue = (0, 0, 255) # 创建显示窗口 gameDisplay = pygame.display.set_mode((display_width, display_height), pygame.RESIZABLE) pygame.display.set_caption('Laser') myfont = pygame.font.SysFont("monaco", sizefont) # GPIO配置 GPIO.setmode(GPIO.BCM) LSGPIO = 18 GPIO.setup(LSGPIO, GPIO.IN) # 计数器与时间变量初始化 icount_signal = 0 xsave = 0 Time1 = time.perf_counter() Time2 = time.perf_counter() newt = time.time() + 60 if __name__ == '__main__': try: while True: # 处理Pygame事件队列,避免窗口无响应 for event in pygame.event.get(): if event.type == QUIT: GPIO.cleanup() pygame.quit() sys.exit() # 处理窗口调整大小事件 if event.type == VIDEORESIZE: display_width, display_height = event.size gameDisplay = pygame.display.set_mode((display_width, display_height), pygame.RESIZABLE) sizefont = int((display_width + display_height) / 4.25) myfont = pygame.font.SysFont("monaco", sizefont) # 激光信号检测逻辑 current_gpio_state = GPIO.input(LSGPIO) if current_gpio_state == 0: Time1 = time.perf_counter() else: Time2 = time.perf_counter() if current_gpio_state: xsave = 1 else: if xsave == 1: TimeE = Time2 - Time1 # 实时计算时间差 if TimeE > 0.5: icount_signal += 1 print(f'Detection = {icount_signal}') xsave = 0 Time1 = time.perf_counter() # 重置时间起点 # 每分钟更新显示逻辑(放在主循环外层,确保定时执行) if time.time() > newt: takt = int(icount_signal * 60) gameDisplay.fill(black) text1 = myfont.render(str(takt), True, blue) # 文本居中显示(优化) text_rect = text1.get_rect(center=(display_width//2, display_height//2)) gameDisplay.blit(text1, text_rect) pygame.display.flip() # 全屏更新更可靠 icount_signal = 0 newt = time.time() + 60 except KeyboardInterrupt: print("Measurement stopped by User") finally: GPIO.cleanup() pygame.quit() sys.exit()
关键修改点说明
- 添加Pygame事件循环:处理
QUIT和VIDEORESIZE事件,保证窗口正常响应,解决无响应黑屏问题。 - 调整渲染逻辑位置:将每分钟更新显示的代码移到主循环最外层,确保到时间就执行,不受GPIO信号状态影响。
- 修正TimeE计算时机:在激光信号从高变低时实时计算时间差,避免使用陈旧值导致计数错误。
- 移除重复初始化:删除多余的
pygame.init()调用。 - 优化显示更新:使用
pygame.display.flip()替代update(),全屏更新更稳定;添加文本居中显示的优化。 - 添加finally块:确保程序退出时一定会清理GPIO资源并关闭Pygame,避免资源泄漏。
内容的提问来源于stack exchange,提问作者Ormal85
相关产品推荐
相关产品推荐

