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. Serial performance
Forum Updated to NodeBB v4.3 + New Features

Serial performance

Scheduled Pinned Locked Moved Unsolved Mobile and Embedded
8 Posts 3 Posters 3.0k Views 1 Watching
  • 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.
  • J Offline
    J Offline
    jastmc
    wrote on last edited by
    #1

    I am using Qt 5.3 on a Beaglebone Black to control my hardware and display results. My hardware is driven by 3 serial ports running at 115200 baud. The Beaglebone is single core.
    The application is a state machine that sends a command packet (5 bytes) to the serial port. To send a packet, we emit a signal with the packet data and a slot in the Comms sends the data. When data is received, the port is read ( data = this->port->readAll(); ) and a signal is emitted for the packet contents to be checked and a flag for command acknowledge or error is set.
    The next state in the application then checks for the correct flag before proceeding. Standard stuff!
    This works OK but it takes a lot of time for the received packet to be detected and flag set (200ms to 500ms or longer) even though on the oscilloscope it can be seen that the hardware responds in 10ms.

    It seems to me that it takes a long time for the events on the serial port to be processed and there are a lot of command to be processed so the application seems slow.

    My question is, would this benefit from moving the serial port interface code and processing to a separate thread?

    Apologies if this has been asked before (please point me to appropriate answers).

    Regards,
    James

    PS. Processing of the received packet doesn't take long, its just verifying the checksum and setting a flag to say the command has been correctly acknowledged.

    kshegunovK 1 Reply Last reply
    0
    • J jastmc

      I am using Qt 5.3 on a Beaglebone Black to control my hardware and display results. My hardware is driven by 3 serial ports running at 115200 baud. The Beaglebone is single core.
      The application is a state machine that sends a command packet (5 bytes) to the serial port. To send a packet, we emit a signal with the packet data and a slot in the Comms sends the data. When data is received, the port is read ( data = this->port->readAll(); ) and a signal is emitted for the packet contents to be checked and a flag for command acknowledge or error is set.
      The next state in the application then checks for the correct flag before proceeding. Standard stuff!
      This works OK but it takes a lot of time for the received packet to be detected and flag set (200ms to 500ms or longer) even though on the oscilloscope it can be seen that the hardware responds in 10ms.

      It seems to me that it takes a long time for the events on the serial port to be processed and there are a lot of command to be processed so the application seems slow.

      My question is, would this benefit from moving the serial port interface code and processing to a separate thread?

      Apologies if this has been asked before (please point me to appropriate answers).

      Regards,
      James

      PS. Processing of the received packet doesn't take long, its just verifying the checksum and setting a flag to say the command has been correctly acknowledged.

      kshegunovK Offline
      kshegunovK Offline
      kshegunov
      Moderators
      wrote on last edited by
      #2

      @jastmc said in Serial performance:

      My question is, would this benefit from moving the serial port interface code and processing to a separate thread?

      I doubt it, but probably @kuzulis can give you a better answer.

      Read and abide by the Qt Code of Conduct

      1 Reply Last reply
      0
      • K Offline
        K Offline
        kuzulis
        Qt Champions 2020
        wrote on last edited by kuzulis
        #3
        1. QSP internally uses the QSocketNotifier. If you use the 'pure' asynchronous state machine and so on (without calls of waitFoxxXX() methods), then it is impossible to have a delays as '200ms to 500ms or longer'. Maybe your remote device introduces delays (too long thinks) at making a response on a request.

        2. ( data = this->port->readAll(); ) does not guarantie that you are receive whole response package.

        3. Version 5.3 is too old, try 5.9.2.

        4. Usually, the threads does not required on 115200 bauds, at this speed is soo slow, to influence on the CPU and Qt-event loop.

        kshegunovK 1 Reply Last reply
        2
        • K kuzulis
          1. QSP internally uses the QSocketNotifier. If you use the 'pure' asynchronous state machine and so on (without calls of waitFoxxXX() methods), then it is impossible to have a delays as '200ms to 500ms or longer'. Maybe your remote device introduces delays (too long thinks) at making a response on a request.

          2. ( data = this->port->readAll(); ) does not guarantie that you are receive whole response package.

          3. Version 5.3 is too old, try 5.9.2.

          4. Usually, the threads does not required on 115200 bauds, at this speed is soo slow, to influence on the CPU and Qt-event loop.

          kshegunovK Offline
          kshegunovK Offline
          kshegunov
          Moderators
          wrote on last edited by
          #4

          @kuzulis, just out of curiosity, what'd be a typical figure for the latency of QSP and to what you'd attribute it? Is the socket notifier the "slowest link" in the chain leading to readyRead()?

          Read and abide by the Qt Code of Conduct

          J K 2 Replies Last reply
          0
          • kshegunovK kshegunov

            @kuzulis, just out of curiosity, what'd be a typical figure for the latency of QSP and to what you'd attribute it? Is the socket notifier the "slowest link" in the chain leading to readyRead()?

            J Offline
            J Offline
            jastmc
            wrote on last edited by jastmc
            #5

            Thanks for the prompt replies.

            I am not using any blocking calls and the remote device responds in ~10ms, observed on 'scope.

            I was wondering whether the Qt Event loop could be so busy that it was taking so long to get around to processing the serial port signals?

            I did a simple serial test in a very basic application to just send a packet and, when I received 5 characters back, I sent another packet. In that test, Qt took 10 - 15ms to respond to a received packet.

            In my real application, there are a number of graphics screens, one of which is displayed at a time but all they do is advance a progress bar while we send commands to and get responses from the serial port. That should not be enough to introduce such a large delay!

            Can you give me any tips on how to zone in on the actual cause of the delays in order to break it down into steps?

            Regards,
            James

            1 Reply Last reply
            0
            • kshegunovK kshegunov

              @kuzulis, just out of curiosity, what'd be a typical figure for the latency of QSP and to what you'd attribute it? Is the socket notifier the "slowest link" in the chain leading to readyRead()?

              K Offline
              K Offline
              kuzulis
              Qt Champions 2020
              wrote on last edited by kuzulis
              #6

              @kshegunov said in Serial performance:

              @kuzulis, just out of curiosity, what'd be a typical figure for the latency of QSP and to what you'd attribute it?

              Usually, less than one millisecond (please see below).

              @kshegunov said in Serial performance:

              Is the socket notifier the "slowest link" in the chain leading to readyRead()?

              I'm don't think so.

              @jastmc, could you please make following test on your board: connect Rx && Tx physically and run following code:

              #include <QCoreApplication>
              #include <QSerialPort>
              #include <QElapsedTimer>
              #include <QDebug>
              
              int main(int argc, char *argv[])
              {
                  QCoreApplication a(argc, argv);
                  QElapsedTimer timer;
                  QSerialPort uart("/dev/ttyUSB0");
                  QCoreApplication::connect(&uart, &QSerialPort::readyRead, [&uart, &timer]() {
                      if (uart.bytesAvailable() < 5)
                          return;
                      qDebug() << "Rx:" << uart.readAll() << "in" << timer.nsecsElapsed() << "ns";
                      timer.start();
                      uart.write("Hello");
                  });
                  uart.setBaudRate(115200);
                  uart.open(QIODevice::ReadWrite);
                  uart.write("Hello");
                  return a.exec();
              }
              

              E.g. for me it prints out following:

              Rx: "Hello" in 645445 ns
              Rx: "Hello" in 616017 ns
              Rx: "Hello" in 598339 ns
              Rx: "Hello" in 639166 ns
              Rx: "Hello" in 604685 ns

              I have used ArchLinux x64, UART USB - pl2303, Qt 5.9.2.

              PS: Sometimes, problems comes from the drivers, e.g: QTBUG-48561, also, maybe your driver does not used a DMA and so on. You need to do tests, e.g. with diffrent uarts (e.g. try to plug the USB serial port or something else to your board), or try to update the kernel, because I can't say nothing more. I never used the boards with a single core CPU.

              In my real application, there are a number of graphics screens,

              Maybe it is reason too.

              J 1 Reply Last reply
              2
              • K kuzulis

                @kshegunov said in Serial performance:

                @kuzulis, just out of curiosity, what'd be a typical figure for the latency of QSP and to what you'd attribute it?

                Usually, less than one millisecond (please see below).

                @kshegunov said in Serial performance:

                Is the socket notifier the "slowest link" in the chain leading to readyRead()?

                I'm don't think so.

                @jastmc, could you please make following test on your board: connect Rx && Tx physically and run following code:

                #include <QCoreApplication>
                #include <QSerialPort>
                #include <QElapsedTimer>
                #include <QDebug>
                
                int main(int argc, char *argv[])
                {
                    QCoreApplication a(argc, argv);
                    QElapsedTimer timer;
                    QSerialPort uart("/dev/ttyUSB0");
                    QCoreApplication::connect(&uart, &QSerialPort::readyRead, [&uart, &timer]() {
                        if (uart.bytesAvailable() < 5)
                            return;
                        qDebug() << "Rx:" << uart.readAll() << "in" << timer.nsecsElapsed() << "ns";
                        timer.start();
                        uart.write("Hello");
                    });
                    uart.setBaudRate(115200);
                    uart.open(QIODevice::ReadWrite);
                    uart.write("Hello");
                    return a.exec();
                }
                

                E.g. for me it prints out following:

                Rx: "Hello" in 645445 ns
                Rx: "Hello" in 616017 ns
                Rx: "Hello" in 598339 ns
                Rx: "Hello" in 639166 ns
                Rx: "Hello" in 604685 ns

                I have used ArchLinux x64, UART USB - pl2303, Qt 5.9.2.

                PS: Sometimes, problems comes from the drivers, e.g: QTBUG-48561, also, maybe your driver does not used a DMA and so on. You need to do tests, e.g. with diffrent uarts (e.g. try to plug the USB serial port or something else to your board), or try to update the kernel, because I can't say nothing more. I never used the boards with a single core CPU.

                In my real application, there are a number of graphics screens,

                Maybe it is reason too.

                J Offline
                J Offline
                jastmc
                wrote on last edited by
                #7

                @kuzulis

                I had tried this following test:

                #include "mainwindow.h"
                #include "ui_mainwindow.h"
                #include "comms.h"
                
                #include <QDebug>
                #include <QSerialPort>
                #include <iostream>
                #include <QObject>
                #include <QByteArray>
                #include <QString>
                #include <QElapsedTimer>
                
                int count;
                QByteArray dataout;
                QByteArray datain;
                
                MainWindow::MainWindow(QWidget *parent) :
                    QMainWindow(parent),
                    ui(new Ui::MainWindow)
                {
                    ui->setupUi(this);
                
                    timer = new QElapsedTimer();
                
                    dataout.append(0x03);
                    dataout.append(0x20);
                    dataout.append(0x03);
                    dataout.append(0x07);
                    dataout.append(0x2d);
                
                    serial = new QSerialPort(this);
                    serial->setPortName("/dev/ttyO4");
                    serial->setBaudRate(QSerialPort::Baud115200);
                    serial->setDataBits(QSerialPort::Data8);
                    serial->setParity(QSerialPort::NoParity);
                    serial->setStopBits(QSerialPort::OneStop);
                    serial->setFlowControl(QSerialPort::NoFlowControl);
                    if (!serial->open(QIODevice::ReadWrite))
                    {
                        qDebug() << " Failed to open port";
                        qApp->quit();
                    }
                    if (!connect(serial, (&QSerialPort::readyRead), this, (&MainWindow::readData )) )
                    {
                        qDebug() << " Can't connect ...";
                    }
                
                    qDebug() << " Starting...";
                    count = 0;
                
                    serial->write(dataout);
                    serial->flush();
                }
                
                void MainWindow::readData()
                {
                    QByteArray chars = serial->readAll();
                    din.append(chars);
                
                    if (din.size() > 4)
                    {
                        qDebug() << din.toHex() << "in" << timer->nsecsElapsed() << "ns";;
                        din.remove(0,5);
                
                        if (count++ < 1000)
                        {
                            serial->write(dataout);
                            serial->flush();
                        }
                
                    }
                }
                
                MainWindow::~MainWindow()
                {
                    delete ui;
                }
                
                

                The result was

                Starting...
                "0620030730" in 131405492763 ns
                "0620030730" in 131415504304 ns
                "0620030730" in 131417467096 ns
                "0620030730" in 131419417096 ns
                "0620030730" in 131421047638 ns
                

                The initial response take 10ms and the following ones come quicker.

                So I guess I need to look elsewhere.

                Thanks for your help.

                James

                K 1 Reply Last reply
                0
                • J jastmc

                  @kuzulis

                  I had tried this following test:

                  #include "mainwindow.h"
                  #include "ui_mainwindow.h"
                  #include "comms.h"
                  
                  #include <QDebug>
                  #include <QSerialPort>
                  #include <iostream>
                  #include <QObject>
                  #include <QByteArray>
                  #include <QString>
                  #include <QElapsedTimer>
                  
                  int count;
                  QByteArray dataout;
                  QByteArray datain;
                  
                  MainWindow::MainWindow(QWidget *parent) :
                      QMainWindow(parent),
                      ui(new Ui::MainWindow)
                  {
                      ui->setupUi(this);
                  
                      timer = new QElapsedTimer();
                  
                      dataout.append(0x03);
                      dataout.append(0x20);
                      dataout.append(0x03);
                      dataout.append(0x07);
                      dataout.append(0x2d);
                  
                      serial = new QSerialPort(this);
                      serial->setPortName("/dev/ttyO4");
                      serial->setBaudRate(QSerialPort::Baud115200);
                      serial->setDataBits(QSerialPort::Data8);
                      serial->setParity(QSerialPort::NoParity);
                      serial->setStopBits(QSerialPort::OneStop);
                      serial->setFlowControl(QSerialPort::NoFlowControl);
                      if (!serial->open(QIODevice::ReadWrite))
                      {
                          qDebug() << " Failed to open port";
                          qApp->quit();
                      }
                      if (!connect(serial, (&QSerialPort::readyRead), this, (&MainWindow::readData )) )
                      {
                          qDebug() << " Can't connect ...";
                      }
                  
                      qDebug() << " Starting...";
                      count = 0;
                  
                      serial->write(dataout);
                      serial->flush();
                  }
                  
                  void MainWindow::readData()
                  {
                      QByteArray chars = serial->readAll();
                      din.append(chars);
                  
                      if (din.size() > 4)
                      {
                          qDebug() << din.toHex() << "in" << timer->nsecsElapsed() << "ns";;
                          din.remove(0,5);
                  
                          if (count++ < 1000)
                          {
                              serial->write(dataout);
                              serial->flush();
                          }
                  
                      }
                  }
                  
                  MainWindow::~MainWindow()
                  {
                      delete ui;
                  }
                  
                  

                  The result was

                  Starting...
                  "0620030730" in 131405492763 ns
                  "0620030730" in 131415504304 ns
                  "0620030730" in 131417467096 ns
                  "0620030730" in 131419417096 ns
                  "0620030730" in 131421047638 ns
                  

                  The initial response take 10ms and the following ones come quicker.

                  So I guess I need to look elsewhere.

                  Thanks for your help.

                  James

                  K Offline
                  K Offline
                  kuzulis
                  Qt Champions 2020
                  wrote on last edited by kuzulis
                  #8

                  @jastmc said in Serial performance:

                  "0620030730" in 131417467096 ns
                  "0620030730" in 131419417096 ns

                  Well, ~1.5-2 msec is too long, IMHO. Try it without a gui app, just as console app (e.g. with that code which I posted).

                  UPD: Also, don't use flush().

                  1 Reply Last reply
                  0

                  • Login

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