ValueError:无法将字符串转换为浮点数:使用 matplotlib、arduino 和 pyqt5 时
Posted
技术标签:
【中文标题】ValueError:无法将字符串转换为浮点数:使用 matplotlib、arduino 和 pyqt5 时【英文标题】:ValueError: could not convert string to float: when using matplotlib, arduino and pyqt5 【发布时间】:2020-12-01 06:47:18 【问题描述】:在使用 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'
或以like结尾
ValueError: could not convert string to float: '255\r0'
窗口中显示的值可能是 255 或 0 或什么都没有的数字,或者它们的一部分(使用的数字,而不是介于两者之间的数字)。因此,当 arduino 运行速度快时,没有错误,但是当它运行缓慢时,就会出现错误。我试图让多个东西同时运行,pyqt5 与 arduino 和 matplotlib。我已经让所有这些单独运行(如 pyqt5 和 arduino、matplotlib 和 arduino、arduino 和 pyqt5),如果我只用 arduino 运行 pyqt5 并打印出值,则没有错误。关于可能导致错误的任何想法都会有所帮助,谢谢。
【问题讨论】:
【参考方案1】:不要使用 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_())
【讨论】:
太棒了。这通常有效,但有时我运行它并收到一条消息2 Access is denied.
,它打印出的 0 和 255 似乎比 arduino 灯闪烁的速度更快,并且情节上没有任何显示。另一次我收到一条消息9 The device does not recognize the command.
,但随后它开始工作,但在开始附近出现错误,例如error could not convert string to float: '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00255'
,但有更多\x00
或者我在开始时收到错误0 error could not convert string to float: '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x000'
,但之后似乎运行良好
@dsfgh 再试一次
酷,是的,只删除 \x00 是有意义的。有 Qt 版本的东西很好。有时我仍然会收到一条消息2 Access is denied.
,但我认为这是我在使用 Arduino 时遇到的一个普遍问题,我必须拔下并重新插入 arduino,再次运行 arduino 代码,以便 python 代码工作。就像当我尝试重新运行我的原始代码时,我每次都会收到错误 SerialException: could not open port 'COM3': PermissionError(13, 'Access is denied.', None, 5)
。至少对于您的代码,它有时可以重新运行,也许如果等待足够长的时间。
@dsfgh 这些是硬件问题,如果同样的问题出现在 Qt 和 pyserial 中,请检查您的 arduino 的电源,不要使用串行连接器作为电源,很多次我都有这种类型的问题,因为输出引脚消耗大量电流,不足以进行串行通信。此外,请勿将电机(或产生大量噪音的系统)放置在您的设备附近。以上是关于ValueError:无法将字符串转换为浮点数:使用 matplotlib、arduino 和 pyqt5 时的主要内容,如果未能解决你的问题,请参考以下文章
ValueError:无法将字符串转换为浮点数:'2100 - 2850'
ValueError:无法将字符串转换为浮点数:'62,6'
ValueError:无法将字符串转换为浮点数:''20,99''