میتونید بجای pyserial از
QSerialPort استفاده کنید (برای مثال
این پاسخ رو ببینید).
وقتی یک بایت از درگاه سریال دریافت شد، سیگنال readyRead صدا زده میشه و بدون استفاده از حلقه بایتهای دریافتی در دسترس هست.
به عنوان یک پروتکل ساده، میشه خروجی حسگرها رو در میکروکنترلر به شکل یک رشته درآورد که دادههای مختلف با کاما جدا شده:
22.51,10.0\n
مثلا عدد اول دما و دومی رطوبت هست. کاراکتر n\ هم انتهای پیام رو مشخص میکنه.
در پایتون وقتی کاراکتر n\ رسید یعنی یک پیام کامل دریافت شد، بنابراین کد زیر اجرا میشه و متن پیام در متغیر text و دادهها بصورت عدد اعشاری در آرایه data قرار میگیره:
text = self.serial.readLine().data().decode().rstrip()
data = [float(x) for x in text.split(',')]
نمونه برنامه کامل، تصویرش رو پیوست کردم:
import sys
from PyQt5.QtWidgets import QMainWindow, QApplication, QComboBox, QPushButton, QVBoxLayout, QWidget, QTextEdit, QLabel
from PyQt5.QtSerialPort import QSerialPort, QSerialPortInfo
from PyQt5.QtCore import QIODevice
class Window(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle('Serial Port')
self.statusBar().showMessage('Ready')
layout = QVBoxLayout()
widget = QWidget()
widget.setLayout(layout)
self.textView = QTextEdit(readOnly=True)
layout.addWidget(self.textView)
self.temperatureLabel = QLabel('Temperature: no data')
layout.addWidget(self.temperatureLabel)
self.humidityLabel = QLabel('Humidity: no data')
layout.addWidget(self.humidityLabel)
self.portCombo = QComboBox()
ports = QSerialPortInfo.availablePorts()
self.portCombo.addItems([port.portName() for port in ports])
layout.addWidget(self.portCombo)
self.connectButton = QPushButton('Connect')
layout.addWidget(self.connectButton)
self.connectButton.clicked.connect(self.connectSerial)
self.serial = QSerialPort(self)
self.serial.readyRead.connect(self.readData)
self.setCentralWidget(widget)
self.show()
def connectSerial(self):
if not self.serial.isOpen():
portName = self.portCombo.currentText()
self.serial.setPortName(portName)
successful = self.serial.open(QIODevice.ReadWrite)
if successful:
self.statusBar().showMessage('Port opened.')
self.connectButton.setText('Disconnect')
else:
self.statusBar().showMessage('Port was not opened.')
else:
self.serial.close()
self.statusBar().showMessage('Port closed.')
self.connectButton.setText('Connect')
def readData(self):
while self.serial.canReadLine():
self.statusBar().showMessage('Data received.')
text = self.serial.readLine().data().decode().rstrip()
self.textView.append(text)
data = [float(x) for x in text.split(',')]
self.temperatureLabel.setText('Temperature: {}'.format(data[0]))
self.humidityLabel.setText('Humidity: {}'.format(data[1]))
if __name__=="__main__":
app = QApplication(sys.argv)
win = Window()
sys.exit(app.exec_())
توی این کد، خط self.serial.readyRead.connect(self.readData) سیگنال readyRead رو به تابع readData متصل میکنه و با دریافت هر بایت این تابع اجرا میشه.
در داخل تابع با چک کردن ()self.serial.canReadLine میشه فهمید که یک پیام کامل دریافت شده.