python - ValueError:无法将字符串转换为浮点数:使用 matplotlib、arduino 和 pyqt5 时
问题描述
在使用 arduino 代码时(也在 arduino uno 中将引脚 13 连接到 A0)来改变值
int PinOutput = 13;
int PinInput = A0;
int inph;
int inpl;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
pinMode(PinInput, INPUT);
pinMode(PinOutput, OUTPUT);
}
void loop() {
// put your main code here, to run repeatedly:
inpl = analogRead(PinInput)/4;
Serial.println(inpl);
analogWrite(PinOutput,255);
delay(1000);
inph = analogRead(PinInput)/4;
Serial.println(inph);
analogWrite(PinOutput,0);
delay(1000);
}
然后尝试使用 python 读取代码,
from PyQt5 import QtCore, QtGui, QtWidgets
import serial
import time
import sys
import random
from matplotlib.figure import Figure
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg
import matplotlib
matplotlib.use('Qt5Agg')
ser = serial.Serial('COM3', baudrate = 9600, timeout = 1)
time.sleep(3)
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(325, 237)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.label = QtWidgets.QLabel(self.centralwidget)
self.label.setGeometry(QtCore.QRect(110, 20, 61, 16))
self.label.setObjectName("label")
self.textEdit = QtWidgets.QTextEdit(self.centralwidget)
self.textEdit.setGeometry(QtCore.QRect(90, 60, 104, 71))
self.textEdit.setObjectName("textEdit")
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setGeometry(QtCore.QRect(100, 150, 75, 23))
self.pushButton.setObjectName("pushButton")
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 325, 21))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "test window"))
self.label.setText(_translate("MainWindow", "pyqt5 tests"))
self.pushButton.setText(_translate("MainWindow", "test button"))
self.pushButton.clicked.connect(self.label_change)
self.thread_start = MyThread()
self.thread_start.ard_signal.connect(self.label.setText)
self.thread_start.start()
def label_change(self):
self.pushButton.setText('Button Clicked!')
self.textEdit.setText('taco')
class MainWindowm(QtWidgets.QMainWindow):
def __init__(self, *args, **kwargs):
super(MainWindowm, self).__init__(*args, **kwargs)
self.canvas = MplCanvas(self, width=5, height=4, dpi=100)
self.setCentralWidget(self.canvas)
n_data = 50
self.xdata = list(range(n_data))
self.ydata = [random.randint(0, 10) for i in range(n_data)]
self._plot_ref = None
self.update_plot()
self.show()
self.timer = QtCore.QTimer()
self.timer.setInterval(1000)
self.timer.timeout.connect(self.update_plot)
self.timer.start()
def update_plot(self):
time.sleep(1)
self.ydata = self.ydata[1:] + [float(ser.readline().decode().split('\r\n')[0].strip())]
self.canvas.axes.cla()
self.canvas.axes.plot(self.xdata, self.ydata, 'r')
self.canvas.draw()
class MyThread(QtCore.QThread):
ard_signal = QtCore.pyqtSignal(str)
def __init__(self):
QtCore.QThread.__init__(self)
def run(self):
counter = 0
while 1:
time.sleep(1)
self.ard_signal.emit(str(ser.readline().decode().split('\r\n')[0]))
counter += 1
sys.exit()
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
w = MainWindowm()
sys.exit(app.exec_())
如果我将 arduino 代码中的延迟设置为,delay(1)
那么我看不到任何错误(至少,只要我尝试等待大约 20 分钟,就不会看到任何错误),并且显示在绘图和窗口中的值为 0或 255。但是由于延迟为 1000,我得到了类似的错误,
Traceback (most recent call last):
File "C:\Documents\ardmatlibpyqt5.py", line 141, in update_plot
self.ydata = self.ydata[1:] + [float(ser.readline().decode().split('\r\n')[0].strip())]
ValueError: could not convert string to float: '25\r0'
或以类似的结尾
ValueError: could not convert string to float: '255\r0'
窗口中显示的值可能是 255 或 0 或什么都没有的数字,或者它们的一部分(使用的数字,而不是介于两者之间的数字)。因此,当 arduino 运行速度快时,没有错误,但是当它运行缓慢时,就会出现错误。我试图让多个东西同时运行,pyqt5 与 arduino 和 matplotlib。我已经让所有这些单独运行(如 pyqt5 和 arduino、matplotlib 和 arduino、arduino 和 pyqt5),如果我只用 arduino 运行 pyqt5 并打印出值,则没有错误。任何可能导致错误的想法都会有所帮助,谢谢。
解决方案
不要使用 pyserial 而是使用 QSerialPort,因为它提供了通过信号通知是否有数据的优势,因此您将避免使用计时器或 time.sleep()。
import random
import sys
from PyQt5 import QtCore, QtGui, QtWidgets, QtSerialPort
from matplotlib.figure import Figure
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg
class MainWindowm(QtWidgets.QMainWindow):
def __init__(self, *args, **kwargs):
super(MainWindowm, self).__init__(*args, **kwargs)
self.canvas = FigureCanvasQTAgg(Figure(figsize=(5, 4), dpi=100))
self.setCentralWidget(self.canvas)
self.axes = self.canvas.figure.subplots()
n_data = 50
self.xdata = list(range(n_data))
self.ydata = [random.randint(0, 10) for i in range(n_data)]
self.serial_port = QtSerialPort.QSerialPort("COM3")
self.serial_port.setBaudRate(QtSerialPort.QSerialPort.Baud9600)
self.serial_port.errorOccurred.connect(self.handle_error)
self.serial_port.readyRead.connect(self.handle_ready_read)
self.serial_port.open(QtCore.QIODevice.ReadWrite)
def handle_ready_read(self):
while self.serial_port.canReadLine():
codec = QtCore.QTextCodec.codecForName("UTF-8")
line = codec.toUnicode(self.serial_port.readLine()).strip().strip('\x00')
try:
print(line)
value = float(line)
except ValueError as e:
print("error", e)
else:
self.update_plot(value)
def handle_error(self, error):
if error == QtSerialPort.QSerialPort.NoError:
return
print(error, self.serial_port.errorString())
def update_plot(self, value):
self.ydata = self.ydata[1:] + [value]
self.axes.cla()
self.axes.plot(self.xdata, self.ydata, "r")
self.canvas.draw()
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
w = MainWindowm()
w.show()
sys.exit(app.exec_())
推荐阅读
- javascript - 仅当一个按钮时才使用动态按钮文本填充按钮数组
- python - 使用日志在 python 中创建不同的日志文件
- google-apps-script - 为时间触发器添加 Null 选项以避免“....未能成功完成”错误报告
- flutter - 如何将小部件放置在表单小部件的底部?
- vue.js - 灯塔指标差异
- python - 查找列表中字符串第一次出现的位置
- sql - 如何将signle qute添加到awk打印/从bash脚本中插入SQL AWK从bash脚本中打印单引号SQL插入
- python - 如何从图像列表(表格)中打开 Flask APP 中的图像
- javascript - Discord.js 删除触发消息
- c++ - 使用 C++ 作为 VueJs/Electron 应用程序的后端