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:
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:
and device two is sending:
will [serial] potentially see:
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).
----------begin_max5_patcher---------- 3640.3oc2cs0aiiaE94jeED4ot.od4cI12FLnsXPK5BryBz8BJFnXq3Q6JK4 JKOyjYw9eu7hrsbhTDkrIMceHN1xhzmyGOWoH442u8l6dn7KoatC7W.+B3la 98au4F8kTW3llOeycqR9x77jM5a6thzOW9vud28lupN8K05KutJqnd2UK1tJ qHOsV2BTyEyVnuQYi+y73c24ikE0EIqR0e0apxRxa0Gkaq20IvV2+lrupueD d1tKuNod9GyJV9gpz40FtAAikeM.IPp+QnpWwvYPv+Q0j+31aUubukL87xUq ROve645MoJRFrtrpFjTr.7Px1Efpj5TqQB2CD3XgFHXM+C5Dj38+ars7Lldt Y5pzMRZJoNqrnsDPrTB.xj+SxunnYwPHjPkxB7CHvq.aP5Lpp036ATHdVjr0 Hb2st0uulzl.tVWtbYt0hMTT2.0ta0bo5mVmZXl6TJmcRus4XLpS7BCsBuHQ chWc05y.d0ubHxZPzWxg3nYBIZfoSQNDQoyHJrLNDkC4NPNDwgchW1IGhhh5 Du7tbn01CQbeYOTrWCkilwTvJxdygQRnT1Xl7dILcqQr.QLDSbh4PbWvkkVC ovNgqv0ZnvWFCE6UOGsPHhFMiqrLfBPgPlSLEh6BsrzRXLrSzxyxfu8e9t29 O.+v2Ad+O7lu+GrEMiPmh73iIySa2wskQ0r+qi5Z.hoCWN1.VhAfZr9liLux eYSboN9e8e89u66AV6tIBdAQVMNgQDMPg31fsDSBbBQusw8fq0VQ4hKM3xhF M1hIXWhsaxyVjVYKBNVW4Grgt2Izf.EJdFhvhnXkBNZFWHCMRZXDIwXDiRol vEQPrfi228OlWlTK+4WustMA0k0.YpP65eBiaY+6enFi8LVK8lwjwm6HjV9d a58K.Ny7LNSIyhEFm8NAok+V10+W.yGHOi0X5rHDKNF4FrFK86YW+eAvZea+ .xmEQh3QtBqk9Brq+u.Xsm8KFGOiwITWYrFyIV1+mCnVRiRTyZndzyKHtuAA M3b28f6dHoX4gQjwkxLWNpHwsXtIcDgDpfRXiIytKVhoOKUtZIYVnRasUrkc LXDGsuSIL1PcpKCw9u+TUI.7yp2Z6.DySyUAUlyLU6kSZYPJrJj.jvlTuIjc sTE+W+sz4v5OMFXk6cXUZEXhvJI1sv5HMYDEtlLjAcCioBNRqcS33H5oaxPZ JefN8BLHDGtCBxHxYBJiRNm1sktqGnScuAlebLFXDd2.iD2EwQhH9DLwHg2W qsNDZey74o4ixkHE6cnEylNzBgtFZGmoCJIbMcnRvDyfjyYHe5rJe8N8BLHv B2AAYlmXBkiDmyAAYPkCzot2HyXBPjA8tQFXzLtDmPjwajAGie015bncLtFY HeCsxD7mLxJCa2wH63rbvvAqkCILS3LTTSLZnHNEc5VNT4MMPudNFEVmTjla 8f.40ET6+oVEGghikl9hYynBn.p3PBbFRPowB0ykR5rJhvQj8L2CKmWlWVY5 AU9GwxLPtW9NpfhTOrb8y0BM3C+Z2uLlCs8m9bfq8sFZAqSp1HIRqW4PiUrG w6c5Bu+D9aP0jNlLPQyyWmYdli8XBJspAFavQ4OQVd5mRkvTC7eey0SVut0k uoUSTf+uZDVX2u+RYElKg1eopzOksq8ByEkCo2t6KOP4ZZkZd1oQTySckzRX SIelWN+2RWzR9+l6Vj9335kx0oEGZgdgHbzKGemYEOWzr8ubx175Oz8vywe+ tmAcmeYmxX2b2xprEkEJh3nVpt7teNIGaFvYsoa8cTjrtiFWWVl+PRkZH4g7 ziFpkJWIEYqRpSqyV07vw22trUlkhd69JsHQ1Geby7px77i5Jy27oN9lERog 4oeNaQ8G080Az5nkLea4r1p8Gc8mo9aT91gd8on26S.near8orwhzqEdJVut KvrcutefP0tcAyn98vf2+4LY2.v2s6Fzl3ZzI7KeSmNeSmJeiB.9FMY9FKZ3 ark7MJjFuwSmu4SkuCfw68qRfIHmiFobNGnm8teN.3Z9j4ZZ7H4Zlgq+o.fq ilNWyFIWSMb8OF.bc7z4Zbz33ZBnYRTC.1VLY1lHhFqCrlo0I.riCmNaymHa GBB4mf6KxnceELlwOgfUfSiqCAy3SWDGEMMtN.jvQS2dlZCbLRtNXLiilt2K DZhrc.HiildnJwSjqOqx3GMWaOa2aOOIOE.AHHlHSvGfl0K3v6wGW6Fz+Djz 6x1afkt2qLmZCjJ.wruUPP1w616qAPkGbfZSlFpEJ20JnhPgGpZxjgfEWunJ N7PUSlRDH45EUCOypMIhgM6suqSTkFdnpIOOL6R4rpRxNofju.RdBj7Uvxu. V9DX4WAa9LR9GdzwJwlJDKdUH11m+1ILDfMGPNbnSFBNdgR7rsX457rZvlzh MkU.j9XzYz.+jMCCmLvgabaEadTyXpS.NMm2KZ.6QLbhpxs2Q58+nEL6FWKC o+uUUtB7d8ojzUSP8TQvYnrYlgHlIM3pz8CMN7PUXSX8WugJQiBNTsYlsHl3 PuNQ0vKEzlYNi.QWunZ3E.ZyDyginWunZ3kXuYd+vz3++HpdL8pKp9lQflYd 0QA0O3H.ZBAxO4T+IVg0mLlhhMmUJjHumnzaKK9TZUM3Mu+su6cf5RvlmV8P Y9XgXp+yURsOO0q8OCDRubXmLEmzkoUJzSCiiE7XW.viZ.OBwkf2qnL+nLGt oIp4ifSasPvQl0Ear.hDb8Jjs4cnmkg5jT7MyVcD02veVcYRu.Ooaf2M4Z8h 4GvaXu43alx8M1+0bvRour08h+3tw+IOCB3A8hc5fIBYVq4dOV2zbIoHCHDf HidlUgNIt.8l749C++jlMAwA6CQ92C26dD7T4VvxzZfbLHOqHE7mLQJffey8 p4WcAn9iof7rM0y.st6pz5sUE6uYx2.VTBJJqUr2LvaJdBHeuzk4mRx2ldOH YwBk2yccUaZQ8iNubqYp+HicDleAbsB0iYbyILn4bwTk0RmCZG10BJ9rmM.f 9GQ88cOZtoba07cBeMSUK3X6iKR2TmUreOb7KGj+e1M9wrEKNdOSX1WKKVWJ MT2PeVJ9MZxVQNXKnawzHaAeF6dfYKxb38tjYftiYHwyzakU3AtQ+AWwN1JS oVDxgjLE1V5NNrnahszsHrnapkzMIvr8HyACPrwlIJ7naarY1ghvEmtQ1P2j vitsx2JM7nalM5kgGYGYCYGfzM2F5N.ESnVP27fhrUSvqcVSXSitQLlJBKrL KW0IMTDe+mbIGYk++vR.RSNVovhBO51JEVb3Q21HmPCP71FMVZ.JeaS7VTd3 Q21DeKMJ7naabHQiCO51l3sngU9aV61gETjM05o7JrDuo1Z9FEVh2cXcqG5N rDu6v5VOx2g0zSzg0sdn6vxMeGV25gtCqvprU7FGVd4sV5NrxV1Vg6vx1ssh 1mSK2MWb2IH1caR9T5hOH+URmW+gj55prG1VadLRsHeaNssdkuZnC5qk4kOj j2bxpsuONpmew4+0nNzvt8.J31RpivukCC0AdtKKSTLLIXKSTLpmwZ04ZtyJ STLHMPKSTLOWlnTG5htrLQQiYAaYhZ+QQjuv5XnSKSTTNOXKSTLtmwZN1okI JJMNXKSTrHOi0TpSqSTTBLXqSTrvsdiPH7yechhgwWW0IJl2q2HpvDmVAMRE .3URchh68x..AIlJrBYgTchBEvlLTGbPm65DkJX6fqNQgPA6ffJj7ydchREG 9UUchh68hggB2mZwLRAuWM0IJt2qSTppbyjgVdTXUmn3gachRmg44tNQoSqL zpST7vs9rpR87rWmnT4adUUmn3du9rNTEI5UMxPEWO0IJt2qQqpL7mLzJydO nJTT7vsNspv4yekhRMBDbUJp8GaxStRQgonIUpnZ1kpGpWT6dm8kJJ04qnGK UT0kKUC31VBEgib5+Zukd6E2E5i7.yluc+quFb0Tbmv6O4ObfDWO0PqlMYJr SDC2QMoEd1rH7hMQ5HJGVXygljYS4xvGu6QOSdalmmM+2.eLsJUsANmmWtIU uMN2nOd1.qKqpsVC9r6FpCcNyQpWyd+FC4d.TTUgpIiIQd.S1cl5DeNvjUoa 1jrLsCLQJZXqBDd7EgtgeVDiVwoQJgzblLdlADkX.HwVDAItnHBABaIiPQmD hzmZyaORsQsMxSzaGbP4is0c1XsxiGzcLGCRwMFWiNIUmd797eWkVWUBPV69 AgOaxJ1EGZuNqMtd3LmXQwTR9rESHWV8GbK4DB+jTe5MHEsFRhLnQFFBsdhq OeS7gd33zpbmlyCGAwItk+9zjE6LjjUrdaM3gsO9XZEPU6OeRcFhrJKWZvIc dYwh8VYN5.n.aKpxbusG9AMrlJdpxekCrH2DCy2ZhtqkkX84p7l5jp5ucSco pRyJIxSC27P7NXhVKz3U2bbP7BfSKBe7YxgAGe9pDsAMGXiv22tn7n0F5KWW nculPewX6YklP9kjTaCLzPjTezDxczDdHZJ16zTz.jzwqpauPRrAHoi2dydg jnCQRQdmjHCQR9WVBMzHG0+5bCoxQ8u78PVlnL+SRCIfe7dyxKzDe.Rx+nzP d4XX+OvMjY.1EvLvfQn3ecNwPjj+8oDODI4YeJVIg6YkNrMwVR8avkDGPSpJ Kl9vVinOCPTa7ilOcpTarMipdV3W3BDDZPPBpMBRPmLBhQNfZwwQZ5iQaSsp OchTKwlrw7q42mEarMaUW2SS1nVf8qwNJzFAMrWM1QswXGwuQ0+rvis4D0w4 zDyFGUD+p2wrRFW3UZhai7D1ugrxswjIyu4+vswlIKJ7rOc7IvoENBMt9n5C d1FuhpObp12sgVw9cVI0zzfyJoXrANBUPVSgrxDCTT7Kl24a+ia+edhD73A -----------end_max5_patcher-----------
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.
Would that add considerable latency to the setup? (if every bit of sensor data makes it’s own round trip)
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…
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.
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.
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?
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.
Look at that! Very convenient. I shall take a look when I get home from work.
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).
You can decrease those delays to something closer to 2ms each. The 10ms is a large safety buffer.
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.
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).
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:
From the raw one:
// send sensor values:
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.