Home>

I am writing a simple application for working with SerialPort. In Qt Desinger made a window for choosing a port and a connection, the received data is written to the VScode terminal. I use "Virtual Serial Ports Emulator" for testing. When two terminals "Terminal v1.9b" are connected between each other, the data is sent correctly, if I use "Terminal v1.9b" in conjunction with my program, then the received data from the terminal is beaten into three lines each time of different length. When using the "Termite" terminal, the data /line is received by my program correctly. I also tried to receive data from the microcontroller through uart, a line (array) of the following type comes from it: "uf000F000t" without a carriage return and the beginning of a new line, in Terminal v1.9b the data is taken as one long line as intended (uf000F000tuf000F000tuf000F000tuf000F000t, etc.) , and in my program, each character is on a new line. Actually the question is why the line beats by three, and when sending from the microcontroller, each character is from a new line?

Code:

from PyQt5 import QtWidgets, uic
from threading import *
from PyQt5.QtSerialPort import QSerialPort, QSerialPortInfo
from PyQt5.QtCore import QIODevice
app= QtWidgets.QApplication ([])
ui= uic.loadUi ("MainWindow.ui")
ui.closePortBut.setEnabled (False)
serial= QSerialPort ()
serial.setBaudRate (9600)
# update the port list
def updateList ():
    portList= []
    ports= QSerialPortInfo (). availablePorts ()
    for port in ports: portList.append (port.portName ())
    ui.comBox.clear ()
    ui.comBox.addItems (portList)
# open serial port
def onOpen ():
    serial.setPortName (ui.comBox.currentText ())
    serial.open (QIODevice.ReadWrite)
    if serial.OpenMode:
        print ("openPort")
        ui.openPortBut.setEnabled (False)
        ui.closePortBut.setEnabled (True)
# close the port
def onClose ():
    serial.close ()
    print ("closePort")
    ui.openPortBut.setEnabled (True)
    ui.closePortBut.setEnabled (False)
# read port
def onRead ():
    rx= serial.readLine ()
    rxStrnig= str (rx, "utf-8")
    print (rxStrnig)
serial.readyRead.connect (onRead)
ui.openPortBut.clicked.connect (onOpen)
ui.closePortBut.clicked.connect (onClose)
updateList ()
ui.show ()
app.exec () 
  • Answer # 1

    It's simple -in a multitasking OS (no matter which one), data is buffered -what the program writes to the port first goes to the I /O buffer, and then the serial port driver slowly sends it to the device.

    The opposite is also true -what is sent by the device, the driver adds to the buffer, after which the buffer is flushed to the application.

    The presence of a buffer is due, in particular, to the presence of multitasking -an application transmitting data at the moment can be supplanted by the CPU scheduler, and the data must be put somewhere.

    Network protocols, such as TCP, work in a similar way.

    For your application to work correctly, you need your own communication protocol, which works via UART.

    Specifically, you need:

    1. Correctly synchronize the device and the computer, because it may happen that the device worked-worked, and then it was connected to the PC -and you started receiving messages from the middle.

    2. Provide indication of the beginning and end of the message.

    Both of these tasks are accomplished by, for example, using the end-of-message marker -for example, the byte sequence 0x0D0A ("\ r \ n"). It is clear that inside the message, you will either have to escape these bytes (for example"\\ r \\ n", or never use.

    I added a line integrity check to the onRead () function via canReadLine () and add \ n (0A) to the end of the line -it works, but what if I want to use my own characters for the beginning and end of the line?

    Mastech2021-09-25 11:16:44

    @Mastech -obviously, in this case, you will have to write your own canReadLine (), which will work with your line ends, but it will look strange -there are standard symbols, everyone works with them -you want variety.

    gbg2021-09-25 11:38:07
  • Answer # 2

    It's simple -in a multitasking OS (no matter which one), data is buffered -what the program writes to the port first goes to the I /O buffer, and then the serial port driver slowly sends it to the device.

    The opposite is also true -what is sent by the device, the driver adds to the buffer, after which the buffer is flushed to the application.

    The presence of a buffer is due, in particular, to the presence of multitasking -an application transmitting data at the moment can be supplanted by the CPU scheduler, and the data must be put somewhere.

    Network protocols, such as TCP, work in a similar way.

    For your application to work correctly, you need your own communication protocol, which works via UART.

    Specifically, you need:

    1. Correctly synchronize the device and the computer, because it may happen that the device worked-worked, and then it was connected to the PC -and you started receiving messages from the middle.

    2. Provide indication of the beginning and end of the message.

    Both of these tasks are accomplished by, for example, using the end-of-message marker -for example, the byte sequence 0x0D0A ("\ r \ n"). It is clear that inside the message, you will either have to escape these bytes (for example"\\ r \\ n", or never use.

    I added a line integrity check to the onRead () function via canReadLine () and add \ n (0A) to the end of the line -it works, but what if I want to use my own characters for the beginning and end of the line?

    Mastech2021-09-25 11:16:44

    @Mastech -obviously, in this case, you will have to write your own canReadLine (), which will work with your line ends, but it will look strange -there are standard symbols, everyone works with them -you want variety.

    gbg2021-09-25 11:38:07