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. Write ASCII Character and read response using serialport

Write ASCII Character and read response using serialport

Scheduled Pinned Locked Moved Solved General and Desktop
15 Posts 3 Posters 2.0k 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.
  • H Offline
    H Offline
    H.dragon
    wrote on 23 Jul 2020, 07:58 last edited by
    #1

    capture.png
    Hi. I'm making GUI which displays encoder's position on the QTextBrowser. I communicate with my device through serialport, So I use QSerialport.
    The picture I attach is the some parts of the document.

    class MotorPort : public QSerialPort
    /// this is my MotorPort class.
    void MotorPort::openMotorPort(const QString &portName)
    {
        setPortName(portName);
        setBaudRate(defaultBaudRate);
        setDataBits(defaultDataBits);
        setStopBits(defaultStopBits);
        setParity(defaultParity);
        open(QIODevice::ReadWrite);
    
    }
    

    based on this I wrote code like below.

    /// In MainWindow.h
    MotorPort *rls;
    /// In MainWindow.cpp
    rls->openMotorPort("COM5"); //I Checked my PC and device are connected!
    
    rls->write(//something//);
    QByteArray data = rls-> readAll();
    
    ui->statusencoder->setText(QString(data)); //statusencoder is QTextBrowser
    
    

    The problem is I don't know what to put in the rls->write(). I try to make code like this one, but It doesn't work.

    char ch1(63); //63 means "?" in ASCII table.
    rls->write(&ch1);
    

    Can you let me know how to send ASCII character? Also, Is QByteArray data = rls-> readAll(); enough to read the response?

    Thank you

    1 Reply Last reply
    0
    • M Offline
      M Offline
      mrjj
      Lifetime Qt Champion
      wrote on 23 Jul 2020, 08:13 last edited by
      #2

      Hi

      You can use
      QByteArray buffer = "?";
      serial->write(buffer);

      • rls-> readAll(); enough to read the response?

      No, not always. You should read until you see CR ( as shown in your table)

      Also you cant just call it. you normally use the signal QSerialPort::readyRead and then call readall()
      More than one signal might come.

      So not sure you are using it correctly.

      1 Reply Last reply
      5
      • S Offline
        S Offline
        SGaist
        Lifetime Qt Champion
        wrote on 23 Jul 2020, 11:13 last edited by
        #3

        Hi,

        In addition to @mrjj, you should always check that the QSerialPort open method returned successfully. You may be using the correct port name but not have access to the device for different reasons.

        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
        3
        • H Offline
          H Offline
          H.dragon
          wrote on 25 Jul 2020, 07:50 last edited by H.dragon
          #4

          Sorry for the late reply.
          After reading @mrjj 's answer, I added readyRead.

          // Constructor
          MotorPort::MotorPort(QSerialPort* parent) : QSerialPort(parent)
          {
              // Connect signals to slots.
              connect(this, SIGNAL(readyRead()), this, SLOT(getData()));
          
              // Default port connection parameters.
          
              defaultBaudRate = QSerialPort::Baud9600;
              defaultDataBits = QSerialPort::Data8;
              defaultStopBits = QSerialPort::OneStop;
              defaultParity   = QSerialPort::NoParity;
          
          }
          
          // Destructor
          MotorPort::~MotorPort()
          {
          
          }
          
          bool MotorPort::openMotorPort(const QString &portName)
          {
              setPortName(portName);
              setBaudRate(defaultBaudRate);
              setDataBits(defaultDataBits);
              setStopBits(defaultStopBits);
              setParity(defaultParity);
              bool openning;
              opening = open(QIODevice::ReadWrite);
              return openning;
          }
          
          void MotorPort::getData()
          {
              Output = QIODevice::readAll(); // Output(QByteArray) is private member of MotorPort
          }
          
          QByteArray MotorPort::getresponse()
          {
              QByteArray buffer = "?";
              write(buffer);
              getData();
              return Output;
          }
          

          and in mainwindow.cpp

          bool open = rls->openMotorPort("COM5");
          if (open==true)
          {
              ui->statusencoder->append("success");
              QByteArray data=rls->getresponse();
              ui->statusencoder->append(QString(data));
              int array[10]; //I tried to choose return value type as int
              for (int i=0;i<10;i++)
               {
                      array[i]=7;
                      ui->statusencoder->append(QString::number(array[i]));
                      array[i]=data[i];
                      ui->statusencoder->append(QString::number(array[i]));
                }
          
          }
          

          After running this code, My QTextBrowser(statusencoder) shows like this one

          success
          
          7
          0
          7
          0
          7
          0
          7
          0
          7
          0
          7
          0
          7
          0
          7
          0
          7
          0
          7
          0
          

          the reference software says encoder's position is 3.032mm. so I expect any different value. but QByteArray data seems to be NULL. Am I still making code wrong?

          1 Reply Last reply
          0
          • M Offline
            M Offline
            mrjj
            Lifetime Qt Champion
            wrote on 25 Jul 2020, 08:25 last edited by mrjj
            #5

            Hi
            Its asynchronous so i think the issue lies here

            QByteArray MotorPort::getresponse()
            {
                QByteArray buffer = "?";
                write(buffer); // send 
                getData();// you just call it so might be nothing to read yet.  its not called by serialport due to incoming data
                return Output;
            }
            

            So you cant really do it this way. it has to be like this

            You send something
            Serialport issues one or more readyRead signals
            in getData you read and append to a buffer

            Output += QIODevice::readAll(); // note the plus

            then when data contains a CR, we know you got full set.
            Then you can send signal to mainWindow that data is ready.
            and it that slot in main window, you can then use the data.

            I know it seems a bit complicated but thats how async programming is.

            If you really find it hard to get work, you can use the blocking api of QSrialport
            https://doc.qt.io/qt-5/qtserialport-creadersync-example.html

            But do note that this LAGS the GUI. gui will not redraw etc while code is running and that is
            why the async way with signal and slot is preferred.

            H 1 Reply Last reply 25 Jul 2020, 10:13
            5
            • M mrjj
              25 Jul 2020, 08:25

              Hi
              Its asynchronous so i think the issue lies here

              QByteArray MotorPort::getresponse()
              {
                  QByteArray buffer = "?";
                  write(buffer); // send 
                  getData();// you just call it so might be nothing to read yet.  its not called by serialport due to incoming data
                  return Output;
              }
              

              So you cant really do it this way. it has to be like this

              You send something
              Serialport issues one or more readyRead signals
              in getData you read and append to a buffer

              Output += QIODevice::readAll(); // note the plus

              then when data contains a CR, we know you got full set.
              Then you can send signal to mainWindow that data is ready.
              and it that slot in main window, you can then use the data.

              I know it seems a bit complicated but thats how async programming is.

              If you really find it hard to get work, you can use the blocking api of QSrialport
              https://doc.qt.io/qt-5/qtserialport-creadersync-example.html

              But do note that this LAGS the GUI. gui will not redraw etc while code is running and that is
              why the async way with signal and slot is preferred.

              H Offline
              H Offline
              H.dragon
              wrote on 25 Jul 2020, 10:13 last edited by
              #6

              @mrjj
              Hi. I read your answer but It is a little difficult for me to understand the concept of asynchronous, I googled it and some functions, I changed MotorPort::getresponse() like below. then it works

              QByteArray MotorPort::getresponse()
              {
                  QByteArray buffer = "?";
                  write(buffer);
                  waitForReadyRead(500);
                  return Output;
              }
              

              Is this the solution of your answer? Actually I don't think I fully understood your answer.
              Anyway, Thank you mrjj!

              M 1 Reply Last reply 25 Jul 2020, 10:24
              1
              • H H.dragon
                25 Jul 2020, 10:13

                @mrjj
                Hi. I read your answer but It is a little difficult for me to understand the concept of asynchronous, I googled it and some functions, I changed MotorPort::getresponse() like below. then it works

                QByteArray MotorPort::getresponse()
                {
                    QByteArray buffer = "?";
                    write(buffer);
                    waitForReadyRead(500);
                    return Output;
                }
                

                Is this the solution of your answer? Actually I don't think I fully understood your answer.
                Anyway, Thank you mrjj!

                M Offline
                M Offline
                mrjj
                Lifetime Qt Champion
                wrote on 25 Jul 2020, 10:24 last edited by
                #7

                @H-dragon
                Hi
                asynchronous means it will happen at another point in time (than right now) and yes it can be
                difficult to handle.

                You used the blocking call
                waitForReadyRead(500);
                so yes that was what i meant in the second part of the answer.
                Even now you kinda mix sync and async but it seems that it fires in right order
                so it works :)

                1 Reply Last reply
                3
                • H Offline
                  H Offline
                  H.dragon
                  wrote on 27 Jul 2020, 06:30 last edited by H.dragon
                  #8

                  @mrjj
                  HI.
                  Can I ask you one last question?

                  QByteArray MotorPort::getresponse()
                  {
                      QByteArray buffer = "?";
                      write(buffer);
                      waitForReadyRead(500);
                      return Output;
                  }
                  

                  How the private member Output gets some data from serialport when I call the function getresponse(), although there isnt the function getData()? As I know, the waitForReadyRead(500) blocks the cell until new data is available.
                  Is that because I connected signal to slots? (connect(this, SIGNAL(readyRead()), this, SLOT(getData()));)
                  Thank you for your continued kindness :)

                  M 1 Reply Last reply 27 Jul 2020, 06:58
                  0
                  • H H.dragon
                    27 Jul 2020, 06:30

                    @mrjj
                    HI.
                    Can I ask you one last question?

                    QByteArray MotorPort::getresponse()
                    {
                        QByteArray buffer = "?";
                        write(buffer);
                        waitForReadyRead(500);
                        return Output;
                    }
                    

                    How the private member Output gets some data from serialport when I call the function getresponse(), although there isnt the function getData()? As I know, the waitForReadyRead(500) blocks the cell until new data is available.
                    Is that because I connected signal to slots? (connect(this, SIGNAL(readyRead()), this, SLOT(getData()));)
                    Thank you for your continued kindness :)

                    M Offline
                    M Offline
                    mrjj
                    Lifetime Qt Champion
                    wrote on 27 Jul 2020, 06:58 last edited by
                    #9

                    @H-dragon
                    Hi
                    Yes its due to the readyRead signal calling getData() and fill Output.
                    So we kinda mixed async and sync calls.
                    But docs says
                    "This function blocks until new data is available for reading and the readyRead() signal has been emitted. "
                    https://doc.qt.io/qt-5/qserialport.html#waitForReadyRead

                    so it does come in right order and then it worked.

                    1 Reply Last reply
                    4
                    • H Offline
                      H Offline
                      H.dragon
                      wrote on 4 Aug 2020, 06:35 last edited by
                      #10

                      @mrjj
                      Hi. Thanks to you, I completed my GUI work. I really appreciate it.
                      But while writing codes, I came up with a question.
                      In your second answer, you changed Output = QIODevice::readAll() to Output += QIODevice::readAll().
                      Can you explain why the former doesn't work(my gui terminate)? is it related with asynchronous?

                      M 1 Reply Last reply 4 Aug 2020, 06:46
                      0
                      • H H.dragon
                        4 Aug 2020, 06:35

                        @mrjj
                        Hi. Thanks to you, I completed my GUI work. I really appreciate it.
                        But while writing codes, I came up with a question.
                        In your second answer, you changed Output = QIODevice::readAll() to Output += QIODevice::readAll().
                        Can you explain why the former doesn't work(my gui terminate)? is it related with asynchronous?

                        M Offline
                        M Offline
                        mrjj
                        Lifetime Qt Champion
                        wrote on 4 Aug 2020, 06:46 last edited by mrjj 8 Apr 2020, 07:02
                        #11

                        Hi
                        Good to hear
                        Well there is only a small difference

                        This overwrites all that already is in Output
                        Output = QIODevice::readAll()

                        This Adds to what is already is in Output
                        Output += QIODevice::readAll().

                        The last is the best due to the following reason.

                        When you sent something big enough over serial - it will result in multiple pieces of data
                        so the readyRead() will trigger more than one time.

                        So in such cases,
                        one has to add the incoming data to a buffer as to collect it all

                        • before using it.
                          and that is what
                          Output += QIODevice::readAll().
                          does. Add data to the Output buffer.

                        So that is something to keep in mind.

                        1 Reply Last reply
                        3
                        • H Offline
                          H Offline
                          H.dragon
                          wrote on 4 Aug 2020, 08:04 last edited by
                          #12

                          @mrjj
                          Do I understand well?
                          for example, let's say something big data (123456789) is divided into multiple pieces(123, 456, 789).

                          If I use Output = QIODevice::readAll(), it can cause follow situation
                          readyRead()
                          Output is 123
                          readyRead()
                          Output is 456
                          readyRead()
                          Output is 789

                          but when I use Output+=QIODevice::readAll(),
                          readyRead()
                          Output is 123
                          readyRead()
                          Output is 123456
                          readyRead()
                          Output is 123456789

                          The reason += is the best is It can prevent the former situation. right?

                          M 1 Reply Last reply 4 Aug 2020, 09:56
                          0
                          • H H.dragon
                            4 Aug 2020, 08:04

                            @mrjj
                            Do I understand well?
                            for example, let's say something big data (123456789) is divided into multiple pieces(123, 456, 789).

                            If I use Output = QIODevice::readAll(), it can cause follow situation
                            readyRead()
                            Output is 123
                            readyRead()
                            Output is 456
                            readyRead()
                            Output is 789

                            but when I use Output+=QIODevice::readAll(),
                            readyRead()
                            Output is 123
                            readyRead()
                            Output is 123456
                            readyRead()
                            Output is 123456789

                            The reason += is the best is It can prevent the former situation. right?

                            M Offline
                            M Offline
                            mrjj
                            Lifetime Qt Champion
                            wrote on 4 Aug 2020, 09:56 last edited by
                            #13

                            @H-dragon
                            Hi
                            Yes that is exactly like that.

                            When it will be broken up depends on the hardware. some have bigger buffers than others and
                            so on but it does happen.

                            H 1 Reply Last reply 6 Aug 2020, 05:55
                            1
                            • M mrjj
                              4 Aug 2020, 09:56

                              @H-dragon
                              Hi
                              Yes that is exactly like that.

                              When it will be broken up depends on the hardware. some have bigger buffers than others and
                              so on but it does happen.

                              H Offline
                              H Offline
                              H.dragon
                              wrote on 6 Aug 2020, 05:55 last edited by
                              #14

                              Thanks!!

                              M 1 Reply Last reply 6 Aug 2020, 06:03
                              1
                              • H H.dragon
                                6 Aug 2020, 05:55

                                Thanks!!

                                M Offline
                                M Offline
                                mrjj
                                Lifetime Qt Champion
                                wrote on 6 Aug 2020, 06:03 last edited by
                                #15

                                @H-dragon

                                Np.

                                In your concrete use case, all feedback from the hardware ends with CR
                                so its easy to spot when you have read all data.

                                In other cases one has to look at size to know if
                                all has been read.

                                1 Reply Last reply
                                1

                                • Login

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