首页 > 解决方案 > 如何在 python dash 应用程序中绘制来自传感器的串行信号?

问题描述

我正在尝试从 arduino uno 读取模拟输入,并在破折号 GUI 中不断显示新输入。使用 pyserial 包从 arduino 读取 USB 串行信号非常简单。

但是,我还不能在 Dash 中实现读数。

到目前为止,我得到的是这段代码,其中每 1000 毫秒触发一次间隔事件,并将生成的数据添加到绘图中(更新):

import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import os
import plotly.graph_objects as go
import serial
import time, datetime


os.system("start \"\" http://127.0.0.1:8050/") # necessary since dash does not automatically open browser

# readout function for analog signal reading
def readAO():
    ser = serial.Serial('COM3', baudrate=9600, timeout=10)
    dat = ser.readline().decode('ascii')
    ser.close()
    return dat

# arrays for saving data points
X = [0]
Y = [0]

# GUI layout/design
app = dash.Dash()
app.layout = html.Div(
    children=[
        html.H1('Datenauswertung '),
        dcc.Graph(id='live-graph'),
        dcc.Interval(id='update_graph', interval=1000),
        html.Button(id='textout', children='text')
    ]
)

# update part where data is read and the plot and data arrays are updated
@app.callback(Output('live-graph', 'figure'),
              [Input('update_graph', 'n_intervals')])
def update(i_input):
    
    # this is where the Error happens
    dat = readAO()

    if(dat > 100 | dat < 600):
        Y.append(float(1))
        X.append(datetime.datetime.now().strftime('%H:%M:%S'))
    
    if len(X) > 50:
        del(X[0])
        del(Y[0])
    
    plot = go.Figure(go.Scatter(x=X, y=Y, mode='markers+lines'))
    return plot     
     
if __name__ == '__main__':
    app.run_server()

我得到的是这个错误:

serial.serialutil.SerialException: could not open port 'COM3': PermissionError(13, 'Permission denied', None, 5)

我不明白。我是 PC 的唯一用户,因此授予管理员权限。以下也执行得很好:

while(True):
    ser = serial.Serial('COM3', baudrate=9600, timeout=10)
    dat = ser.readline().decode('ascii')
    print(dat)
    ser.close()

让我恼火的一件事是,当我在 while 循环中执行代码时,有时会得到错误的结果(没有错误)。

这可能是串行连接配置的问题,即超时设置不匹配或类似情况?

感谢大家的帮助和见解!

编辑:好的,我进一步本地化了问题。似乎 readline() 时不时地会出错,因此将串行读取封装在 try except 中会捕获到这一点。Dash 和 pyserial 似乎也不能很好地协同工作。我坚持的是 readline() 或多或少地不断输出相同的值

标签: pythonserializationpyserialplotly-dash

解决方案


由于我特别不熟悉 Dash,因此很难准确诊断出这里出了什么问题。但是,我在 Python 和 Arduinos 方面的其他经验提出了一些故障排除建议,按照我建议尝试的顺序:

  1. 尝试拔下和插入您的 Arduino,并关闭其他可能试图使用 COM 端口的程序。通常(总是?)一次只有一个程序可以打开给定的 COM 端口。第二个程序将得到一个权限被拒绝的错误。
  2. 尝试在回调函数之外初始化串行端口。即,在脚本的早期打开 com 端口,将其“ser”对象作为全局变量。
  3. 也许 Dash 窗口不会自动获得管理员权限。尝试以管理员身份显式运行 Python 提示符。(当您尝试打开命令行、终端、Python IDE 或您正在使用的任何东西时,通过右键单击应用程序图标。)

您猜测波特率或超时设置通常可能是一个问题是正确的,但是您的两个示例代码中的串行初始化行是相同的,所以我怀疑这是这里的问题。


推荐阅读