ValueError: could not convert string to float: when using matplotlib, arduino and pyqt5

筅森魡賤 提交于 2021-01-29 14:02:21

问题


While using an arduino code (also connecting pin 13 to A0 in an arduino uno) to have changing values

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);
}

And then trying to read the code with python using,

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_())

If I set the delays in the arduino code to delay(1) then I don't see any error (at least, not for as long as I've tried waiting, about 20 minutes), and values that show up in the plot and window are 0 or 255. But with the delay at 1000, I get errors like,


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'

or with the ending like

ValueError: could not convert string to float: '255\r0'

with the value showing up in the window being digits that may be like 255 or 0 or nothing, or parts of them (the digits used, not numbers in between). So when the arduino is running fast, there are no errors, but when it's slow, there are. I'm trying to get multiple things running at once, pyqt5 with arduino and matplotlib. I've gotten all of these to run separately together (like pyqt5 and arduino, matplotlib and arduino, arduino and pyqt5), there are no errors if I just run pyqt5 with arduino, printing out values. Any ideas on what could be causing the error would be helpful, thanks.


回答1:


Do not use pyserial but QSerialPort since it offers the advantage of notifying if there is data or not through signals and thus you will avoid using timers or 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_())


来源:https://stackoverflow.com/questions/63360947/valueerror-could-not-convert-string-to-float-when-using-matplotlib-arduino-an

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!