问题
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