You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python 3.11树莓派4激光计数器程序无法显示计数问题

问题分析与修复方案

核心问题

  1. Pygame事件循环缺失:未处理Pygame事件队列,导致窗口无法响应系统事件,出现黑屏无更新的情况。
  2. 渲染逻辑位置错误:显示更新代码嵌套在GPIO信号检测的else分支中,仅在特定GPIO状态下才可能执行,60秒定时更新逻辑无法正常触发。
  3. TimeE计算时机错误:时间差判断使用的是陈旧的TimeE值,导致计数逻辑可能不准确。
  4. 重复初始化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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 05:07:16