SoFunction
Updated on 2024-11-17

Serial port debugging assistant using python+Pyqt5

python can utilize the serial module to communicate with serial devices for 485 or 232.

在这里插入图片描述

Of course, there are many small programs of this type of serial port debugging assistant on the Internet, but these programs either charge a fee and can only be tried for 30 days, or they don't work well.

Besides, you can only use a program written by someone else, you can't take out the data in it to process it, so if you can write your own program, it's easy to use and you can use the data in it whenever you want.

Software: python 3.10
pycharm2021
Hardware: window10 computer
Serial 485 equipment (domestic flow meters)
Serial to usb cable (computer does not come with serial port, only adapter)

串口转usb线

流量计带485通讯

When you are ready, you can start writing the program.

The serial communication program starts by setting up the serial port, such as baud rate, data bits, stop bits, parity bits, and so on. It can be called initialization:

Initialization:

def serial_init(self):   # Initialization

         = self.port_set.currentText()
         = int(self.baud_set.currentText())
         = float(self.timeout_set.text())
        try:
             = (port=,baudrate=,bytesize=8,parity='N',stopbits=1)
            print()
            if .is_open:
                print('Serial port normal')
        except Exception as e:
            (self, 'tips!', str(e),  | , )
            print('Exception:', e)

After initialization, the serial port needs to be opened, and only if the serial port is successfully opened can the later data transfer take place. the serial module in python is provided to do the checking. Of course, it should be noted that when serial is instantiated, the serial port is actually opened at the same time. So, if the instantiation is created in the initialization program:

  = (port=,baudrate=,bytesize=8,parity='N',stopbits=1)

Then it is also possible to open the serial port without having to repeat the process.

The serial port is open:

def open_serial(self):   # Open the serial port
        try:
            ()
        except Exception as e:
            (self, 'tips!', str(e),  | , )
            print('Exception:', e)

The serial port is closed:

 def close_serial(self):  # Close the serial port
        try:
            ()

        except Exception as e:
            (self,'tips!',str(e),|,)
            print('Exception:', e)

When debugging is complete, it is best to close the serial port and have a start and finish.

After completing the initialization and opening steps above, it is possible to read and write data. In this example, communication with the flowmeter is used to read the real-time flow of the flowmeter. The flowmeter reads and writes data in a specialized format:

在这里插入图片描述

Therefore, when sending commands from the computer side, you need to send them in the format of the flow meter to get the correct feedback. 485 is a half-duplex transmission, that is, you can only read or write at the same time, and reading and writing cannot be done at the same time.

In this example, the read flow command format is:
01 03 00 10 00 02 C5 CE
In practice, I changed the address of the meter device to 2, i.e.
02 03 00 10 00 02 C5 CE

Send data:

def send_data(self):
        ct = ()                       # Get the current system time
        ct_str = ("%Y-%m-%d %H:%M:%S")          # Format the current system time (in character form)
        try:
            self.senddata_s=self.le_senddata.text()
            =(self.senddata_s)  # Characters to bytes
            ()
            #self.senddata_str=()
            self.senddata_str_fg=self.str_fenge(self.senddata_s)
            #self.le_senddata.setText(())
            self.le_recdata.append('\n' + '[' + ct_str+ ']' + ' ' + self.senddata_str_fg + '\n')
            #print()
            (0.1)
            self.read_data_size()
        except Exception as e:
            (self, 'tips!', str(e),  | , )

Read data:

 def read_data_size(self):
        ct=()
        ct_str=("%Y-%m-%d %H:%M:%S")
        try:
            #=10
            self.read_data=.read_all()
            #print(self.read_data)
            self.read_data_str=self.read_data.hex()   # Byte to hexadecimal character display
            #(r'.{3}',self.read_data_str)
            self.read_data_str_fg=self.str_fenge(self.read_data_str)
            #print(self.read_data_str)
            self.le_recdata.append('\n'+'['+ct_str+']'+' '+self.read_data_str_fg+'\n')
        except Exception as e:
            (self, 'tips!', str(e),  | , )
        #return self.read_data

Serial read data, there are several ways, read (), read_all (), readline (), read () is in accordance with the byte size size read cache bytes, read_all () that is, read all the data, readline () read the latest line of data in the cache.

Complete program:

from .function_base import place
import serial
import .list_ports
import sys
import re
import os
import time
import datetime
import threading
from  import *
from  import *
from  import *
class Serialwindow(QWidget):
    def __init__(self) -> None:
        super().__init__()
        ()
    def initUI(self):
        # = 'E:\\\100proworld2021\opencvtestpro01\crawler program\crawler-'
        # = ()
         = ''
         = 0
         = 0.0
        =bytes()
        self.read_data=''
        
        self.btn_plist=QPushButton('Get available serial ports',self)
        self.btn_plist.setGeometry(20,20,60,20)
        self.btn_plist.(self.get_serial_info)
        self.btn_plist.adjustSize()
        
        self.btn_ser_init=QPushButton('Initialization',self)
        self.btn_ser_init.setGeometry(20,50,60,20)
        self.btn_ser_init.(self.serial_init)
        self.btn_ser_init.adjustSize()
        self.btn_open=QPushButton('Open serial port',self)
        self.btn_open.setGeometry(20,80,60,20)
        self.btn_open.(self.open_serial)
        self.btn_open.adjustSize()
        self.btn_close=QPushButton('Close serial port',self)
        self.btn_close.setGeometry(20,110,60,20)
        self.btn_close.(self.close_serial)
        self.btn_close.adjustSize()
        self.btn_read_data=QPushButton('Read data',self)
        self.btn_read_data.setGeometry(20,140,60,20)
        self.btn_read_data.(self.read_data_size)
        self.btn_read_data.adjustSize()
        self.btn_write_data=QPushButton('Send data',self)
        self.btn_write_data.setGeometry(40,460,60,20)
        self.btn_write_data.(self.send_data)
        self.btn_write_data.adjustSize()
        #Qcombobox
        self.port_set=QComboBox(self)
        self.port_set.setGeometry(500,20,100,20)
        self.port_set.addItems(['COM1'])
        #self.port_set.()
        self.lbl_port_set=QLabel(self)
        self.lbl_port_set.setGeometry(420,20,60,20)
        self.lbl_port_set.setText('Serial number:')
        self.baud_set=QComboBox(self)
        self.baud_set.setGeometry(500,50,100,20)
        self.baud_set.addItems(['9600','19200','38400','115200'])
        self.lbl_baud_set=QLabel(self)
        self.lbl_baud_set.setGeometry(420,50,60,20)
        self.lbl_baud_set.setText('Baud rate:')
        self.stopbit_set=QComboBox(self)
        self.stopbit_set.setGeometry(500,80,100,20)
        self.stopbit_set.addItems(['0','1'])
        self.lbl_stopbit_set = QLabel(self)
        self.lbl_stopbit_set.setGeometry(420, 80, 60, 20)
        self.lbl_stopbit_set.setText('Stop bit:')
        self.parity_set=QComboBox(self)
        self.parity_set.setGeometry(500,110,100,20)
        self.parity_set.addItems(['None','odd calibration','Even checking'])
        self.lbl_parity_set = QLabel(self)
        self.lbl_parity_set.setGeometry(420, 110, 60, 20)
        self.lbl_parity_set.setText('Check digit:')
        self.databit_set=QComboBox(self)
        self.databit_set.setGeometry(500,140,100,20)
        self.databit_set.addItems(['8','7'])
        self.lbl_databit_set=QLabel(self)
        self.lbl_databit_set.setGeometry(420,140,60,20)
        self.lbl_databit_set.setText('Data bits:')
        self.timeout_set=QLineEdit(self)
        self.timeout_set.setGeometry(500,170,100,20)
        self.timeout_set.setText('1000')
        self.lbl_timeout_set=QLabel(self)
        self.lbl_timeout_set.setGeometry(420,170,60,20)
        self.lbl_timeout_set.setText('Timeout setting:')
        self.lbl_timeout_set_2=QLabel(self)
        self.lbl_timeout_set_2.setGeometry(610,170,60,20)
        self.lbl_timeout_set_2.setText('ms')
        #
        self.le_senddata=QLineEdit(self)
        self.le_senddata.setGeometry(120,460,300,20)
        self.le_senddata.setText('010300100002C5CE')
        self.le_recdata=QTextEdit(self)
        self.le_recdata.setGeometry(120,220,600,200)
        (100,100,800,600)
        ('Simple Serial Debugging Assistant - Bacterial Dust')
       # ()
        ()
    def Qcombo(self):
        print(self.port_set.currentText())
        print(self.baud_set.currentText())
        print(self.stopbit_set.currentText())
        print(self.parity_set.currentText())
        print(self.databit_set.currentText())
        print(self.timeout_set.text())
    def get_serial_info(self):   # Get a list of available serial ports
        # Print the list of available serial ports
        #self.need_serial = ''
         = list(.list_ports.comports())
        if len() <= 0:
            print('Serial port not found')
            qm = (self, 'Tip Window', 'Serial port not found! Please check wiring and computer interface.', |,)
            if qm == :
                print('Yes')
            else:
                print('No')
        else:
            for i in list():
                self.port_set.addItem()
        #return self.need_serial
        #print()
    def serial_init(self):   # Initialization
         = self.port_set.currentText()
         = int(self.baud_set.currentText())
         = float(self.timeout_set.text())
        try:
             = (port=,baudrate=,bytesize=8,parity='N',stopbits=1)
            print()
            if .is_open:
                print('Serial port normal')
        except Exception as e:
            (self, 'tips!', str(e),  | , )
            print('Exception:', e)
    def open_serial(self):   # Open the serial port
        try:
            ()
        except Exception as e:
            (self, 'tips!', str(e),  | , )
            print('Exception:', e)
    def close_serial(self):  # Close the serial port
        try:
            ()
        except Exception as e:
            (self,'tips!',str(e),|,)
            print('Exception:', e)
    def read_data_size(self):
        ct=()
        ct_str=("%Y-%m-%d %H:%M:%S")
        try:
            #=10
            self.read_data=.read_all()
            #print(self.read_data)
            self.read_data_str=self.read_data.hex()   # Byte to hexadecimal character display
            #(r'.{3}',self.read_data_str)
            self.read_data_str_fg=self.str_fenge(self.read_data_str)
            #print(self.read_data_str)
            self.le_recdata.append('\n'+'['+ct_str+']'+' '+self.read_data_str_fg+'\n')
        except Exception as e:
            (self, 'tips!', str(e),  | , )
        #return self.read_data
    def read_data_line(self):
        self.read_data=()
        return self.read_data
    def send_data(self):
        ct = ()                       # Get the current system time
        ct_str = ("%Y-%m-%d %H:%M:%S")          # Format the current system time (in character form)
        try:
            self.senddata_s=self.le_senddata.text()
            =(self.senddata_s)  # Characters to bytes
            ()
            #self.senddata_str=()
            self.senddata_str_fg=self.str_fenge(self.senddata_s)
            #self.le_senddata.setText(())
            self.le_recdata.append('\n' + '[' + ct_str+ ']' + ' ' + self.senddata_str_fg + '\n')
            #print()
            (0.1)
            self.read_data_size()
        except Exception as e:
            (self, 'tips!', str(e),  | , )
    def read_data_alway(self, way):
        print('Starting to receive data:')
        while True:
            try:
                if :
                    if(way == 0 ):
                        for i in range():
                            print('Receive ascII data:'+str(self.read_data_size(1)))
                            data1 = self.read_data_size(1).hex()
                            data2 = int(data1, 16)
                            print('Received hexadecimal data:'+data1+'Received decimal data:'+str(data2))
                    if(way == 1 ):
                        data = .read_all()
            except Exception as e:
                print('Exception:', e)
    def str_fenge(self,A):
        '''
        Split the string by length and add other characters in between, such as spaces, dash, etc.
        '''
        b = (r'.{2}',A)
        c = ' '.join(b)
        #print(c)
        return c
if __name__ == '__main__':
    app = QApplication()
    ex = Serialwindow()
    (app.exec_())

The above program has been tested and can communicate properly with the flow meter.

to this article on the use of python Pyqt5 serial port debugging assistant to this article, more related python Pyqt5 serial port debugging assistant content, please search for my previous posts or continue to browse the following related articles I hope you will support me in the future!