如何在 python dash 应用程序中绘制来自传感器的串行信号?

Posted

技术标签:

【中文标题】如何在 python dash 应用程序中绘制来自传感器的串行信号?【英文标题】:How to plot serial signal from a sensor in a python dash app? 【发布时间】:2020-11-15 21:25:23 【问题描述】:

我正在尝试从 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() 不断地或多或少地输出相同的值

【问题讨论】:

【参考方案1】:

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

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

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

【讨论】:

以上是关于如何在 python dash 应用程序中绘制来自传感器的串行信号?的主要内容,如果未能解决你的问题,请参考以下文章

Plotly Dash:在 Python 中绘制 networkx

使用 Plotly 生成有角度的条形图(来自 Dash 的风险分析)

如何将布局更新到 Python Dash 应用程序中

如何在 python Dash 中访问应用布局中的输入值?

即使屏幕尺寸在 Dash-plotly 中使用 python 改变,如何在导航栏中固定按钮的位置

如何在循环中绘制来自多个文件的数据