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. read data from serial port
Forum Updated to NodeBB v4.3 + New Features

read data from serial port

Scheduled Pinned Locked Moved Solved General and Desktop
29 Posts 4 Posters 5.8k 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.
  • JonBJ Online
    JonBJ Online
    JonB
    wrote on last edited by JonB
    #18

    Now, going back to where @isan wrote:

    return :
     \n191", "2018/8/3", "23:28:55 \r\n187", "2018/8/3", "23:28:55 \r\n185", "2018/8/3", "23:28:55 \r\n164", "2018/8/3", "23:28:55 \r\n131", "2018/8/3", "23:28:55 \r\n103", "2018/8/3", "23:28:55 \r\n....................................
    

    So if that's really right, after first splitting on "\r\n" (not even certain about that if the input really starts as shown with just \n and not \r\n, I'll just assume it's really \r\n), he then needs to split on "\",\"", not just plain ,. Then at the end of that you have 3 clean tokens per line.

    I have to say the input looks a bit oddly tokenized/quoted, but that's what corresponds to the input he shows. If you're not careful and leave " characters in, you'll get toInt() returning 0 where you don't expect.

    mrjjM 1 Reply Last reply
    2
    • JonBJ JonB

      Now, going back to where @isan wrote:

      return :
       \n191", "2018/8/3", "23:28:55 \r\n187", "2018/8/3", "23:28:55 \r\n185", "2018/8/3", "23:28:55 \r\n164", "2018/8/3", "23:28:55 \r\n131", "2018/8/3", "23:28:55 \r\n103", "2018/8/3", "23:28:55 \r\n....................................
      

      So if that's really right, after first splitting on "\r\n" (not even certain about that if the input really starts as shown with just \n and not \r\n, I'll just assume it's really \r\n), he then needs to split on "\",\"", not just plain ,. Then at the end of that you have 3 clean tokens per line.

      I have to say the input looks a bit oddly tokenized/quoted, but that's what corresponds to the input he shows. If you're not careful and leave " characters in, you'll get toInt() returning 0 where you don't expect.

      mrjjM Offline
      mrjjM Offline
      mrjj
      Lifetime Qt Champion
      wrote on last edited by
      #19

      @JonB
      Hi
      I think the "s comes from qDebug and is not in the input. (looking at the sending code higher up)
      It seems he reads the entire load in one go and closes port so that means he should be able to
      read complete string and then split it. ( i hope )

      1 Reply Last reply
      2
      • mrjjM mrjj

        @isan
        Looking at the code, it seems to me you
        send al data and thread will read it all. and then close serial.
        so

        while (serialDataAvail(fd) > -2) {
          //-------value format is int-------
          value = serialGetchar (fd) ;
          //--------vs format is QString------
          vs.push_back(value);  
         }
         serialClose(fd);
         
         // here u should have complete data and can use 
        to get the values if data is complete
        input would be vs
        
          QStringList lines = input.split("\\n\\r");
          for ( const QString& line : lines) {
            QStringList values = line.split(",");
            for ( const QString& valline : values ) {
              qDebug() << "val =" << valline.trimmed().toInt();
            }
          }
        }
        
        I Offline
        I Offline
        isan
        wrote on last edited by isan
        #20

        @mrjj said in read data from serial port:

        @isan
        Looking at the code, it seems to me you
        send al data and thread will read it all. and then close serial.
        so

        while (serialDataAvail(fd) > -2) {
          //-------value format is int-------
          value = serialGetchar (fd) ;
          //--------vs format is QString------
          vs.push_back(value);  
         }
         serialClose(fd);
         
         // here u should have complete data and can use 
        to get the values if data is complete
        input would be vs
        
          QStringList lines = input.split("\\n\\r");
          for ( const QString& line : lines) {
            QStringList values = line.split(",");
            for ( const QString& valline : values ) {
              qDebug() << "val =" << valline.trimmed().toInt();
            }
          }
        }
        

        Data is always sent and It does not go out of while() and I can not wait for complete data
        Upon receive, I must use the data in other classes
        I should not miss any data, if I close the port, the data will be lost

        mrjjM 1 Reply Last reply
        0
        • I isan

          @mrjj said in read data from serial port:

          @isan
          Looking at the code, it seems to me you
          send al data and thread will read it all. and then close serial.
          so

          while (serialDataAvail(fd) > -2) {
            //-------value format is int-------
            value = serialGetchar (fd) ;
            //--------vs format is QString------
            vs.push_back(value);  
           }
           serialClose(fd);
           
           // here u should have complete data and can use 
          to get the values if data is complete
          input would be vs
          
            QStringList lines = input.split("\\n\\r");
            for ( const QString& line : lines) {
              QStringList values = line.split(",");
              for ( const QString& valline : values ) {
                qDebug() << "val =" << valline.trimmed().toInt();
              }
            }
          }
          

          Data is always sent and It does not go out of while() and I can not wait for complete data
          Upon receive, I must use the data in other classes
          I should not miss any data, if I close the port, the data will be lost

          mrjjM Offline
          mrjjM Offline
          mrjj
          Lifetime Qt Champion
          wrote on last edited by
          #21

          @isan
          ok so it must be on the fly.

          Then you need to use 2 buffers as not to parse already received data over and over.
          so in pseudo code

          Read char from serial
          tempbuffer += char
          if char is \n then
          split tempbuffer
          emit value
          clear tempbuffer

          //i assume u want to store all ?
          Mainbuffer +=char

          I 1 Reply Last reply
          1
          • mrjjM mrjj

            @isan
            ok so it must be on the fly.

            Then you need to use 2 buffers as not to parse already received data over and over.
            so in pseudo code

            Read char from serial
            tempbuffer += char
            if char is \n then
            split tempbuffer
            emit value
            clear tempbuffer

            //i assume u want to store all ?
            Mainbuffer +=char

            I Offline
            I Offline
            isan
            wrote on last edited by isan
            #22

            @mrjj so the code is like:

            void MyThread::run()
            {
            
                qDebug("Thread id inside run %d",(int)QThread::currentThreadId());
            
                int fd ,x;
                
                  
                if ((fd = serialOpen ("/dev/ttyACM0",230400)) < 0)
                {
                    fprintf (stderr, "Unable to open serial device: %s\n", strerror (errno)) ;
                }
            
                while (serialDataAvail(fd)>-2)
                {
                     //-------value format is int -------//
                    value=serialGetchar (fd) ;
                 //--------vs format is QString------//
                     vs.push_back(value);
                //--------tempbuffer format is QString------//
               tempbuffer .append( vs);
               if (vs=="\n")
              //-------- values format is QStringList------//
                 values = tempbuffer.split(",");
                  x= values[0].toInt();
             msleep(1); 
                   emit signalValueUpdated(x);
                   tempbuffer.clear();
              
                }
                serialClose(fd); 
            }
            

            is it true?

            mrjjM 1 Reply Last reply
            0
            • I isan

              @mrjj so the code is like:

              void MyThread::run()
              {
              
                  qDebug("Thread id inside run %d",(int)QThread::currentThreadId());
              
                  int fd ,x;
                  
                    
                  if ((fd = serialOpen ("/dev/ttyACM0",230400)) < 0)
                  {
                      fprintf (stderr, "Unable to open serial device: %s\n", strerror (errno)) ;
                  }
              
                  while (serialDataAvail(fd)>-2)
                  {
                       //-------value format is int -------//
                      value=serialGetchar (fd) ;
                   //--------vs format is QString------//
                       vs.push_back(value);
                  //--------tempbuffer format is QString------//
                 tempbuffer .append( vs);
                 if (vs=="\n")
                //-------- values format is QStringList------//
                   values = tempbuffer.split(",");
                    x= values[0].toInt();
               msleep(1); 
                     emit signalValueUpdated(x);
                     tempbuffer.clear();
                
                  }
                  serialClose(fd); 
              }
              

              is it true?

              mrjjM Offline
              mrjjM Offline
              mrjj
              Lifetime Qt Champion
              wrote on last edited by mrjj
              #23

              @isan
              Hi
              Almost, you need to clear tempbuffer as soon as you have used it.
              And u need to check last read char (value) being the \n

              void MyThread::run() {
              
                qDebug("Thread id inside run %d", (int)QThread::currentThreadId());
              
                int fd, x=0;
              
              
                if ((fd = serialOpen ("/dev/ttyACM0", 230400)) < 0) {
                  fprintf (stderr, "Unable to open serial device: %s\n", strerror (errno)) ;
                }
              
                while (serialDataAvail(fd) > -2) {
                  value = serialGetchar (fd) ;
                  vs.push_back(value);
                  tempbuffer += value;
                  if (value == '\n') {
                    values = tempbuffer.split(",");
                    x = values[0].toInt();
                    tempbuffer.clear();
                  }
                  msleep(1);
                  emit signalValueUpdated(x);
                  
              
                }
                serialClose(fd);
              }
              
              JonBJ 1 Reply Last reply
              1
              • mrjjM mrjj

                @isan
                Hi
                Almost, you need to clear tempbuffer as soon as you have used it.
                And u need to check last read char (value) being the \n

                void MyThread::run() {
                
                  qDebug("Thread id inside run %d", (int)QThread::currentThreadId());
                
                  int fd, x=0;
                
                
                  if ((fd = serialOpen ("/dev/ttyACM0", 230400)) < 0) {
                    fprintf (stderr, "Unable to open serial device: %s\n", strerror (errno)) ;
                  }
                
                  while (serialDataAvail(fd) > -2) {
                    value = serialGetchar (fd) ;
                    vs.push_back(value);
                    tempbuffer += value;
                    if (value == '\n') {
                      values = tempbuffer.split(",");
                      x = values[0].toInt();
                      tempbuffer.clear();
                    }
                    msleep(1);
                    emit signalValueUpdated(x);
                    
                
                  }
                  serialClose(fd);
                }
                
                JonBJ Online
                JonBJ Online
                JonB
                wrote on last edited by JonB
                #24

                @mrjj , @isan
                This code looks wrong. It doesn't help that we don't see the declarations of vs or tempbuffer. Comment:

                //--------tempbuffer format is QStringList------//

                No, it isn't, because later you go tempbuffer.split(",");. So it's probably a QString.

                Then: you read 1 char, you append it to vs. Then you append vs to tempbuffer. If value is not \n, you pick up the next char, append that to vs (now 2 chars long), append that to tempBuffer (now 3 chars long)...

                Hmm, vs must be a single char, not a QString like the comment says it is? Who knows....

                Separate issue:

                while (serialDataAvail(fd)>-2)
                

                Nope. serialDataAvail(fd) returns -1 on error. The code accepts that as a legal. It also should therefore never exit the while loop. Further, if 0 bytes are available code goes into the value=serialGetchar (fd) call. After 10 seconds of no data that will return -1. At which point accepts that as the legal char received. Finally, if error opening device in the first place, the code writes a message and then continues into the loop, which makes no sense.

                All this code really needs correcting....

                Finally, have a think about the fact that sometimes you are using Qt & C++ functions, sometimes you are doing lowest-level C library calls. Do you really need to mix them?

                mrjjM 1 Reply Last reply
                2
                • JonBJ JonB

                  @mrjj , @isan
                  This code looks wrong. It doesn't help that we don't see the declarations of vs or tempbuffer. Comment:

                  //--------tempbuffer format is QStringList------//

                  No, it isn't, because later you go tempbuffer.split(",");. So it's probably a QString.

                  Then: you read 1 char, you append it to vs. Then you append vs to tempbuffer. If value is not \n, you pick up the next char, append that to vs (now 2 chars long), append that to tempBuffer (now 3 chars long)...

                  Hmm, vs must be a single char, not a QString like the comment says it is? Who knows....

                  Separate issue:

                  while (serialDataAvail(fd)>-2)
                  

                  Nope. serialDataAvail(fd) returns -1 on error. The code accepts that as a legal. It also should therefore never exit the while loop. Further, if 0 bytes are available code goes into the value=serialGetchar (fd) call. After 10 seconds of no data that will return -1. At which point accepts that as the legal char received. Finally, if error opening device in the first place, the code writes a message and then continues into the loop, which makes no sense.

                  All this code really needs correcting....

                  Finally, have a think about the fact that sometimes you are using Qt & C++ functions, sometimes you are doing lowest-level C library calls. Do you really need to mix them?

                  mrjjM Offline
                  mrjjM Offline
                  mrjj
                  Lifetime Qt Champion
                  wrote on last edited by mrjj
                  #25

                  +@JonB
                  Thx, yes value should be added to tempbuffer.
                  Then i can learn not to edit code in forum directly :)
                  So something like this + all than @JonB said

                  while (serialDataAvail(fd) > -2) { // fix condition! 
                      value = serialGetchar (fd) ;// read char
                      vs.push_back(value); // store in ful buffer
                      tempbuffer += value; // add to tempbuffer
                      if (value == '\n') { // if we just read \n
                        values = tempbuffer.split(","); // split on , to QStringList
                        x = values[0].toInt(); // take first index and convert to int
                        tempbuffer.clear(); // clear it for next 
                      }
                  ......
                  
                  I 1 Reply Last reply
                  1
                  • J.HilkJ Online
                    J.HilkJ Online
                    J.Hilk
                    Moderators
                    wrote on last edited by
                    #26

                    I‘ve been following this thread for a while now, and you guy‘s doing a great job :-)

                    Just one thing that‘s been buging me from the beginning.

                    The call off split on the string. It‘s used for nothing but temporary storage to than turn the first entry into an INT.

                    I would highly recommand to at least use splitref.


                    Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


                    Q: What's that?
                    A: It's blue light.
                    Q: What does it do?
                    A: It turns blue.

                    mrjjM 1 Reply Last reply
                    3
                    • mrjjM mrjj

                      +@JonB
                      Thx, yes value should be added to tempbuffer.
                      Then i can learn not to edit code in forum directly :)
                      So something like this + all than @JonB said

                      while (serialDataAvail(fd) > -2) { // fix condition! 
                          value = serialGetchar (fd) ;// read char
                          vs.push_back(value); // store in ful buffer
                          tempbuffer += value; // add to tempbuffer
                          if (value == '\n') { // if we just read \n
                            values = tempbuffer.split(","); // split on , to QStringList
                            x = values[0].toInt(); // take first index and convert to int
                            tempbuffer.clear(); // clear it for next 
                          }
                      ......
                      
                      I Offline
                      I Offline
                      isan
                      wrote on last edited by isan
                      #27

                      @mrjj Thanks for keep helping to solve my problem
                      It's work!

                      mrjjM 1 Reply Last reply
                      2
                      • I isan

                        @mrjj Thanks for keep helping to solve my problem
                        It's work!

                        mrjjM Offline
                        mrjjM Offline
                        mrjj
                        Lifetime Qt Champion
                        wrote on last edited by
                        #28

                        @isan
                        Super :) \O/

                        1 Reply Last reply
                        0
                        • J.HilkJ J.Hilk

                          I‘ve been following this thread for a while now, and you guy‘s doing a great job :-)

                          Just one thing that‘s been buging me from the beginning.

                          The call off split on the string. It‘s used for nothing but temporary storage to than turn the first entry into an INT.

                          I would highly recommand to at least use splitref.

                          mrjjM Offline
                          mrjjM Offline
                          mrjj
                          Lifetime Qt Champion
                          wrote on last edited by
                          #29

                          @J.Hilk
                          Yes i agree. but in this case we wanted to split very small sample so
                          i decided not to introduce new classes. (QVector/QStringRef)
                          as to focus on getting it running. But yes, much better to use normally as the speed gain is huge for large dataset. (more than i did imagine)

                          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