Serial communication sync problem

Hi everyone,

I've got a custom sensor system hooked up to one of the serial ports of my Mega. I receive packages of 6 bytes, always starting with 's' to signal the start of a new package. I need some of those bytes for further calculations and I've put together some very simple code that seems to work, however only for a couple of minutes. Then it seems to get out of sync somehow..

Here's my code:

byte data[6];
byte index = 0;


void setup()
{
  Serial1.begin(9600);
}

void loop()
{
  if (Serial1.available()) {
    byte b = Serial1.read();
    if (b == 115) index = 0;  //if byte equals 's' reset index
    data[index] = b;
    index++;
  }

  if (index == 6)  {

    (do some calculations)

    index = 0;
  }
}

The baud rate is correct and I have no access to the sensor system, so I can't alter the packages that are being sent. Could someone please help me make this code more robust so it's more reliable for extended time periods? I'm a bit of a noob when it comes to coding. Thank you very much in advance!

A couple of things:

[glow]int[/glow] b = Serial1.read();
    if (b == [glow]'s'[/glow]) index = 0;

I can't really see why it should get out of sync, except perhaps for noise - is it a very long serial line or near to a source of electrical noise?

You could implement a timeout - if all the characters are sent one after the other, then a timeout of 10 milliseconds started when you get an 's' could reset "index".

How frequent are the data packets?
If you're spending too long doing other stuff ("calculations"), the input buffer could overflow.
If nothing is taking characters out, and the serial line is maxed-out, the buffer will overflow in about 128/960 = 133 milliseconds.

This code resets the index if it sees an s,
However, could it be that there is a byte which corresponds to an s that is 115 in the following bytes. How sure are you that the s is unique.
If there is another byte in the data field with the same value this could be causing your problem.

Try printing out the data bytes and see. Wipe the buffer on each synchronisation to make it stand out.

Thank you for your lightning quick replies.

I will try implementing a timeout and see whether that improves things.

As for the uniqueness of 's', I've watched the data closely on the serial monitor and it's all in the range of 15-60 and comes nowhere near 115. (it involves distance sensors) so I'm pretty sure that shouldn't a problem. I also couldn't detect any noise, the data came through cleanly for minutes in a row.

I am wondering however whether the atmega chip is fast enough to handle all the data.. I receive the packages about 10 times per second (I was actually planning on going much faster) Could that perhaps be a problem?

I receive the packages about 10 times per second

60 characters per second - the serial line is running at 960 characters per second - as long as you don't take longer than about 16ms processing each character, you shouldn't have any problems.

Your code doesn't check for buffer overflow. Always check for this, always always always :wink:

Your code doesn't check for buffer overflow

Yes, it does!

if (index == 6)  {

Thank you all. I've just got a couple of questions for my personal understanding:

Wipe the buffer on each synchronisation to make it stand out.

Noob question: How do I wipe the buffer? Would that involve the Serial.flush() command?

as long as you don't take longer than about 16ms processing each character

Is there a way to check exactly how long it takes?

And finally, if I understand correctly, increasing the baud rate will allow the arduino more time for its calculations and reduce the chances of a buffer overflow. I can easily set the rate of my sensor system to 115k, is this still a safe rate or is this too fast for my arduino? (With some more work I can get other rates as well, so if there's a recommended maximum please let me know)

Re: Wiping the buffer.
I assume Mike meant setting your "buffer" to zero, for example with "memset ((void*)buffer, 0, sizeof (buffer));"

If you increase the line speed, you still have the same amount of time per character to process it - 1/60th second (assuming ten lots of six characters per second) = 16.6ms.

How can you find out how long your processing is taking?
By noting the time at the start and end of the calculation (using "millis" or "micros"), and subtracting.

Ok thank you all for your replies. I think I've found the problem and it was so obvious that nobody even noticed:

I have an array of 6 ints. Since the index starts counting at 0, it should (of course) only count until 5 and then start over. In my code I checked for index == 6, which gave me random information for the last index number. That was probably the cause of the problem, since now that it's changed, it seems to work fine.

slaps himself in the face

Still thanks for all your help.

But you've got a post increment - when the count reaches 6, the buffer is full (it has six elements in it).
As far as the code you posted, that's fine (and you'll see that the matter of buffer overflow was discussed and dismissed), however, if you used that as an index into the array after that, that's your look-out, because you didn't post that part of the code.

I have an array of 6 ints

Not in the example you posted.

Yes you sir are correct. it seems I've posted too soon, as right now it doesn't behave as it should anymore with index == 5.

It was however part of the problem, as the calculations I used involved a for loop that looped until data[6] and therefore used some random data for its calculations. I'm quite positive that that was the real problem.

Sigh, I still have a lot to learn.

I'm sorry for being so vague about the calculations and sensors I'm using, but I'm kinda bound to a non disclosure agreement for my project, which means I can't go into too much detail.

Fortunately, it finally works now so thank you ones again!

edit: and you were right ones again, I'm using an array of 6 bytes, not ints