Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. Data packet was cut when sending from Arduino Uno to Raspberry Pi 3 in C++

Data packet was cut when sending from Arduino Uno to Raspberry Pi 3 in C++

Scheduled Pinned Locked Moved C / C++ / MFC
hardwarehelpcsharpc++html
6 Posts 4 Posters 0 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
    Ahmad ZULKIPLEE
    wrote on last edited by
    #1

    I hope that someone can help me.

    I am currently working on developing a flight simulator with force feedback. To do the calculations of the force feedback, we need to know the position of vertical yoke that we are using. We use two potentiometers to detect the position of the yoke for roll and pitch. The potentiometers are connected with Arduino Uno that will change analog values to digital values:

    Digital value of roll will be between [450: 650] Digital value of pitch will be between [100: 340] These values then will be sent to Raspberry Pi where we do the calculations of force feedback. I’m using the RS232 protocol (library developed by Teunis van Beelen [link]) to receive the data from Arduino.I'm using a usb cable to send data from Arduino To RPi. I’m developing the code in Qt Creator in C++ My problem: I received the data packets from Arduino every 10ms, BUT, sometimes the packets are cut into two parts (see figure 1). I can say that for every 100 data packets sent, 6 will be cut. So I will receive 6 times incomplete data packets for the calculations. The "incomplete part" will come together with the next data packet. For the time being, if the data was cut, the code will just "jump" the data packet and will not do any calculation. But, for optimisation purpose, I need to resolve this problem. By the way, the baudrate is the same for Arduino and RPi that is 115200. The whole program is being developed in C++, so it is not advisable to use pyserial because the program need to receive and calculate the force feedback within 10ms. [figure1] Can someone explains why and how did these happen? What do I need to do to resolve this problem? My code in Arduino

    int pinpotRoulis=A0; //analog input 0
    int valpotRoulis=0;
    int valmancheRoulis=0;
    int mapRoulis =0;
    int pinpotTangage=A5; //analog input 0
    int valpotTangage=0;
    int valmancheTangage=0;
    int mapTangage =0;
    int voltage = 8;
    void setup() {
    Serial.begin(115200);
    pinMode(voltage,OUTPUT);
    digitalWrite(voltage,HIGH);

    }
    void loop()

    J L L 3 Replies Last reply
    0
    • A Ahmad ZULKIPLEE

      I hope that someone can help me.

      I am currently working on developing a flight simulator with force feedback. To do the calculations of the force feedback, we need to know the position of vertical yoke that we are using. We use two potentiometers to detect the position of the yoke for roll and pitch. The potentiometers are connected with Arduino Uno that will change analog values to digital values:

      Digital value of roll will be between [450: 650] Digital value of pitch will be between [100: 340] These values then will be sent to Raspberry Pi where we do the calculations of force feedback. I’m using the RS232 protocol (library developed by Teunis van Beelen [link]) to receive the data from Arduino.I'm using a usb cable to send data from Arduino To RPi. I’m developing the code in Qt Creator in C++ My problem: I received the data packets from Arduino every 10ms, BUT, sometimes the packets are cut into two parts (see figure 1). I can say that for every 100 data packets sent, 6 will be cut. So I will receive 6 times incomplete data packets for the calculations. The "incomplete part" will come together with the next data packet. For the time being, if the data was cut, the code will just "jump" the data packet and will not do any calculation. But, for optimisation purpose, I need to resolve this problem. By the way, the baudrate is the same for Arduino and RPi that is 115200. The whole program is being developed in C++, so it is not advisable to use pyserial because the program need to receive and calculate the force feedback within 10ms. [figure1] Can someone explains why and how did these happen? What do I need to do to resolve this problem? My code in Arduino

      int pinpotRoulis=A0; //analog input 0
      int valpotRoulis=0;
      int valmancheRoulis=0;
      int mapRoulis =0;
      int pinpotTangage=A5; //analog input 0
      int valpotTangage=0;
      int valmancheTangage=0;
      int mapTangage =0;
      int voltage = 8;
      void setup() {
      Serial.begin(115200);
      pinMode(voltage,OUTPUT);
      digitalWrite(voltage,HIGH);

      }
      void loop()

      J Offline
      J Offline
      Jochen Arndt
      wrote on last edited by
      #2

      The answer is obvious: You have to rewrite your code to be able to handle incomplete packages. You got incomplete packets because you stop receiving if any number of data has been received (even a single byte/character). That would be the normal behaviour. The only reason why that happens not very often is that the system has to service also other tasks. And that is not done while waiting (see end of my post)! Because you are sending only a single kind of data, you can change the data being send using a fixed length format by using leading zeroes:

      sprintf(dataToSend, "R%03dE T%03dE", valpotRoulis, valpotTangage);

      That makes parsing much simpler (e.g. using scanf()) and you can wait for the known number of characters (11 + line feed):

      const int CMD_LENGTH = 12; // Or whatever applies
      while(n < CMD_LENGTH && i < 1000000);

      By the way: what is the purpose of the undefined variable i here? But when doing so you will run more into the already existing performance problem of using a polling loop. Waiting for the data wastes a lot of time (10 ms) that is not available for other tasks. The solution is to put the receiving into an own thread and use the fine Qt signaling features. Because there are only two event data values, there is even no need to use shared variables.

      A 1 Reply Last reply
      0
      • A Ahmad ZULKIPLEE

        I hope that someone can help me.

        I am currently working on developing a flight simulator with force feedback. To do the calculations of the force feedback, we need to know the position of vertical yoke that we are using. We use two potentiometers to detect the position of the yoke for roll and pitch. The potentiometers are connected with Arduino Uno that will change analog values to digital values:

        Digital value of roll will be between [450: 650] Digital value of pitch will be between [100: 340] These values then will be sent to Raspberry Pi where we do the calculations of force feedback. I’m using the RS232 protocol (library developed by Teunis van Beelen [link]) to receive the data from Arduino.I'm using a usb cable to send data from Arduino To RPi. I’m developing the code in Qt Creator in C++ My problem: I received the data packets from Arduino every 10ms, BUT, sometimes the packets are cut into two parts (see figure 1). I can say that for every 100 data packets sent, 6 will be cut. So I will receive 6 times incomplete data packets for the calculations. The "incomplete part" will come together with the next data packet. For the time being, if the data was cut, the code will just "jump" the data packet and will not do any calculation. But, for optimisation purpose, I need to resolve this problem. By the way, the baudrate is the same for Arduino and RPi that is 115200. The whole program is being developed in C++, so it is not advisable to use pyserial because the program need to receive and calculate the force feedback within 10ms. [figure1] Can someone explains why and how did these happen? What do I need to do to resolve this problem? My code in Arduino

        int pinpotRoulis=A0; //analog input 0
        int valpotRoulis=0;
        int valmancheRoulis=0;
        int mapRoulis =0;
        int pinpotTangage=A5; //analog input 0
        int valpotTangage=0;
        int valmancheTangage=0;
        int mapTangage =0;
        int voltage = 8;
        void setup() {
        Serial.begin(115200);
        pinMode(voltage,OUTPUT);
        digitalWrite(voltage,HIGH);

        }
        void loop()

        L Offline
        L Offline
        Lost User
        wrote on last edited by
        #3

        This is a common issue with communication lines. When you read the incoming data you cannot assume that every message will contain everything that was sent from the other end. You need to read however many bytes are presented in a loop, and build the message as you go. How you check for a complete message depends on the protocol you are using.

        1 Reply Last reply
        0
        • J Jochen Arndt

          The answer is obvious: You have to rewrite your code to be able to handle incomplete packages. You got incomplete packets because you stop receiving if any number of data has been received (even a single byte/character). That would be the normal behaviour. The only reason why that happens not very often is that the system has to service also other tasks. And that is not done while waiting (see end of my post)! Because you are sending only a single kind of data, you can change the data being send using a fixed length format by using leading zeroes:

          sprintf(dataToSend, "R%03dE T%03dE", valpotRoulis, valpotTangage);

          That makes parsing much simpler (e.g. using scanf()) and you can wait for the known number of characters (11 + line feed):

          const int CMD_LENGTH = 12; // Or whatever applies
          while(n < CMD_LENGTH && i < 1000000);

          By the way: what is the purpose of the undefined variable i here? But when doing so you will run more into the already existing performance problem of using a polling loop. Waiting for the data wastes a lot of time (10 ms) that is not available for other tasks. The solution is to put the receiving into an own thread and use the fine Qt signaling features. Because there are only two event data values, there is even no need to use shared variables.

          A Offline
          A Offline
          Ahmad ZULKIPLEE
          wrote on last edited by
          #4

          Jochen Arndt wrote:

          That makes parsing much simpler (e.g. using scanf()) and you can wait for the known number of characters (11 + line feed):

          const int CMD_LENGTH = 12; // Or whatever applies
          while(n < CMD_LENGTH && i < 1000000);

          By the way: what is the purpose of the undefined variable i here?

          I don't really understand what you are doing here? Can you please explain it a bit more and detailed? And where do i need to put this code, is it after I received the data from Arduino (after printf to see how many data in the string?). By the way, i just started coding two months ago. I'm sorry if I asked a lot of questions.

          do{
          n = RS232_PollComport(cport_nr, (unsigned char *) str_recv, (int)BUF_SIZE);
          i++;
          }while(n <= 0 && i < 1000000);

                  if(n > 0){
                    str\_recv\[n\] = 0;
                    printf("Received %i bytes: '%s'\\n", n, str\_recv);
          

          Jochen Arndt wrote:

          But when doing so you will run more into the already existing performance problem of using a polling loop. Waiting for the data wastes a lot of time (10 ms) that is not available for other tasks. The solution is to put the receiving into an own thread and use the fine Qt signaling features. Because there are only two event data values, there is even no need to use shared variables.

          Like you said, I would prefer to not use polling because the program needs to be really dynamic(10 ms). When you said "put the receiving into an own thread", do you mean put the received data in another string? I don't really know about the Qt signaling features. I just took a hold in this project two months ago and just started doing Qt 2 weeks ago. Would you give me a link that would help me to understand the features and why and how to use them? Tqvm

          J 1 Reply Last reply
          0
          • A Ahmad ZULKIPLEE

            Jochen Arndt wrote:

            That makes parsing much simpler (e.g. using scanf()) and you can wait for the known number of characters (11 + line feed):

            const int CMD_LENGTH = 12; // Or whatever applies
            while(n < CMD_LENGTH && i < 1000000);

            By the way: what is the purpose of the undefined variable i here?

            I don't really understand what you are doing here? Can you please explain it a bit more and detailed? And where do i need to put this code, is it after I received the data from Arduino (after printf to see how many data in the string?). By the way, i just started coding two months ago. I'm sorry if I asked a lot of questions.

            do{
            n = RS232_PollComport(cport_nr, (unsigned char *) str_recv, (int)BUF_SIZE);
            i++;
            }while(n <= 0 && i < 1000000);

                    if(n > 0){
                      str\_recv\[n\] = 0;
                      printf("Received %i bytes: '%s'\\n", n, str\_recv);
            

            Jochen Arndt wrote:

            But when doing so you will run more into the already existing performance problem of using a polling loop. Waiting for the data wastes a lot of time (10 ms) that is not available for other tasks. The solution is to put the receiving into an own thread and use the fine Qt signaling features. Because there are only two event data values, there is even no need to use shared variables.

            Like you said, I would prefer to not use polling because the program needs to be really dynamic(10 ms). When you said "put the receiving into an own thread", do you mean put the received data in another string? I don't really know about the Qt signaling features. I just took a hold in this project two months ago and just started doing Qt 2 weeks ago. Would you give me a link that would help me to understand the features and why and how to use them? Tqvm

            J Offline
            J Offline
            Jochen Arndt
            wrote on last edited by
            #5

            When you send data with the format "R%03dE T%03dE" it will be of fixed length like in "R450E T030E". The length is 11 characters plus the the line termination appended Serial.println(). Assuming that it appends a single LF and not a CR-LF pair, the length will be 12 bytes. Knowing that you can implement reading until all bytes of a package has been received (untested from scratch):

            const int packetLength = 12;
            int packetRead = 0;
            while (packetRead < packetLength)
            {
            // Append data to buffer
            int read = RS232_PollComport(cport_nr, (unsigned char *)str_recv + packetRead, (int)BUF_SIZE - packetRead);
            // Check for error
            if (read < 0)
            {
            return;
            }
            packetRead += read;
            }
            // Null terminate the buffer so that it can be used with string functions
            // This will replace the trailing LF
            str_recv[packetRead - 1] = 0;
            // Get data from the received string
            char cmd1, cmd2;
            int val1, val2
            sscanf(str_recv, "%c%03dE %c%03dE", &cmd1, &val1, &cmd2, &val2);
            // Handle data here
            if ('R' == cmd1)
            position = val1;
            else
            position = -1;

            An application can be splitted into multiple threads. You typically have the main thread that is doing the user interaction and screen outout (often also called GUI thread) and background threads that perform asnychronous operations like networking or serial communication as in your case. If you execute such polling operations (or calling sleep()) within the main thread that will be blocked for long times resulting in lags and stuttering screen update. Note also the error check in the above code. Without that your application would stuck forever when the serial connection is interrupted by unplugging the cable or switching the Arduino off. The solution is to create a worker thread that receives the data and uses events to signal the main (GUI) thread when new data has been received. The main thread then handles the event and can update the screen with the new data. However, using threads is an advance programming topic so you might proceed with the polling for testing the communication. But sooner or later you would have to use threads. The thread itself can be implemented as pthread or QThread Class | Qt Core 5.10[^]. Inside the worker thread use a QEvent Class | Qt Core 5.10[

            1 Reply Last reply
            0
            • A Ahmad ZULKIPLEE

              I hope that someone can help me.

              I am currently working on developing a flight simulator with force feedback. To do the calculations of the force feedback, we need to know the position of vertical yoke that we are using. We use two potentiometers to detect the position of the yoke for roll and pitch. The potentiometers are connected with Arduino Uno that will change analog values to digital values:

              Digital value of roll will be between [450: 650] Digital value of pitch will be between [100: 340] These values then will be sent to Raspberry Pi where we do the calculations of force feedback. I’m using the RS232 protocol (library developed by Teunis van Beelen [link]) to receive the data from Arduino.I'm using a usb cable to send data from Arduino To RPi. I’m developing the code in Qt Creator in C++ My problem: I received the data packets from Arduino every 10ms, BUT, sometimes the packets are cut into two parts (see figure 1). I can say that for every 100 data packets sent, 6 will be cut. So I will receive 6 times incomplete data packets for the calculations. The "incomplete part" will come together with the next data packet. For the time being, if the data was cut, the code will just "jump" the data packet and will not do any calculation. But, for optimisation purpose, I need to resolve this problem. By the way, the baudrate is the same for Arduino and RPi that is 115200. The whole program is being developed in C++, so it is not advisable to use pyserial because the program need to receive and calculate the force feedback within 10ms. [figure1] Can someone explains why and how did these happen? What do I need to do to resolve this problem? My code in Arduino

              int pinpotRoulis=A0; //analog input 0
              int valpotRoulis=0;
              int valmancheRoulis=0;
              int mapRoulis =0;
              int pinpotTangage=A5; //analog input 0
              int valpotTangage=0;
              int valmancheTangage=0;
              int mapTangage =0;
              int voltage = 8;
              void setup() {
              Serial.begin(115200);
              pinMode(voltage,OUTPUT);
              digitalWrite(voltage,HIGH);

              }
              void loop()

              L Offline
              L Offline
              leon de boer
              wrote on last edited by
              #6

              The problem is simple Serial.println won't necessarily clear the buffer in your small 10ms delay. There is a guaranteed Line Feed character "\n" on the output with this line

              Serial.println(dataToSend);

              So you have a guaranteed packet end marker. On that poll routine you could simply also insert a timeout error handler. However the only basic requirement is the read poll loops keeping all characters it see's before a LF character. At the moment your crazy reading poll runs around a million times instead of just looking for the LF character :-)

              In vino veritas

              1 Reply Last reply
              0
              Reply
              • Reply as topic
              Log in to reply
              • Oldest to Newest
              • Newest to Oldest
              • Most Votes


              • Login

              • Don't have an account? Register

              • Login or register to search.
              • First post
                Last post
              0
              • Categories
              • Recent
              • Tags
              • Popular
              • World
              • Users
              • Groups