Data over XBee works for a few seconds then stops...

I have a series1 XBee (http://www.sparkfun.com/products/8664) connected to an ArduIMU (http://www.sparkfun.com/products/9956) which is basically an arduino and a 6DOF board.

I have DIN connected to TX and DOUT connected to RX. I also have 3.3v and ground connected.

On the receiving side I have a USB shield (SparkFun XBee Explorer USB - WRL-11812 - SparkFun Electronics) for the XBee and that's connecting directly to a laptop, which will then receive the data via Max/MSP.

The baud rate for the XBees and Arduino are set to 115200, and the DL address of my transmitting XBee is set to the MY address of the receiving one.

The code I have is working (though I'm tweaking/improving it) and it looks like this:

const int ax = A0;
const int ay = A1;
const int az = A2;
const int gx = A6;
const int gy = A7;
const int gz = A3;

void setup()
{
  Serial.begin(115200);
}

void loop()
{
  Serial.print("2 ax ");
  Serial.print(analogRead(ax));
  Serial.println();
  Serial.print("2 ay ");
  Serial.print(analogRead(ay));
  Serial.println();
  Serial.print("2 az ");
  Serial.println(analogRead(az));
  Serial.println();
  Serial.print("2 gx ");
  Serial.print(analogRead(gx));
  Serial.println();
  Serial.print("2 gy ");
  Serial.print(analogRead(gy));
  Serial.println();
  Serial.print("2 gz ");
  Serial.println(analogRead(gz));
  Serial.println();
}

It's basically a tweaked version of the "VirtualColorMixer" example that comes built-in with the Arduino IDE.

With that code on the Arduino, I get data on my computer just fine, in both Max/MSP and Serial Monitor. Now when I transmit over the XBee I get a short spurt of data (maybe 2-3 seconds) filled with errors (I get a bunch of error messages from my parsing routine in Max/MSP) then it stops working altogether. I also tested it with serial monitor and I get the same thing (a short spurt of data, then nothing).

Is it physically connected right? (only 4 wires from the arduino to the xbee)
Is the data going across too fast or something?

I tried adding a 'delay(40)' at the end of my main loop in case data was going across too fast and it still crapped out (though I want to say it took longer to crap out, but I didn't time it or anything).

Anyone?

I tried adding a 'delay(40)' at the end of my main loop in case data was going across too fast and it still crapped out (though I want to say it took longer to crap out, but I didn't time it or anything).

40 milliseconds may not be enough for the receiver to process all the data received. Try a (much) larger delay (maybe 500 to start with). If that works, slowly lower it until you find a value that works.

So it's that I'm sending too much information?

500ms would be unusably slow (I know that's just an example value), but 40ms is more latency that I'd want as well.

I'm rewriting the code (though your help in another thread) to send binary bytes, instead of the text-based serial.print code posted here, so that would produce much less information per spurt which would hopefully help things overall. (6 sensors, 4bytes per sensor, so 24bytes of data per loop).

Would lowering the baud rate help too? Or is it a matter of generating less information per loop overall?

Would lowering the baud rate help too?

It would hurt. Sending data slower is the opposite of what you want to do.

Or is it a matter of generating less information per loop overall?

It's a matter of not sending data faster than the receiver can handle it. Once the receiver quits acknowledging packets, the sender quits sending. Packets that are not added to the serial buffer are not acknowledged. So, the rate that data can be sent can be no faster than the receiver can read (and process) it,

So the things I can do to improve this are:

Send less data overall (binary bytes)
Add delay to the loop

That's it?

If you want to get the best results, use the CTS pin. Send only when the XBee buffer is not full. :slight_smile:

Isn't the receiver the problem? (So I'm sending too much data, wether or not the sending arduino's buffer is full)

Isn't the receiver the problem? (So I'm sending too much data, wether or not the sending arduino's buffer is full)

Yes, the receiver is the problem. Its receive buffer is overflowing, not the Arduino's buffer. Outgoing data is not (yet) buffered on the Arduino.

You kind of confused me there with the last part.

Relatedly I tried putting together the code for sending binary bytes using serial.write and am getting a compile error I've not seen before.

This code:

Serial.write(0x11, BYTE);
Serial.write(highByte(AccX));
Serial.write(lowByte(AccX));
Serial.write(0x99, BYTE);

Is giving this error:
invalid conversion from 'int' to 'const uint8_t*'

In searching the forum the solution I've seen says to use Serial.print instead of Serial.write, which is a step backwards in terms of sending less data.

I don't know about the BYTE parameter, but if you are trying to send individual bytes, this works for me.
I encoded the letters 'H' into the highByte, and 'I' in the lowByte, the 0x21 is an exclamation point, the last two are the CR-LF.
The array I filled in setup(). It is sent two ways. One as an array (needed typecasting) and count, the other as a zero terminated string.

char outBuf[6];
int AccX = 0x4849;

void setup()
{
  Serial.begin(9600);
  outBuf[0] = 0x48;
  outBuf[1] = 0x49;
  outBuf[2] = 0x21;
  outBuf[3] = 0x0D;
  outBuf[4] = 0x0A;
  outBuf[5] = 0;
}


void loop()
{
  Serial.write("Single\r\n");
  Serial.write(highByte(AccX));
  Serial.write(lowByte(AccX));
  Serial.write(0x21);
  Serial.write(0x0D);
  Serial.write(0x0A);
  delay(1000);
  Serial.write("Count\r\n");
  Serial.write((uint8_t*)outBuf,5);
  delay(1000);
  Serial.write("String\r\n");
  Serial.write(outBuf);
  delay(1000);  
}

Ok, so I've changed it to this:

Serial.write(0x11);
Serial.write(highByte(AccX));
Serial.write(lowByte(AccX));
Serial.write(0x99);

And I don't get any compile errors. I've not tested to see if I'm getting data yet. I need to figure out the parsing side of things as I've not done binary parsing in my host program (Max/MSP) before, so I need to figure that out.

I don't follow most of that code with the string bits in it. I'm specifically trying to send as little information as possible, to hopefully alleviate this buffer overrun problem, and to improve/reduce latency in general.

I'm using the first byte to tag which device I'm using (I have two arduino's, each with 9 sensor outs, so 0x11 = device 1, sensor 1), then the actual sensor data (in this case Accelerometer X axis), then a footer tag (for parsing purposes). So 4 bytes total per sensor (x 9 per arduino, so 36bytes in data total).

Isn't "Count\r\n" at least 9 bytes on it's own? (Unless I'm misunderstanding how "quotes" work when used with Serial.write

All this is not as important with Serial.print() and Serial.write() as it is in some other transport protocols.

With the ethernet shield (TCP or UDP), client.print(), client.println(), and client.write(uint8_t) will send each character in its own packet. Very wasteful.

Those last two array writes (Count and String) are the only way to send all that data in one packet.

Edit: The "Count\r\n" is being sent as a zero-terminated string, letting you know the next line is going to be the array and count method. It is the "HI!\r\n" in the array that is 5 characters. The sixth character in the array is the zero terminator.

"Count\r\n" as an array would be 7 characters. "Count\r\n" with a terminating zero would take an 8 character array.
\r = 0x0D ( one character)
\n = 0x0A (one character)

So if I send the data as a string, it stays together as one packet?

So I could send sensor/device tag & sensor data as a single packet, and if I had two XBees sending this way, each packet would arrive at the receiver in one piece?

One thing that I know I was going to have a hard time was when I had two XBees going at the same time, each sending 9 sensors worth of data, with the streams getting crossed or collided.

Not with XBee. That is serial, not TCP or UDP. No packets involved with serial. It all goes in its own "packet", but with serial, there is only a start and stop bit as "packet overhead". With the other protocols, the packet overhead is high if you send just one byte.

Don't be confused with that now. Just be aware of the different ways you can "write" to different devices.

Ok, I get you.

I thought you had just dropped a simple way for me to avoid a bunch of problems!

So over XBee using the headerbyte, 2byte sensor data, footerbyte is as small as I can get then? (while still having a header/footer for parsing purposes)

There is one thing you can try to speed things up (usually a lot). If you are currently using broadcast, switch to directly addressing the other XBee. Depending on the XBee series you are using set each one to directly address the other and then try the experiment again. When you're using broadcast (the default way they are shipped) the buffers may not go out quickly. Using direct addresses they shoot right out.

At the receiving end, grab the bytes as soon as they appear to minimize buffering on the receive XBee.

I've got them set to direct addresses, though I've not yet tested sending both to a single receiver (I want to figure out the parsing first so I know what's happening on the computer side).

Finally had some time to sit down and test the new code (sending binary).

It still craps out after a couple of seconds (with no discernible difference from using serial.print).

I added in a delay(100) (which is waaay too much latency for the intended usage) and it died after 7seconds....

Any other ideas on how to fix this?

Correct me if I'm wrong. There's only two possibilities left. 1, The XBees just cant keep up 2, The receiving end can't suck the characters out fast enough to clear the buffer.

Judging from your description, you are hitting the XBee to send as fast as you can given the baud rate limitations and the other end has to get them all and pass them out the serial port. This then locks up and you stop seeing characters coming out the Rx end serial port. I mean, they don't come out in hunks, they just quit coming out, never to resume.

So, at the Rx end, dump the parsing and any other code and just use a serial terminal to watch the port as fast as it can. Turn on the Tx arduino and the XBee. In your code, give the XBee a couple of seconds to get connected ok and then hit it. If the Rx end keeps up, the parsing code isn't fast enough to keep up with the input stream and you're filling the Rx buffer on the xbee or something along those lines. If the terminal program sees the same results, then the XBees just can't handle it.

I'd try it, but I don't have any Series 1 XBees, I'm exclusively Series two and the data rates I use are a whole lot lower than what you want to do.