Java/C# Serial port write to Arduino reading wrong bytes

I have a program I wrote originally in Java that writes to a serial port that I have an arduino pro mini plugged into. Each chunk of data is 6 bytes, and when the arduino receivies the data, it just spits it back out to the console to I can see that. The problem is when the data is spit back out, it is often in the wrong order with some bytes appearing to be sent twice. I wrote the same functionality in c# and the same thing is happening. I wrote some arduino code to write data to itself and echo it back, and that is correct.

So the problem must be my non arduino code, or some hardware settings. In my code, I added a delay after every write that allows the data to stay correct for a while, but it eventually starts getting screwed up.

I tried messing with the baud rate, but it didn’t help. Why could this be happening??

Here’s my arduino code.

#include <SPI.h>

byte data[7];
int DATA_SIZE = 7;
int val = 0;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
 
   
}


void loop() {

  //wait for seven bytes to come
   if (Serial.available() >= DATA_SIZE) {
        /* read the most recent byte */
       Serial.readBytes(data,sizeof(data));
       Serial.print("Data: ");
        
        for(int i = 0; i < DATA_SIZE; i++)
        {
            Serial.print((int)data[i], DEC);
            Serial.print(" ");
         }
    
         Serial.println();
        // nrf24.send(data, sizeof(data));
    }
  
}

Moderator edit: CODE TAGS {sob}

The examples in serial input basics are simple reliable ways to receive data. If you want to ensure the correct order you need to read all the data before you send any of it back.

And always post a complete program, not snippets that have things such as DATA_SIZE in them that we have no idea about.

...R

We would also need to see the sending code. If you are sending 6 bytes and a carriage return and line feed, and expecting 6 bytes, that would be a problem.

Also, if you are sending data faster than you are reading it, data could get discarded. You've provided about 10% of the information needed to help you.

Are you using 9600 baud perchance? That's pretty slow and would mean longer sending delays might be needed.

In general if you send without waiting for the reply you risk over-running the serial buffers. Make the sending side wait for the newline in the response before sending the next line.

Updated first post to include whole code. I even changed the code to grab all bytes at once and then printing everything.

The input is coming from a java program I wrote and writing to the serial port. I'm literally making a byte array of 7 bytes, so I don't expect extra characters.

MarkT: Are you using 9600 baud perchance? That's pretty slow and would mean longer sending delays might be needed.

In general if you send without waiting for the reply you risk over-running the serial buffers. Make the sending side wait for the newline in the response before sending the next line.

What do you mean wait for a new line in response?

You should have some means for the Arduino to know when the data starts and when it ends. If you look at the 3rd example in serial input basics you will see that it uses < and > as markers. The 2nd example just uses an end-marker (a newline character is commonly used) so the assumption is that it acts as the end marker for one message and the start marker for the next message.

If you don’t have any marker there is a real risk that the Arduino will get out of sync and will assume that a message consists of (say) bytes 5 6 7 1 2 3 4 - mixing up 2 messages.

…R

kpn2652:
What do you mean wait for a new line in response?

kpn2652:
What do you mean wait for a new line in response?

The way you are doing this is not the best choice IMHO.

The problem is you are delimiting the data by size. If for some reason it gets out of sync i.e. dropped character, line noise, it will never sync again. If this is going to be a program that reads data for hours like home control or over the internet, it will not function right after it loses sync until it is rebooted.

To be a little more robust, it should have something that checks for a key pressed or some other non numeric character i.e. [@,!,$.%].

To be even better you should have some type of error detection and recovery. Right now seems like a good time to add it since you are having problems. Something like send the bytes followed by the sum of the bytes sent is SOP. i.e. if you sent 1 2 3 4 5 6 the actual data should be 1 2 3 4 5 6 21.

For debugging, the Arduino side should print all the data and the problem it had with the data i.e. “Data frame checksum failed” while you are debugging.

Depending on your application, you may want the data frame to have some kind of time limit on it where the Arduino flushes the buffer if it doesn’t hear from the sender during an expected response time.

Robin2:
You should have some means for the Arduino to know when the data starts and when it ends. If you look at the 3rd example in serial input basics you will see that it uses < and > as markers. The 2nd example just uses an end-marker (a newline character is commonly used) so the assumption is that it acts as the end marker for one message and the start marker for the next message.

If you don’t have any marker there is a real risk that the Arduino will get out of sync and will assume that a message consists of (say) bytes 5 6 7 1 2 3 4 - mixing up 2 messages.

…R

But I’m always waiting for Serial.available() to be larger than 7. Can what you said still happen?

ricortes:
The way you are doing this is not the best choice IMHO.

The problem is you are delimiting the data by size. If for some reason it gets out of sync i.e. dropped character, line noise, it will never sync again. If this is going to be a program that reads data for hours like home control or over the internet, it will not function right after it loses sync until it is rebooted.

To be a little more robust, it should have something that checks for a key pressed or some other non numeric character i.e. [@,!,$.%].

To be even better you should have some type of error detection and recovery. Right now seems like a good time to add it since you are having problems. Something like send the bytes followed by the sum of the bytes sent is SOP. i.e. if you sent 1 2 3 4 5 6 the actual data should be 1 2 3 4 5 6 21.

For debugging, the Arduino side should print all the data and the problem it had with the data i.e. “Data frame checksum failed” while you are debugging.

Depending on your application, you may want the data frame to have some kind of time limit on it where the Arduino flushes the buffer if it doesn’t hear from the sender during an expected response time.

I understand, but even if I do do this, it doesn’t actually fix anything does it? It just allows me to check if the data de-synced.

kpn2652:
But I’m always waiting for Serial.available() to be larger than 7. Can what you said still happen?

Yes, because you have no way of knowing where the count to 7 starts. Remember that code arrives in the serial input buffer very slowly by Arduino standards.

This is one of those things that you will get away with for 3 days and when you want to show your pride and joy to your Wife/Boyfriend/Mother/Father it will break. I am always impressed by how easily people who know nothing about computers can cause my code to fail.

…R

Updated first post to include whole code.

Well, forget any input from me. That was NOT what you were supposed to do. You are supposed to add the code in a reply. Changing the original post makes anyone that comments on it look like an idiot.

Simple example of delimiting the data packet with a comma to keep the appropriate bytes together.

//zoomkat 3-5-12 simple delimited ',' string  
//from serial port input (via serial monitor)
//and print result out serial port

String readString;

void setup() {
  Serial.begin(9600);
  Serial.println("serial delimit test 1.0"); // so I can keep track of what is loaded
}

void loop() {

  //expect a string like wer,qwe rty,123 456,hyre kjhg,
  //or like hello world,who are you?,bye!,
  
  if (Serial.available())  {
    char c = Serial.read();  //gets one byte from serial buffer
    if (c == ',') {
      //do stuff
      Serial.println(readString); //prints string to serial port out
      readString=""; //clears variable for new input      
     }  
    else {     
      readString += c; //makes the string readString
    }
  }
}

Public forum so I’m in nag mode! It is kind of important to use/advocate good programming practices. :slight_smile:

Eventually you will want the program to be as fail safe as possible. Robin and zoomkat are giving you good advice<and code!> that will make your results much more satisfactory. I mean even for little stuff others may snip out of your code and use it for turning on the lights while they go on vacation or feeding the cat.

There’s been a ton of stuff learned over the last 30 years or so. More smarts in your java side would help too. For instance, the Arduino should be able to request a new packet from the sender if it receives a bad one OR have something like drop dead code should it lose sync or connection. Most new cars with electronic ignitions do something like this for when there is sensor failure. Rather then just dump you in the middle of the road, they just use a best guess fallback position that is good enough to get you to an off ramp. The handshaking doesn’t have to be that complicated, just ACKowlege, NegativeACkowlege, with checksum. Xmodem file transfer is a good example and it is well documented.