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:无法将字符串转换为浮点数:'Mme'

ValueError:无法将字符串转换为浮点数:'62,6'

ValueError:无法将字符串转换为浮点数:''20,99''

我收到 ValueError:无法将字符串转换为浮点数:'8,900' [重复]

ValueError:无法将字符串转换为浮点数:'31,950'