Parsing binary (Arduino Sensor) data using [serial]?

Oct 16, 2011 at 11:06pm

Parsing binary (Arduino Sensor) data using [serial]?

So I have two Arduino boards, with 9 analog sensors each, going over a pair of XBee (series 1) into another XBee connected to a Sparkfun USB Explorer Xbee shield.

It’s 3axis gyro, 3axis accel, 3axis compas.

In Max I need to determine which arduino is sending the data, and for which sensor.

I started off using serial.print() in the Arduino code with a tweaked version of Sensor Box (http://cycling74.com/toolbox/sensorbox/) in Max, but I started getting buffer overflows when going over XBee. I’ve since switched to serial.write() in order to send the data as binary bytes, to send as little data as possible.

Here is one clump of the code from the Arduino:

Serial.write(0×11);
Serial.write(highByte(AccX));
Serial.write(lowByte(AccX));
Serial.write(0×99);

It’s the same format for each sensor. The first byte is my header which tags the device and the sensor, so 0×11 = device 1, sensor 1. AccX is the accelerometer X axis, and 0×99 is my footer.

Now the sensor box parsing used Serial.println() and [select 10 13] to group each bit of data together. I’m not using serial.print but 0×99 instead as it’s only one byte.
Also, I don’t know how I would assemble the binary byte back together in max either.

I then need to route the sensor/device data out to different places. Before I was using [route] as I had plain text coming in, now it’s a binary byte as the sensor/device tag, so not sure if I can use [route] with that, or if I turn the binary byte into something [route] would be happy with.

Lastly, is there anything I can do on the Max side of things to make sure the data from each device doesn’t “cross streams” with the other one? I basically have two of these devices, all sending 9 sensors worth of data to [serial] at all times. If I figure out the binary parsing/routing, what’s to stop the messages coming in mixed together?

So if device one is sending:

Serial.write(0×11);
Serial.write(highByte(AccX));
Serial.write(lowByte(AccX));
Serial.write(0×99);

and device two is sending:

Serial.write(0×25);
Serial.write(highByte(GyroY));
Serial.write(lowByte(GyroY));
Serial.write(0×99);

will [serial] potentially see:

Serial.write(0×11);
Serial.write(0×25);
Serial.write(highByte(AccX));
Serial.write(highByte(GyroY));
Serial.write(lowByte(AccX));
Serial.write(lowByte(GyroY));
Serial.write(0×99);
Serial.write(0×99);

Because that would obviously break the parsing routine.

Here is the max patch I’m using (though all the parsing objects are setup for my older Serial.print() code).

– Pasted Max Patch, click to expand. –
#59365
Oct 17, 2011 at 2:28am

To make sure you aren’t “crossing the streams”, try sending a byte to the sensor you want information from first, indicating you’re ready to receive. Once you’ve received from sensor 1, send a byte to sensor 2 requesting data. This should help insure you know what you’re getting.

#213550
Oct 17, 2011 at 9:59am

Would that add considerable latency to the setup? (if every bit of sensor data makes it’s own round trip)

#213551
Oct 17, 2011 at 10:53am

Hi Rodrigo
Try different baud rate settings to determine the significance of adding call/response code to your setup.

I’m interested to know the reason for using two separate Arduinos…

Brendan

#213552
Oct 17, 2011 at 11:11am

There’s two sending devices.

It’s for a sensor setup on a painter. So there’s an Arduino/Sensorboard + Xbee + battery per arm/wrist. All of that data will end up in max and after some software filtering (kalman/marg? I’ve not gotten that far yet) I’ll then use the angles to determine DSP/sampling stuff.

At the moment I’m at the maximum baud rate that the XBee’s will do. 11500, so anything else would only increase the delay. I’ve not tested a call/response thing at 11500 though.

I still don’t know how to make sense of the binary bytes coming in (particularly the sensor one which is split), so can’t really setup a call response thing yet.

#213553
Oct 17, 2011 at 2:07pm

There shouldn’t be a noticeable latency. One of the big benefits to a call and response method helps insure both the sender and the receiver are ready for new information, not backlogging the queue.

As an aside, I’ve found Xbees to be unreliable at 115,200 baud, you may want to try something slower like 57600. That should be more than sufficient for sending 4 bytes at a time from the sensors and processing it in Max.

#213554
Oct 17, 2011 at 4:23pm

So on the Max side of things do you just setup a [sel] type thing? So you send an initial byte to get it started, then once the footer tag is received, use sel to bang the next byte (sensor tag) and just having it go through a sel/bang/byte loop in max?

#213555
Oct 17, 2011 at 7:28pm

You’ve nailed it.

Look at the Arduino communication examples that come with the IDE. There’s one for raw bytes found in file>examples>communication>serial call and response.

In that example, there’s no need for a final footer byte either. Because you can expect the size of the payload, you can just bang out when the right number of bytes arrive.

#213556
Oct 18, 2011 at 7:51am

Look at that! Very convenient. I shall take a look when I get home from work.

#213557
Oct 19, 2011 at 3:47pm

So there’s a 10ms delay between each sensor… that could prove to be problematic as I have 9 sensors per unit, and 2 units, so 18 sensors total, so if I’m handshaking, I’ll have 180ms latency (not counting actual processing/transmitting time).

#213558
Oct 19, 2011 at 4:25pm

You can decrease those delays to something closer to 2ms each. The 10ms is a large safety buffer.

#213559
Oct 19, 2011 at 4:51pm

It’s also only between the first two (analog sensors), is it only needed after an ADC is read, but not before the end of the loop?

Actually, the read/sent loop only runs once (per byte received), so that delay is a blanked thing for reading ADCs?

A different version of my code (before I was printing with bytes and was using text as my header/footers) had all the ADCs being read at the same time and it seemed to work OK, it’s only when I tried to go wireless with it that it broke.

I also noticed that you use Serial.print vs Serial.write, I was under the (mistaken?) impression that for binary printing you had to use Serial.write.

#213560
Oct 19, 2011 at 6:52pm

The delay should be done after each analogRead. The reason there is only 1 in that sketch is because there are only 2 analog sensors. It is in there in the first place is to let the onboard ADC ‘settle’ after each analogRead. So it’s not necessary to have one after your final sensor has been read (depending on your sketch).

There are 2 examples in the Communication folder, one for ASCII and one for raw bytes. Make sure you’re looking at the right one. You’re correct that Serial.write() is for bytes, and Serial.print is ASCII (usually).

#213561
Oct 19, 2011 at 7:16pm

Does that just increase ADC accuracy? As it seems to work fine without the delay.

Both versions in IDE 022 use Serial.print:

From the ASCII one:
// send sensor values:
Serial.print(firstSensor, DEC);
Serial.print(“,”);
Serial.print(secondSensor, DEC);
Serial.print(“,”);
Serial.println(thirdSensor, DEC);

From the raw one:
// send sensor values:
Serial.print(firstSensor, BYTE);
Serial.print(secondSensor, BYTE);
Serial.print(thirdSensor, BYTE);

#213562
Oct 19, 2011 at 7:42pm

Yes, it does increase the accuracy. But if it’s working for you, keep what you have.

In 022, Serial.print(value, BYTE) works, but as of version 1.0 (due out in a few weeks), that is no longer supported. Serial.write() will be the way to send bytes in the future.

#213563

You must be logged in to reply to this topic.