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. Raspbbery Pi 3 Serial Port Performance Problem
Forum Updated to NodeBB v4.3 + New Features

Raspbbery Pi 3 Serial Port Performance Problem

Scheduled Pinned Locked Moved Unsolved Mobile and Embedded
13 Posts 3 Posters 3.0k Views 2 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.
  • K Offline
    K Offline
    koahnig
    wrote on 25 Mar 2017, 09:50 last edited by
    #2

    Hi and welcome to devnet forum

    If I understand correctly, you have no problem reading the serial data and display it somewhere until you try to export the data into excel sheets with qxlsx.

    You are suspecting a performance problem. IMHO you are right that it is in either component serial plus display or qxlsx, but more likely qxlsx is causing the problem because of complexity of Excel formatting.
    Therefore, I would start looking into details of cpu time consumption of components rather than pointing to somewhere and try to optimize there.

    I have never worked RP, but I assume that you can check in parallel some cpu time checks. This might be through linux commands in RP OS in parallel or measures of time differences in your application. You probably need to research on your own what the best way is.

    Another option would be storing the information into plain text files without any additional processing instead of your excel sheet. If this works sufficiently, you can check the performance of qxlsx by simply generating data with an internal time stamp and store with qxlsx in a similar fashion as you do with data coming from serial.

    When the storing of plain files is already a problem, your board is too slow and you need to lower the data output by your device and/or looking for the optimization as you already looking for above.

    My gut feeling tells me that probably you are facing already problems with your simulation of storing with qxlsx. This is probably slowing the whole process and casuing your problems.

    Vote the answer(s) that helped you to solve your issue(s)

    1 Reply Last reply
    0
    • A Offline
      A Offline
      aktay
      wrote on 25 Mar 2017, 14:10 last edited by
      #3

      I tried to add the data to MySQL. But the same thing happens again.Some data do not come as characters, they come as strings.

      QT App CPU= %6.0, Memory usage: Regular increase. Avarege %14.5
      Mysql CPU=1.0, Memory usage : Regular increase. Avarage % 4

      I think that an arrangement should be made in software.
      Are there any idea that you can suggest me for getting data as more efficient?

      Thanks.

      K 1 Reply Last reply 25 Mar 2017, 17:54
      0
      • A aktay
        25 Mar 2017, 14:10

        I tried to add the data to MySQL. But the same thing happens again.Some data do not come as characters, they come as strings.

        QT App CPU= %6.0, Memory usage: Regular increase. Avarege %14.5
        Mysql CPU=1.0, Memory usage : Regular increase. Avarage % 4

        I think that an arrangement should be made in software.
        Are there any idea that you can suggest me for getting data as more efficient?

        Thanks.

        K Offline
        K Offline
        koahnig
        wrote on 25 Mar 2017, 17:54 last edited by koahnig
        #4

        @aktay said in Raspbbery Pi 3 Serial Port Performance Problem:

        QT App CPU= %6.0, Memory usage: Regular increase. Avarege %14.5
        Mysql CPU=1.0, Memory usage : Regular increase. Avarage % 4

        That is good. There seem to be enough cpu available.

        @aktay said in Raspbbery Pi 3 Serial Port Performance Problem:

        I tried to add the data to MySQL. But the same thing happens again.Some data do not come as characters, they come as strings.
        Where do you see the problem here?
        A string is just a sequence of characters. Very often there are more just one byte/character in the buffer when you got the signal readyRead().
        With

                  QByteArray portData;
                  portData=serial->readAll();
        

        You are reading all bytes at once from the buffer associated with the serial into portData. Then you loop over the different bytes and seem to handle them correctly. It is not clear to me where you have a problem.

        Vote the answer(s) that helped you to solve your issue(s)

        1 Reply Last reply
        0
        • A Offline
          A Offline
          aktay
          wrote on 25 Mar 2017, 20:03 last edited by
          #5

          You may see correct data format below:

          "["
          "1"
          "0"
          "0"
          "0"
          ","
          "2"
          "1"
          ","
          "3"
          "6"
          "7"
          "8"
          ","
          "3"
          "6"
          "8"
          //etc.
          

          When I put on extra work (ex. write data to excel, write data to mysql etc.) data format changes.

          "0"
          "]"
          "0"
          "6"
          "9"
          "*"
          "\r\n\x00\x00\x00"
          **"[1000,25,+00"** // Normally I should get this as one charecter.
          "0"
          "0"
          "0"
          ","
          "2"
          "]"
          "0"
          "7"
          "7"
          "*"
          "\r"
          "\n"
          "["
          "1"
          

          Thanks.

          K 1 Reply Last reply 25 Mar 2017, 20:40
          0
          • A aktay
            25 Mar 2017, 20:03

            You may see correct data format below:

            "["
            "1"
            "0"
            "0"
            "0"
            ","
            "2"
            "1"
            ","
            "3"
            "6"
            "7"
            "8"
            ","
            "3"
            "6"
            "8"
            //etc.
            

            When I put on extra work (ex. write data to excel, write data to mysql etc.) data format changes.

            "0"
            "]"
            "0"
            "6"
            "9"
            "*"
            "\r\n\x00\x00\x00"
            **"[1000,25,+00"** // Normally I should get this as one charecter.
            "0"
            "0"
            "0"
            ","
            "2"
            "]"
            "0"
            "7"
            "7"
            "*"
            "\r"
            "\n"
            "["
            "1"
            

            Thanks.

            K Offline
            K Offline
            koahnig
            wrote on 25 Mar 2017, 20:40 last edited by
            #6

            @aktay

            Please show the code you are using to print this stuff.

            Vote the answer(s) that helped you to solve your issue(s)

            1 Reply Last reply
            0
            • A Offline
              A Offline
              aktay
              wrote on 25 Mar 2017, 22:37 last edited by aktay
              #7

              I am read port after write console. I just using qDebug().

              void MainWindow::portRead(){
                     QByteArray portData;
                        portData=serial->readAll();
              qDebug()<<portData;  // I am writing the console here. Also I am sending data mysql and qwidget. (Via another Class and another function)
                    
                           if(portData==QChar('[')){
                           tempList.append(portData);
                           arrayFirst=1;
                           }else if(portData==QChar('*') && arrayFirst!=0){
                             emit arraySplit(tempList);
                                tempList.clear();
                                arrayFirst=0;
              }else if(arrayFirst==1){
                     tempList.append(portData);
                           }
                   
              }
              
              K 1 Reply Last reply 26 Mar 2017, 10:57
              0
              • A aktay
                25 Mar 2017, 22:37

                I am read port after write console. I just using qDebug().

                void MainWindow::portRead(){
                       QByteArray portData;
                          portData=serial->readAll();
                qDebug()<<portData;  // I am writing the console here. Also I am sending data mysql and qwidget. (Via another Class and another function)
                      
                             if(portData==QChar('[')){
                             tempList.append(portData);
                             arrayFirst=1;
                             }else if(portData==QChar('*') && arrayFirst!=0){
                               emit arraySplit(tempList);
                                  tempList.clear();
                                  arrayFirst=0;
                }else if(arrayFirst==1){
                       tempList.append(portData);
                             }
                     
                }
                
                K Offline
                K Offline
                koahnig
                wrote on 26 Mar 2017, 10:57 last edited by
                #8

                @aktay

                You are reading all bytes in the buffer with readAll() and you are outputting all those bytes with the next statement. Actually you are always reading a complete string and youare always outputting a complete string. Only the first case the loop trigger, you are probably using, is faster and readAll reads only one byte to the buffer.
                Anything you add as processing will ultimately slow down you all other processing. In your case the loop reading the data is slowed by this additional code and suddenly your are reading more than one byte/character into your string. That's it.

                However, what you need to check is that this code sample has a significant difference

                @aktay said in Raspbbery Pi 3 Serial Port Performance Problem:

                void MainWindow::portRead(){
                       QByteArray portData;
                          portData=serial->readAll();
                qDebug()<<portData;  // I am writing the console here. Also I am sending data mysql and qwidget. (Via another Class and another function)
                      
                             if(portData==QChar('[')){
                             tempList.append(portData);
                             arrayFirst=1;
                             }else if(portData==QChar('*') && arrayFirst!=0){
                               emit arraySplit(tempList);
                                  tempList.clear();
                                  arrayFirst=0;
                }else if(arrayFirst==1){
                       tempList.append(portData);
                             }
                     
                }
                

                to the initial code sample which is probably causing your confusion:
                @aktay said in Raspbbery Pi 3 Serial Port Performance Problem:

                void MainWindow::portRead(){
                       QByteArray portData;
                          portData=serial->readAll();
                         for(int i=0;i<portData.size();i++){
                             if(portData.at(i)==QChar('[')){
                             tempList.append(portData.at(i));
                             arrayFirst=1;
                             }else if(portData.at(i)==QChar('*') && arrayFirst!=0){
                               emit arraySplit(tempList);
                                  tempList.clear();
                                  arrayFirst=0;
                             }else if(arrayFirst==1){
                       tempList.append(portData.at(i));
                             }
                         }
                }
                

                Sometime obviously you have changed the code.

                In your initial code you have this construct:

                        QByteArray portData;
                        portData=serial->readAll();                            // you read all bytes into a "string"
                        for(int i=0;i<portData.size();i++){                  // you loop over all individual bytes 
                            if(portData.at(i)==QChar('[')){                     // you access byte by byte and compare with another byte a QChar
                                tempList.append(portData.at(i));          // you are pushing byte by byte into a container
                

                In the code of your last post:

                      QByteArray portData;
                      portData=serial->readAll();                            // you read all bytes  into a "string" as above
                      qDebug()<<portData;  // I am writing the console here. Also I am sending data mysql and qwidget. (Via another Class and another function)
                                                                                                     // you print all bytes to qDebug
                      if(portData==QChar('[')){                                 // you compare all bytes in portData with one byte (usually the compiler should give a warning)
                          tempList.append(portData);                      //  you push all bytes of portData into the container
                

                Vote the answer(s) that helped you to solve your issue(s)

                1 Reply Last reply
                2
                • A Offline
                  A Offline
                  aktay
                  wrote on 26 Mar 2017, 14:03 last edited by
                  #9

                  As I said at the beginning, if I use the loop, the data comes out late. For this reason I do not use that code. Because I have to take the data instantaneously without delay.
                  I am using code below in my program.

                  void MainWindow::portRead(){
                         QByteArray portData;
                            portData=serial->readAll();
                               if(portData==QChar('[')){
                               tempList.append(portData);
                               arrayFirst=1;
                               }else if(portData==QChar('*') && arrayFirst!=0){
                                 emit arraySplit(tempList);
                                    tempList.clear();
                                    arrayFirst=0;
                               }else if(arrayFirst==1){
                         tempList.append(portData);
                  
                  K 1 Reply Last reply 26 Mar 2017, 16:32
                  0
                  • A aktay
                    26 Mar 2017, 14:03

                    As I said at the beginning, if I use the loop, the data comes out late. For this reason I do not use that code. Because I have to take the data instantaneously without delay.
                    I am using code below in my program.

                    void MainWindow::portRead(){
                           QByteArray portData;
                              portData=serial->readAll();
                                 if(portData==QChar('[')){
                                 tempList.append(portData);
                                 arrayFirst=1;
                                 }else if(portData==QChar('*') && arrayFirst!=0){
                                   emit arraySplit(tempList);
                                      tempList.clear();
                                      arrayFirst=0;
                                 }else if(arrayFirst==1){
                           tempList.append(portData);
                    
                    K Offline
                    K Offline
                    koahnig
                    wrote on 26 Mar 2017, 16:32 last edited by
                    #10

                    @aktay
                    Restructuring your code to make more readable:

                    void MainWindow::portRead()
                    {
                        QByteArray portData;
                        portData=serial->readAll();                                 // this statements whatever is in the buffer of QSerialPort may be 0 to almost infinity
                    
                    // you are compring a string with a character.  Will work only when character is casted autmatically to string
                    // since the comparison is for strings you may compare "[100" with "[" which gives false. 
                    // Only the when you have read one byte and it happens to be "[" you will have true.
                        if(portData==QChar('['))                                        
                        {
                            tempList.append(portData);
                            arrayFirst=1;
                        }
                    // The same here as explained for "[" but for "*"
                        else if(portData==QChar('*') && arrayFirst!=0)
                        {
                            emit arraySplit(tempList);
                            tempList.clear();
                            arrayFirst=0;
                        }
                        else if(arrayFirst==1)
                       {
                           tempList.append(portData);
                    

                    As already written above readAll reads everything in the buffer into a string. If you do so, you need to loop for checking your chars, but you cannot as you do at the moment. You do not compare as you expect.
                    BTW there are many other means to scan QByteArray e.g. http://doc.qt.io/qt-5/qbytearray.html#indexOf-1 for locating a character.

                    Most likely you have another issue. How do you trigger portRead?

                    Typically this is done with the signal readyRead from QSerialPort. However, it is not triggered for every byte, but may be triggered when several bytes are in the buffer. This is dependent on comm speed.

                    Vote the answer(s) that helped you to solve your issue(s)

                    1 Reply Last reply
                    3
                    • A Offline
                      A Offline
                      aktay
                      wrote on 27 Mar 2017, 06:03 last edited by
                      #11

                      Thank you for your replies. I understand what you mean. You can see my serial port configuration below.

                      QSerialPort *serial;
                      
                          serial = new QSerialPort(this);
                          serial->setPortName("ttyS0");
                          serial->setBaudRate(QSerialPort::Baud9600);
                          serial->setDataBits(QSerialPort::Data8);
                          serial->setParity(QSerialPort::NoParity);
                          serial->setStopBits(QSerialPort::OneStop);
                          serial->setFlowControl(QSerialPort::NoFlowControl);
                          serial->open(QIODevice::ReadOnly);
                          connect(serial,SIGNAL(readyRead()),this, SLOT(portRead()));
                      

                      As you say, I use the typical method of triggering. As you know, the PortRead function is as follows.

                      void MainWindow::portRead(){
                             QByteArray portData;
                                portData=serial->readAll();
                                   if(portData==QChar('[')){
                                   tempList.append(portData);
                                   arrayFirst=1;
                                   }else if(portData==QChar('*') && arrayFirst!=0){
                                     emit arraySplit(tempList);
                                        tempList.clear();
                                        arrayFirst=0;
                                   }else if(arrayFirst==1){
                             tempList.append(portData);
                      
                      1. How should I trigger portRead for read the data from the serial port as char? (Without delay.)
                        2.How can I clean the buffer? I tried the Clear & flush methods but it did not work.

                      Thanks.

                      J K 2 Replies Last reply 27 Mar 2017, 07:29
                      0
                      • A aktay
                        27 Mar 2017, 06:03

                        Thank you for your replies. I understand what you mean. You can see my serial port configuration below.

                        QSerialPort *serial;
                        
                            serial = new QSerialPort(this);
                            serial->setPortName("ttyS0");
                            serial->setBaudRate(QSerialPort::Baud9600);
                            serial->setDataBits(QSerialPort::Data8);
                            serial->setParity(QSerialPort::NoParity);
                            serial->setStopBits(QSerialPort::OneStop);
                            serial->setFlowControl(QSerialPort::NoFlowControl);
                            serial->open(QIODevice::ReadOnly);
                            connect(serial,SIGNAL(readyRead()),this, SLOT(portRead()));
                        

                        As you say, I use the typical method of triggering. As you know, the PortRead function is as follows.

                        void MainWindow::portRead(){
                               QByteArray portData;
                                  portData=serial->readAll();
                                     if(portData==QChar('[')){
                                     tempList.append(portData);
                                     arrayFirst=1;
                                     }else if(portData==QChar('*') && arrayFirst!=0){
                                       emit arraySplit(tempList);
                                          tempList.clear();
                                          arrayFirst=0;
                                     }else if(arrayFirst==1){
                               tempList.append(portData);
                        
                        1. How should I trigger portRead for read the data from the serial port as char? (Without delay.)
                          2.How can I clean the buffer? I tried the Clear & flush methods but it did not work.

                        Thanks.

                        J Offline
                        J Offline
                        jsulm
                        Lifetime Qt Champion
                        wrote on 27 Mar 2017, 07:29 last edited by
                        #12

                        @aktay said in Raspbbery Pi 3 Serial Port Performance Problem:

                        How should I trigger portRead for read the data from the serial port as char

                        I think you can't. Just use the loop in portRead().

                        https://forum.qt.io/topic/113070/qt-code-of-conduct

                        1 Reply Last reply
                        2
                        • A aktay
                          27 Mar 2017, 06:03

                          Thank you for your replies. I understand what you mean. You can see my serial port configuration below.

                          QSerialPort *serial;
                          
                              serial = new QSerialPort(this);
                              serial->setPortName("ttyS0");
                              serial->setBaudRate(QSerialPort::Baud9600);
                              serial->setDataBits(QSerialPort::Data8);
                              serial->setParity(QSerialPort::NoParity);
                              serial->setStopBits(QSerialPort::OneStop);
                              serial->setFlowControl(QSerialPort::NoFlowControl);
                              serial->open(QIODevice::ReadOnly);
                              connect(serial,SIGNAL(readyRead()),this, SLOT(portRead()));
                          

                          As you say, I use the typical method of triggering. As you know, the PortRead function is as follows.

                          void MainWindow::portRead(){
                                 QByteArray portData;
                                    portData=serial->readAll();
                                       if(portData==QChar('[')){
                                       tempList.append(portData);
                                       arrayFirst=1;
                                       }else if(portData==QChar('*') && arrayFirst!=0){
                                         emit arraySplit(tempList);
                                            tempList.clear();
                                            arrayFirst=0;
                                       }else if(arrayFirst==1){
                                 tempList.append(portData);
                          
                          1. How should I trigger portRead for read the data from the serial port as char? (Without delay.)
                            2.How can I clean the buffer? I tried the Clear & flush methods but it did not work.

                          Thanks.

                          K Offline
                          K Offline
                          koahnig
                          wrote on 27 Mar 2017, 09:29 last edited by
                          #13

                          @aktay

                          OK, you are triggering portRead through readyRead signal and this is correct. The question was more that you are triggering with the right method.

                          Now some people assume that readyRead() is triggered in regularly e.g. on a byte basis or record basis. However, just to ensure that is not the case. Triggering on a byte basis would probably overflow the event loop for fast connections and recordwise is not possible either, since how should any device decide on a binary level when a record ends.
                          Without knowing the exact details of triggering a signal readyRead, you may assume that it is triggered when new data arrives and you are not in a slot and subsequent routines triggered by readyRead signal.

                          You started to see "problems" when you suddenly did not receive at each call of readyRead one byte. This is completely normal when your additional functionality pick up cpu resources.

                          In your case you are seeing more than one byte in the string returned by readAll after you have added functionality.

                          As already written before

                          @koahnig said in Raspbbery Pi 3 Serial Port Performance Problem:

                          You are reading all bytes in the buffer with readAll() and you are outputting all those bytes with the next statement. Actually you are always reading a complete string and youare always outputting a complete string. Only the first case the loop trigger, you are probably using, is faster and readAll reads only one byte to the buffer.

                          Now you have two choices:

                          • emptying the QSerialPort buffer at once with readAll as you do. This implies that you are required to some looping afterwards and handling individual bytes as you had done in your initial post.
                          • Looping around reading the QSerialPort buffer and use read and read byte by byte

                          Just neglecting a loop will not get you anywhere you like to be. Read also the comments I had added to your code here

                          @koahnig said in Raspbbery Pi 3 Serial Port Performance Problem:

                          void MainWindow::portRead()
                          {
                          QByteArray portData;
                          portData=serial->readAll(); // this statements whatever is in the buffer of QSerialPort may be 0 to almost infinity

                          // you are compring a string with a character. Will work only when character is casted autmatically to string
                          // since the comparison is for strings you may compare "[100" with "[" which gives false.
                          // Only the when you have read one byte and it happens to be "[" you will have true.
                          if(portData==QChar('['))
                          {
                          tempList.append(portData);
                          arrayFirst=1;
                          }
                          // The same here as explained for "[" but for ""
                          else if(portData==QChar('
                          ') && arrayFirst!=0)
                          {
                          emit arraySplit(tempList);
                          tempList.clear();
                          arrayFirst=0;
                          }
                          else if(arrayFirst==1)
                          {
                          tempList.append(portData);

                          One last thing you need to understand also is that when you use readAll at the beginning of the routine, the buffer is completely emptied at that point of time. Your processing in the routine and subsequent routines may take a while. Any byte stored into the buffer during your processing will most likely not create a new readyRead signal. Therefore, it is advisable to check the buffer's size with bytesAvailable at the end in order to make that you are not missing information which will pop up with the next signal readyRead.

                          Vote the answer(s) that helped you to solve your issue(s)

                          1 Reply Last reply
                          2

                          11/13

                          27 Mar 2017, 06:03

                          • Login

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