Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Sending and receiving multiple serial signals
Forum Updated to NodeBB v4.3 + New Features

Sending and receiving multiple serial signals

Scheduled Pinned Locked Moved Solved General and Desktop
12 Posts 4 Posters 2.6k 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.
  • A Offline
    A Offline
    ardmn
    wrote on last edited by
    #1

    Hi everyone, I have a device connected to a serial port that has a command to send one data point upon request. I'm trying to make several sequential requests while printing the responses to the screen, but when I send more than one request I only get one response.

    Here is the serial code:

    ...
    
    connect(&serialPort,SIGNAL(readyRead()),this,SLOT(receiveMessage()));
    
    ...
    
    void Widget::receiveMessage()
    {
        QByteArray data = serialPort.readAll();
        QString dataPoint = QString::fromStdString(data.toStdString());
        ui->textBrowser->append(dataPoint);
    }
    
    void Widget::on_pushButton_clicked()
    {
        QString message = ui->lineEdit_2->text();
        message.append("\n");
        serialPort.write(message.toUtf8());
    }
    

    When sending one message, I get one data point printed on my textBrowser, but when I try to write multiple requests like this:

    void Widget::on_pushButton_clicked()
    {
        QString message = ui->lineEdit_2->text();
        message.append("\n");
        for (int i = 0; i < 5; i++){
            serialPort.write(message.toUtf8());
        }
    }
    

    I still get only one data point printed.
    I managed to get all 5 points by changing the code to this:

    void Widget::on_pushButton_clicked()
    {
        QString message = ui->lineEdit_2->text();
        message.append("\n");
        for (int i = 0; i < 5; i++){
            serialPort.write(message.toUtf8());
            serialPort.waitForReadyRead(500);
        }
    }
    

    But this blocks my program until all the data is received. Is there a way to get the data without waitForReadyRead? I thought I'd need to use threads so the program doesn't get blocked, but from what I read, you're not supposed to use threads since QSerialPort is already async.

    Pl45m4P Christian EhrlicherC 3 Replies Last reply
    0
    • A ardmn

      Hi everyone, I have a device connected to a serial port that has a command to send one data point upon request. I'm trying to make several sequential requests while printing the responses to the screen, but when I send more than one request I only get one response.

      Here is the serial code:

      ...
      
      connect(&serialPort,SIGNAL(readyRead()),this,SLOT(receiveMessage()));
      
      ...
      
      void Widget::receiveMessage()
      {
          QByteArray data = serialPort.readAll();
          QString dataPoint = QString::fromStdString(data.toStdString());
          ui->textBrowser->append(dataPoint);
      }
      
      void Widget::on_pushButton_clicked()
      {
          QString message = ui->lineEdit_2->text();
          message.append("\n");
          serialPort.write(message.toUtf8());
      }
      

      When sending one message, I get one data point printed on my textBrowser, but when I try to write multiple requests like this:

      void Widget::on_pushButton_clicked()
      {
          QString message = ui->lineEdit_2->text();
          message.append("\n");
          for (int i = 0; i < 5; i++){
              serialPort.write(message.toUtf8());
          }
      }
      

      I still get only one data point printed.
      I managed to get all 5 points by changing the code to this:

      void Widget::on_pushButton_clicked()
      {
          QString message = ui->lineEdit_2->text();
          message.append("\n");
          for (int i = 0; i < 5; i++){
              serialPort.write(message.toUtf8());
              serialPort.waitForReadyRead(500);
          }
      }
      

      But this blocks my program until all the data is received. Is there a way to get the data without waitForReadyRead? I thought I'd need to use threads so the program doesn't get blocked, but from what I read, you're not supposed to use threads since QSerialPort is already async.

      Pl45m4P Offline
      Pl45m4P Offline
      Pl45m4
      wrote on last edited by Pl45m4
      #2

      @ardmn said in Sending and receiving multiple serial signals:

      I thought I'd need to use threads so the program doesn't get blocked, but from what I read, you're not supposed to use threads since QSerialPort is already async.

      QSerialPort can be both. There is a synchronous and asynchronous approach, where the former should be avoided to use in GUI threads for obvious reasons.

      for (int i = 0; i < 5; i++){
      serialPort.write(message.toUtf8());
      serialPort.waitForReadyRead(500);
      }

      Here you are mixing both and serialPort.waitForReadyRead(500) blocks as you discovered.

      What does serialPort.write return? How many bytes were actually written?

      message.append("\n");

      Depending on your connected device, you sometimes need CR LF while sometimes just a LF is enough, to "confirm" or "close" the current command.
      Try

      message.append("\r\n");
      

      Here is the async example of QSerialPort

      • https://doc.qt.io/qt-6/qtserialport-terminal-example.html

      If debugging is the process of removing software bugs, then programming must be the process of putting them in.

      ~E. W. Dijkstra

      A 1 Reply Last reply
      2
      • Pl45m4P Pl45m4

        @ardmn said in Sending and receiving multiple serial signals:

        I thought I'd need to use threads so the program doesn't get blocked, but from what I read, you're not supposed to use threads since QSerialPort is already async.

        QSerialPort can be both. There is a synchronous and asynchronous approach, where the former should be avoided to use in GUI threads for obvious reasons.

        for (int i = 0; i < 5; i++){
        serialPort.write(message.toUtf8());
        serialPort.waitForReadyRead(500);
        }

        Here you are mixing both and serialPort.waitForReadyRead(500) blocks as you discovered.

        What does serialPort.write return? How many bytes were actually written?

        message.append("\n");

        Depending on your connected device, you sometimes need CR LF while sometimes just a LF is enough, to "confirm" or "close" the current command.
        Try

        message.append("\r\n");
        

        Here is the async example of QSerialPort

        • https://doc.qt.io/qt-6/qtserialport-terminal-example.html
        A Offline
        A Offline
        ardmn
        wrote on last edited by
        #3

        Hi, thanks for taking your time to answer! I tried your suggestions

        What does serialPort.write return? How many bytes were actually written?

        It always returns 7 bytes, even on the for loop, my command is "DATA1".

        Depending on your connected device, you sometimes need CR LF while sometimes just a LF is enough, to "confirm" or "close" the current command.
        Try

        message.append("\r\n");
        

        Tried it but no luck, still only getting one response on my text box.

        Here is the async example of QSerialPort

        • https://doc.qt.io/qt-6/qtserialport-terminal-example.html

        Same thing happens when trying with the example code, only one data point gets delivered. I was not using qtimer functions, so maybe it has something to do with that?

        1 Reply Last reply
        0
        • A ardmn

          Hi everyone, I have a device connected to a serial port that has a command to send one data point upon request. I'm trying to make several sequential requests while printing the responses to the screen, but when I send more than one request I only get one response.

          Here is the serial code:

          ...
          
          connect(&serialPort,SIGNAL(readyRead()),this,SLOT(receiveMessage()));
          
          ...
          
          void Widget::receiveMessage()
          {
              QByteArray data = serialPort.readAll();
              QString dataPoint = QString::fromStdString(data.toStdString());
              ui->textBrowser->append(dataPoint);
          }
          
          void Widget::on_pushButton_clicked()
          {
              QString message = ui->lineEdit_2->text();
              message.append("\n");
              serialPort.write(message.toUtf8());
          }
          

          When sending one message, I get one data point printed on my textBrowser, but when I try to write multiple requests like this:

          void Widget::on_pushButton_clicked()
          {
              QString message = ui->lineEdit_2->text();
              message.append("\n");
              for (int i = 0; i < 5; i++){
                  serialPort.write(message.toUtf8());
              }
          }
          

          I still get only one data point printed.
          I managed to get all 5 points by changing the code to this:

          void Widget::on_pushButton_clicked()
          {
              QString message = ui->lineEdit_2->text();
              message.append("\n");
              for (int i = 0; i < 5; i++){
                  serialPort.write(message.toUtf8());
                  serialPort.waitForReadyRead(500);
              }
          }
          

          But this blocks my program until all the data is received. Is there a way to get the data without waitForReadyRead? I thought I'd need to use threads so the program doesn't get blocked, but from what I read, you're not supposed to use threads since QSerialPort is already async.

          Christian EhrlicherC Online
          Christian EhrlicherC Online
          Christian Ehrlicher
          Lifetime Qt Champion
          wrote on last edited by
          #4

          @ardmn said in Sending and receiving multiple serial signals:

          void Widget::receiveMessage()
          {
          QByteArray data = serialPort.readAll();
          QString dataPoint = QString::fromStdString(data.toStdString());
          ui->textBrowser->append(dataPoint);
          }

          You might get more than one 'line' here so you have to properly split it up. serial communication is (like socket communication) a stream - there is no 'line' or something else - you have to implement a protocol on top by yourself.

          Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
          Visit the Qt Academy at https://academy.qt.io/catalog

          A 1 Reply Last reply
          3
          • Christian EhrlicherC Christian Ehrlicher

            @ardmn said in Sending and receiving multiple serial signals:

            void Widget::receiveMessage()
            {
            QByteArray data = serialPort.readAll();
            QString dataPoint = QString::fromStdString(data.toStdString());
            ui->textBrowser->append(dataPoint);
            }

            You might get more than one 'line' here so you have to properly split it up. serial communication is (like socket communication) a stream - there is no 'line' or something else - you have to implement a protocol on top by yourself.

            A Offline
            A Offline
            ardmn
            wrote on last edited by
            #5

            @Christian-Ehrlicher said in Sending and receiving multiple serial signals:

            You might get more than one 'line' here so you have to properly split it up. serial communication is (like socket communication) a stream - there is no 'line' or something else - you have to implement a protocol on top by yourself.

            Hi, I'm not exactly sure if this is what you mean but I've tried to make a buffer in the read function like this, the device sends a response that ends with \n

            void MainWindow::readData()
            {
                byteArray += Serial->readAll();
                if(byteArray.contains("\n")){
                    qDebug() << "received data point" << byteArray;
                    byteArray.clear();
                }
            }
            

            This didn't solve the problem though, the response I get when I loop the QSerialPort.write function is still:

            sent command: "DATA1"
            sent command: "DATA1"
            sent command: "DATA1"
            sent command: "DATA1"
            sent command: "DATA1"
            received data point "948302\n"
            
            JonBJ 1 Reply Last reply
            0
            • A ardmn

              Hi everyone, I have a device connected to a serial port that has a command to send one data point upon request. I'm trying to make several sequential requests while printing the responses to the screen, but when I send more than one request I only get one response.

              Here is the serial code:

              ...
              
              connect(&serialPort,SIGNAL(readyRead()),this,SLOT(receiveMessage()));
              
              ...
              
              void Widget::receiveMessage()
              {
                  QByteArray data = serialPort.readAll();
                  QString dataPoint = QString::fromStdString(data.toStdString());
                  ui->textBrowser->append(dataPoint);
              }
              
              void Widget::on_pushButton_clicked()
              {
                  QString message = ui->lineEdit_2->text();
                  message.append("\n");
                  serialPort.write(message.toUtf8());
              }
              

              When sending one message, I get one data point printed on my textBrowser, but when I try to write multiple requests like this:

              void Widget::on_pushButton_clicked()
              {
                  QString message = ui->lineEdit_2->text();
                  message.append("\n");
                  for (int i = 0; i < 5; i++){
                      serialPort.write(message.toUtf8());
                  }
              }
              

              I still get only one data point printed.
              I managed to get all 5 points by changing the code to this:

              void Widget::on_pushButton_clicked()
              {
                  QString message = ui->lineEdit_2->text();
                  message.append("\n");
                  for (int i = 0; i < 5; i++){
                      serialPort.write(message.toUtf8());
                      serialPort.waitForReadyRead(500);
                  }
              }
              

              But this blocks my program until all the data is received. Is there a way to get the data without waitForReadyRead? I thought I'd need to use threads so the program doesn't get blocked, but from what I read, you're not supposed to use threads since QSerialPort is already async.

              Christian EhrlicherC Online
              Christian EhrlicherC Online
              Christian Ehrlicher
              Lifetime Qt Champion
              wrote on last edited by
              #6

              @ardmn said in Sending and receiving multiple serial signals:

              serialPort.waitForReadyRead(500);

              I still don't understand what you want to read here...

              Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
              Visit the Qt Academy at https://academy.qt.io/catalog

              A 1 Reply Last reply
              0
              • A ardmn

                @Christian-Ehrlicher said in Sending and receiving multiple serial signals:

                You might get more than one 'line' here so you have to properly split it up. serial communication is (like socket communication) a stream - there is no 'line' or something else - you have to implement a protocol on top by yourself.

                Hi, I'm not exactly sure if this is what you mean but I've tried to make a buffer in the read function like this, the device sends a response that ends with \n

                void MainWindow::readData()
                {
                    byteArray += Serial->readAll();
                    if(byteArray.contains("\n")){
                        qDebug() << "received data point" << byteArray;
                        byteArray.clear();
                    }
                }
                

                This didn't solve the problem though, the response I get when I loop the QSerialPort.write function is still:

                sent command: "DATA1"
                sent command: "DATA1"
                sent command: "DATA1"
                sent command: "DATA1"
                sent command: "DATA1"
                received data point "948302\n"
                
                JonBJ Offline
                JonBJ Offline
                JonB
                wrote on last edited by
                #7

                @ardmn said in Sending and receiving multiple serial signals:

                byteArray.clear();

                If there is more than one response read into the buffer you will lose it. Only remove up to first \n for one response leaving rest in buffer, do it in loop (or call again) for multiple messages. I'm not saying you're necessarily in this state, but make code correct/robust.

                1 Reply Last reply
                0
                • Christian EhrlicherC Christian Ehrlicher

                  @ardmn said in Sending and receiving multiple serial signals:

                  serialPort.waitForReadyRead(500);

                  I still don't understand what you want to read here...

                  A Offline
                  A Offline
                  ardmn
                  wrote on last edited by
                  #8

                  @Christian-Ehrlicher said in Sending and receiving multiple serial signals:

                  I still don't understand what you want to read here...

                  Sorry, I'm not that experienced in qt or serial communication, I'll try to explain the problem better.
                  My device is listening for the "DATA1" command, this command returns a data point, which for testing purposes is just a random six digit number plus a newline operator on the end. What I want to do is write, for example, 5 messages containing the "DATA1" command and receive 5 data points, but with the code I have I can only ever get one response containing one data point, no matter how many I write. I'm also not sure why waitForReadyRead works, I was just testing the wait commands to see if anything different would happen.

                  So my question is: Is this kind of repeated writing and receiving possible? I'm trying to find examples but all of them either only read a stream from the device and never send anything, or only send one thing and get one response.

                  @JonB said in Sending and receiving multiple serial signals:

                  @ardmn said in Sending and receiving multiple serial signals:

                  byteArray.clear();

                  If there is more than one response read into the buffer you will lose it. Only remove up to first \n for one response leaving rest in buffer, do it in loop (or call again) for multiple messages. I'm not saying you're necessarily in this state, but make code correct/robust.

                  Ty for the heads up, I will correct the code.

                  Christian EhrlicherC 1 Reply Last reply
                  0
                  • A ardmn

                    @Christian-Ehrlicher said in Sending and receiving multiple serial signals:

                    I still don't understand what you want to read here...

                    Sorry, I'm not that experienced in qt or serial communication, I'll try to explain the problem better.
                    My device is listening for the "DATA1" command, this command returns a data point, which for testing purposes is just a random six digit number plus a newline operator on the end. What I want to do is write, for example, 5 messages containing the "DATA1" command and receive 5 data points, but with the code I have I can only ever get one response containing one data point, no matter how many I write. I'm also not sure why waitForReadyRead works, I was just testing the wait commands to see if anything different would happen.

                    So my question is: Is this kind of repeated writing and receiving possible? I'm trying to find examples but all of them either only read a stream from the device and never send anything, or only send one thing and get one response.

                    @JonB said in Sending and receiving multiple serial signals:

                    @ardmn said in Sending and receiving multiple serial signals:

                    byteArray.clear();

                    If there is more than one response read into the buffer you will lose it. Only remove up to first \n for one response leaving rest in buffer, do it in loop (or call again) for multiple messages. I'm not saying you're necessarily in this state, but make code correct/robust.

                    Ty for the heads up, I will correct the code.

                    Christian EhrlicherC Online
                    Christian EhrlicherC Online
                    Christian Ehrlicher
                    Lifetime Qt Champion
                    wrote on last edited by
                    #9

                    @ardmn said in Sending and receiving multiple serial signals:

                    What I want to do is write, for example, 5 messages containing the "DATA1" command and receive 5 data points

                    Then write one 'DATA1', wait for the response correctly via signals and slots and send the new command when the preivous answers arrived.

                    Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                    Visit the Qt Academy at https://academy.qt.io/catalog

                    A 1 Reply Last reply
                    2
                    • Christian EhrlicherC Christian Ehrlicher

                      @ardmn said in Sending and receiving multiple serial signals:

                      What I want to do is write, for example, 5 messages containing the "DATA1" command and receive 5 data points

                      Then write one 'DATA1', wait for the response correctly via signals and slots and send the new command when the preivous answers arrived.

                      A Offline
                      A Offline
                      ardmn
                      wrote on last edited by
                      #10

                      @Christian-Ehrlicher said in Sending and receiving multiple serial signals:

                      Then write one 'DATA1', wait for the response correctly via signals and slots and send the new command when the preivous answers arrived.

                      Thank you, this is exactly what I want, but I can't wrap my head around how I'd actually do it, I thought my first example would accomplish this but it didn't.
                      If it's not asking too much, could you please provide a pseudocode example of how that would look like? Thanks again for the help.

                      1 Reply Last reply
                      0
                      • A Offline
                        A Offline
                        ardmn
                        wrote on last edited by
                        #11

                        It just clicked in my head that I can just call the write function inside of the slot I'm using for the readyRead() signal, that way it sends another command after the data is received. Can't believe I was racking my brain over something so simple, thanks a lot for the help @Christian-Ehrlicher, @JonB and @Pl45m4!

                        JonBJ 1 Reply Last reply
                        0
                        • A ardmn has marked this topic as solved on
                        • A ardmn

                          It just clicked in my head that I can just call the write function inside of the slot I'm using for the readyRead() signal, that way it sends another command after the data is received. Can't believe I was racking my brain over something so simple, thanks a lot for the help @Christian-Ehrlicher, @JonB and @Pl45m4!

                          JonBJ Offline
                          JonBJ Offline
                          JonB
                          wrote on last edited by JonB
                          #12

                          @ardmn
                          Yes, sorry, didn't get around to saying so, but sounds like you have twigged it. Outline:

                          void Class::onReadyRead()    // slot
                          {
                              this->buffer += serial->readAll();
                              if (!this->buffer.contains("\n")    // still no newline received
                                  return;
                              QString line = this->buffer.removeTo("\n");    // extract to \n, remove from pending buffer
                              // either call what you want to do directly
                              someFunction(line);
                              // or (possibly nicer) emit your own signal to which you have attached some other handling slot
                              emit myLineReceivedSignal(line);
                          }
                          

                          Of course if you are going to call this onReadyRead() slot every time you received from serial port you are (likely) going to want to store some state somewhere which tells you how far through your protocol/message exchange you are so as to know how you want to handle this latest line/message which has arrived.

                          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