Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Mobile and Embedded
  4. QSerialPort Async read - How to ensure full packet read
QtWS25 Last Chance

QSerialPort Async read - How to ensure full packet read

Scheduled Pinned Locked Moved Solved Mobile and Embedded
qt5qserialport
11 Posts 3 Posters 2.4k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • S Offline
    S Offline
    SGaist
    Lifetime Qt Champion
    wrote on 26 Mar 2021, 19:15 last edited by
    #2

    Hi and welcome to devnet,

    Do you have any protocol for the serial port data ?
    What you need is a mean to identify a full data frame. For example a frame starts with aaa sequence and ends with a zzz (whatever fits your purpose). Then on the receiver end you cumulate your serial port data in a buffer and each time your receive something, you put it in the buffer, check the buffer content for a full frame and if it's there, extract it, parse it and do whatever you want and if not, continue as usual.

    Interested in AI ? www.idiap.ch
    Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

    1 Reply Last reply
    1
    • M Offline
      M Offline
      Michal Poplawski
      wrote on 26 Mar 2021, 19:21 last edited by
      #3

      Hi!

      Nice to be here! :)

      Unfortunately there is no STX/ETX or such sequences to identify full data frame. Only packet intervals and that's the problem. I can work this out by phisically starting to listen for packets before they start being sent, but this doesn't seem to me like an elegant solution.

      1 Reply Last reply
      0
      • S Offline
        S Offline
        SGaist
        Lifetime Qt Champion
        wrote on 26 Mar 2021, 19:22 last edited by
        #4

        The device is locked ?

        Interested in AI ? www.idiap.ch
        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

        1 Reply Last reply
        0
        • M Offline
          M Offline
          Michal Poplawski
          wrote on 26 Mar 2021, 19:31 last edited by
          #5

          What do you mean by "locked"?

          I open it with this code:

          if (serial_in->open(QSerialPort::ReadOnly)) {
          			serial_in->setBaudRate(QSerialPort::Baud2400);
          			serial_in->setDataBits(QSerialPort::Data8);
          			serial_in->setParity(QSerialPort::NoParity);
          			serial_in->setStopBits(QSerialPort::OneStop);
          			serial_in->setFlowControl(QSerialPort::NoFlowControl);
          }
          
          E 1 Reply Last reply 26 Mar 2021, 20:04
          0
          • S Offline
            S Offline
            SGaist
            Lifetime Qt Champion
            wrote on 26 Mar 2021, 19:37 last edited by
            #6

            Sorry, I meant the data source. So in your case, you wrote it's your car. Are you using a custom device to read the information ? IIRC, cars rather use industrial serial buses like CAN rather than RS-232.

            Interested in AI ? www.idiap.ch
            Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

            M 1 Reply Last reply 27 Mar 2021, 13:49
            1
            • M Michal Poplawski
              26 Mar 2021, 19:31

              What do you mean by "locked"?

              I open it with this code:

              if (serial_in->open(QSerialPort::ReadOnly)) {
              			serial_in->setBaudRate(QSerialPort::Baud2400);
              			serial_in->setDataBits(QSerialPort::Data8);
              			serial_in->setParity(QSerialPort::NoParity);
              			serial_in->setStopBits(QSerialPort::OneStop);
              			serial_in->setFlowControl(QSerialPort::NoFlowControl);
              }
              
              E Offline
              E Offline
              eyllanesc
              wrote on 26 Mar 2021, 20:04 last edited by
              #7

              @Michal-Poplawski I mean you set the parameters of the serial device to open it? Isn't it illogical? Serial communication has rules and among this is the baudrate, for example, which is indicated by the communication speed so that both speak the same "language" and after establishing those rules, they can no longer be changed. So it changes to:

              serial_in->setBaudRate(QSerialPort::Baud2400);
              serial_in->setDataBits(QSerialPort::Data8);
              serial_in->setParity(QSerialPort::NoParity);
              serial_in->setStopBits(QSerialPort::OneStop);
              serial_in->setFlowControl(QSerialPort::NoFlowControl);
              if (serial_in->open(QSerialPort::ReadOnly)) {
                  qDebgu() << "open";
              }
              

              If you want me to help you develop some work then you can write to my email: e.yllanescucho@gmal.com.

              M 1 Reply Last reply 27 Mar 2021, 14:04
              0
              • S SGaist
                26 Mar 2021, 19:37

                Sorry, I meant the data source. So in your case, you wrote it's your car. Are you using a custom device to read the information ? IIRC, cars rather use industrial serial buses like CAN rather than RS-232.

                M Offline
                M Offline
                Michal Poplawski
                wrote on 27 Mar 2021, 13:49 last edited by
                #8

                @SGaist
                Hardware layer is simply a transoptor (PS2501) plus pull-up resistors on input and output lines (both 1kOhm), because input signal is inversed. I have no problem reading data on serial port behind that transoptor.

                In my car (Subaru Outback 2008) most of internal communication indeed is done via CAN bus, however that particular display (clock plus MPG) runs on serial UART and receives data from combination meter.

                What I'm basically trying to achieve is to read data, convert it to metric and put it to metric display unit (originally I have imperial one and the display has fixed fields, so it cannot be reprogrammed conviniently). Eventually the conversion will be done with Arduino, but for now I have PC software based on QT classes, because it's simpler to visualize incomming and outgoing data.

                I have a working solution now.

                First of all:

                read_buffer.clear();
                

                That's a REALLY STUPID WAY OF CLEARING BUFFER AFTER READ. Because buffer is async in nature so I have no way of knowing how much data is in it. Which means that I'm leaking frames/parts of them that have been added to the buffer from port. What I should have done is to:

                read_buffer.remove(some_start_point_mostly_0, read_data_size);
                

                As for a method of ensuring that entire frame has been read... Each frame has a checksum added at the end (least significant byte of sum of all parameters). Bruthal method is to calculate that checksum on incominng stream (if length is proper) and if the checksum is OK, then read parameters. If checksum is not OK then I remove first byte of data stream and start over.

                I understand that it's not a perfect way od doing things (i.e. I can read garbage if checksum over stream is the same as one of the data fields), but it works for now. However if there is a more elegant way of solving this I'd be happy to hear about it.

                Thanks for your interest!

                S 1 Reply Last reply 27 Mar 2021, 19:36
                0
                • E eyllanesc
                  26 Mar 2021, 20:04

                  @Michal-Poplawski I mean you set the parameters of the serial device to open it? Isn't it illogical? Serial communication has rules and among this is the baudrate, for example, which is indicated by the communication speed so that both speak the same "language" and after establishing those rules, they can no longer be changed. So it changes to:

                  serial_in->setBaudRate(QSerialPort::Baud2400);
                  serial_in->setDataBits(QSerialPort::Data8);
                  serial_in->setParity(QSerialPort::NoParity);
                  serial_in->setStopBits(QSerialPort::OneStop);
                  serial_in->setFlowControl(QSerialPort::NoFlowControl);
                  if (serial_in->open(QSerialPort::ReadOnly)) {
                      qDebgu() << "open";
                  }
                  
                  M Offline
                  M Offline
                  Michal Poplawski
                  wrote on 27 Mar 2021, 14:04 last edited by
                  #9

                  @eyllanesc
                  Unfortunately you cannot set baud rate per your needs on non-opened port:

                  baudRate : qint32

                  This property holds the data baud rate for the desired direction

                  If the setting is successful or set before opening the port, returns true; otherwise returns false and sets an error code which can be obtained by accessing the value of the QSerialPort::error property. To set the baud rate, use the enumeration QSerialPort::BaudRate or any positive qint32 value.

                  Note: If the setting is set before opening the port, the actual serial port setting is done automatically in the QSerialPort::open() method right after that the opening of the port succeeds.
                  https://doc.qt.io/qt-5/qserialport.html

                  The same rule applies to the rest of communication parameters, so you must set them according to your needs after the port has been opened.

                  1 Reply Last reply
                  0
                  • M Michal Poplawski
                    27 Mar 2021, 13:49

                    @SGaist
                    Hardware layer is simply a transoptor (PS2501) plus pull-up resistors on input and output lines (both 1kOhm), because input signal is inversed. I have no problem reading data on serial port behind that transoptor.

                    In my car (Subaru Outback 2008) most of internal communication indeed is done via CAN bus, however that particular display (clock plus MPG) runs on serial UART and receives data from combination meter.

                    What I'm basically trying to achieve is to read data, convert it to metric and put it to metric display unit (originally I have imperial one and the display has fixed fields, so it cannot be reprogrammed conviniently). Eventually the conversion will be done with Arduino, but for now I have PC software based on QT classes, because it's simpler to visualize incomming and outgoing data.

                    I have a working solution now.

                    First of all:

                    read_buffer.clear();
                    

                    That's a REALLY STUPID WAY OF CLEARING BUFFER AFTER READ. Because buffer is async in nature so I have no way of knowing how much data is in it. Which means that I'm leaking frames/parts of them that have been added to the buffer from port. What I should have done is to:

                    read_buffer.remove(some_start_point_mostly_0, read_data_size);
                    

                    As for a method of ensuring that entire frame has been read... Each frame has a checksum added at the end (least significant byte of sum of all parameters). Bruthal method is to calculate that checksum on incominng stream (if length is proper) and if the checksum is OK, then read parameters. If checksum is not OK then I remove first byte of data stream and start over.

                    I understand that it's not a perfect way od doing things (i.e. I can read garbage if checksum over stream is the same as one of the data fields), but it works for now. However if there is a more elegant way of solving this I'd be happy to hear about it.

                    Thanks for your interest!

                    S Offline
                    S Offline
                    SGaist
                    Lifetime Qt Champion
                    wrote on 27 Mar 2021, 19:36 last edited by
                    #10

                    @Michal-Poplawski said in QSerialPort Async read - How to ensure full packet read:

                    I understand that it's not a perfect way od doing things (i.e. I can read garbage if checksum over stream is the same as one of the data fields), but it works for now. However if there is a more elegant way of solving this I'd be happy to hear about it.

                    Sounds fine, you have a way to ensure that you got your data and that it is in a consistant form so it's all good.

                    Since you mentioned Arduino, you may also develop the code on the Arduino and forward the data to your application so you have both up and running and available for tests.

                    Interested in AI ? www.idiap.ch
                    Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                    M 1 Reply Last reply 27 Mar 2021, 20:32
                    1
                    • S SGaist
                      27 Mar 2021, 19:36

                      @Michal-Poplawski said in QSerialPort Async read - How to ensure full packet read:

                      I understand that it's not a perfect way od doing things (i.e. I can read garbage if checksum over stream is the same as one of the data fields), but it works for now. However if there is a more elegant way of solving this I'd be happy to hear about it.

                      Sounds fine, you have a way to ensure that you got your data and that it is in a consistant form so it's all good.

                      Since you mentioned Arduino, you may also develop the code on the Arduino and forward the data to your application so you have both up and running and available for tests.

                      M Offline
                      M Offline
                      Michal Poplawski
                      wrote on 27 Mar 2021, 20:32 last edited by
                      #11

                      @SGaist
                      That's precisely the idea! :)

                      1 Reply Last reply
                      0

                      11/11

                      27 Mar 2021, 20:32

                      • Login

                      • Login or register to search.
                      11 out of 11
                      • First post
                        11/11
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • Users
                      • Groups
                      • Search
                      • Get Qt Extensions
                      • Unsolved