基于Dash的超声波传感器计数器UI实时更新故障排查
Dash超声波计数器无实时更新问题修复
问题根源分析
- 回调未绑定定时触发源:当前回调仅监听输入框变化,未加入
interval-component的n_intervals输入,无法定时读取串口数据并更新界面。 - 串口重复初始化:每次回调都重新打开串口,易引发端口占用冲突,且资源未正确释放。
- 变量未安全初始化:
values_number可能在未匹配到传感器数据时未定义,导致运行时错误。 - 循环逻辑不符合实时需求:
for i in range(blocks)会循环指定次数,而非持续检测传感器状态。 - 返回值未使用更新后的数值:最终返回的是原始输入的
blocks,而非递减后的数值,界面自然无变化。 - 无状态存储机制:Dash回调是无状态的,每次回调都会重置计数器数值,需要用
dcc.Store保存当前剩余数量。
修正后的完整代码
import dash from dash import dcc, html, Input, Output, State import serial import re app = dash.Dash(__name__) app.title = "Companyname COUNTER" # 全局初始化串口(仅打开一次) try: ser = serial.Serial(port='COM7', baudrate=57600, timeout=1) except serial.SerialException as e: print(f"串口打开失败: {e}") ser = None app.layout = html.Div(style={'fontFamily': 'Arial, sans-serif', 'backgroundColor': '#f0f4f8', 'padding': '30px'}, children=[ html.H1("Companyname BLOCK COUNTER", style={'textAlign': 'center', 'color': '#333'}), html.Div([ html.Div([ html.Label("Type:", style={'color': '#fff'}), dcc.Input( id='input-1', type='text', value='EPS70', debounce=True, style={'width': '100%', 'padding': '10px', 'border': 'none', 'borderRadius': '5px'} ) ], style={'backgroundColor': 'blue', 'padding': '20px', 'margin': '10px', 'borderRadius': '10px', 'width': '200px'}), html.Div([ html.Label("Colour:", style={'color': '#fff'}), dcc.Input( id='input-2', type='text', value='Silver', debounce=True, style={'width': '100%', 'padding': '10px', 'border': 'none', 'borderRadius': '5px'} ) ], style={'backgroundColor': 'blue', 'padding': '20px', 'margin': '10px', 'borderRadius': '10px', 'width': '200px'}), html.Div([ html.Label("Size:", style={'color': '#fff'}), dcc.Input( id='input-3', type='text', value='0', debounce=True, style={'width': '100%', 'padding': '10px', 'border': 'none', 'borderRadius': '5px'} ) ], style={'backgroundColor': 'blue', 'padding': '20px', 'margin': '10px', 'borderRadius': '10px', 'width': '200px'}), html.Div([ html.Label("Amount:", style={'color': '#fff'}), dcc.Input( id='input-4', type='number', value=0, debounce=True, style={'width': '100%', 'padding': '10px', 'border': 'none', 'borderRadius': '5px'} ) ], style={'backgroundColor': 'blue', 'padding': '20px', 'margin': '10px', 'borderRadius': '10px', 'width': '200px'}), ], style={'display': 'flex', 'justifyContent': 'center', 'flexWrap': 'wrap'}), html.Hr(), html.Div(id='output-display', style={ 'textAlign': 'center', 'fontSize': '100px', 'marginTop': '20px', 'backgroundColor': '#ffffff', 'padding': '20px', 'borderRadius': '10px', 'boxShadow': '0 4px 8px rgba(0, 0, 0, 0.1)' }), dcc.Interval( id='interval-component', interval=1000, # 每秒触发一次检测 n_intervals=0 ), # 存储当前剩余数量的状态容器 dcc.Store(id='remaining-blocks', data=0) ]) @app.callback( [Output('output-display', 'children'), Output('remaining-blocks', 'data')], [Input('interval-component', 'n_intervals'), Input('input-4', 'value')], [State('remaining-blocks', 'data'), State('input-1', 'value'), State('input-2', 'value'), State('input-3', 'value')] ) def update_counter(n_intervals, input_blocks, remaining_blocks, name, color, category): # 当输入的总量变化时,重置剩余数量 if input_blocks is not None and input_blocks != remaining_blocks: remaining_blocks = input_blocks # 串口未连接时直接返回当前状态 if ser is None: return f"串口未连接 | Type: {name} | Colour: {color} | Size: {category} | Amount: {remaining_blocks}", remaining_blocks # 读取并解析传感器数据 value = ser.readline(8) values_number = None if value.startswith(b'R'): values_string = str(value) values_string = re.sub('[^0-9]', '', values_string) if values_string: values_number = int(values_string) # 检测到物体距离小于3500且剩余数量大于0时,递减计数 if values_number is not None and values_number < 3500 and remaining_blocks > 0: remaining_blocks -= 1 # 返回更新后的显示文本和剩余数量 return (f"Type: {name} | Colour: {color} | Size: {category} | Amount: {remaining_blocks}", remaining_blocks) if __name__ == '__main__': app.run(debug=True)
关键修改说明
- 全局初始化串口,避免重复打开引发的端口占用错误。
- 加入
dcc.Store组件保存剩余数量,解决Dash回调无状态的问题。 - 回调绑定
interval-component实现每秒自动触发检测,同时监听输入框变化以重置计数器。 - 安全解析传感器数据,避免变量未定义导致的运行时错误。
- 实时读取串口数据并判断距离,符合机器操作员的实时监控需求。
- 返回更新后的剩余数量,确保界面显示最新计数结果。
内容的提问来源于stack exchange,提问作者Shade-Swift
相关产品推荐
相关产品推荐

