Prepare measurement data for bluetooth transfer

Hello,

I want to send multiple measurements from one arduino to another arduino via Bluetooth.
I have already found this tutorial and I think example 5 would be appropriate for my use case.

So basically my sending arduino is connected to multiple sensors and I want to concatenate the sensor readings in a certain format so that I can send them over bluetooth and parse it again afterwards.

When I stick to the example, the format should look like this: <sensorreading_1, sensorreading_2, sensorreading_3>

The sensor readings are float values, so basically I have to concatenate these floats with the commatas and the start and end markers, but I havenĀ“t really figured out a smart way to do this. For my purpose the first two decimals of each float would be sufficient.

Do I even have to concatenate all those values to a string or can I do that differently?

EDIT: Ok, after some more research I think I can also just use several Serial.prints to reach the same goal, or is there a downside?

Hello,

There are many, many things to consider when designing a protocol like this. I don't know precisely what your application is, so I can only guess at something that might work for you.

There is no need to concatenate commas because floats are a fixed length (4 bytes on Arduino IDE). You can just send 12 bytes out (four bytes for each float). CAVEAT: this method will create a dependency on arduino's exact hardware float format, and the two arduino modules will have to be using the same machine architecture. If the data is read by some other machine architecture that uses a different float format you'll possibly have to do a nasty conversion of some kind. However, you said "arduino to arduino" so let's ignore that issue by assuming both arduinos use the same float format.

Now, you will need a header of some kind so you can be sure you're starting at the first byte of the first value. Plus, you really will want a checksum at the end because you are going to lose some data here and there due to static and noise. You do not want to log data that is possibly bad.

The checksum can just be the lower byte of the sum of all the data bytes. The header could be any magic number you like, I would suggest at least two characters.

An example protocol would be:

  1. Literal string "SD" as header (start data).

  2. four bytes for each of three floats. (You could do least significant byte first or most significant byte first, just be consistent on both sides of the connection).

  3. A one byte checksum which is the lowest byte of the sum of the 12 data bytes. If this does not match on the other side of the communication, then you will ignore that data packet.

On the receiving side, you will flush data until you see the literal character 'S'. You'll then see if the next character is 'D'. (A simple state machine is a good way to do this). If you don't see a 'D' then you'll go back to the state where you're looking for an S. once you get both S and D, you'll read the next 12 bytes into a buffer then cast each 4 byte chunk into a float. Then, you'll go into a state where you wait for the checksum byte. Once you get that, you will see if it matches the sum of the 12 data bytes. If not, you throw away the packet and maybe log an error somewhere. If it's good, you do whatever you were planning to do with the data.

Again, I do not know all the particulars of your specific application, so I can't say whether or not the above is sufficient. If it's crucial for you not to lose any data, you'd have to implement some kind of retransmission protocol along with a packet numbering scheme, or you could implement a more sophisticated checksum method that allows for error correction.

For an example of protocol, here's the spec on the robot control protocol I use for Vorpal the Hexapod:
https://vorpalrobotics.com/wiki/index.php/Vorpal_The_Hexapod_Radio_Protocol_Technical_Information

Hope this helps,
Steve P.

EDIT: Ok, after some more research I think I can also just use several Serial.prints to reach the same goal, or is there a downside?

No downside to using consecutive Serial.print() statements.

The methods of the Serial Input Basics tutorial which you previously cited are the way to go.

joo00:
Do I even have to concatenate all those values to a string or can I do that differently?

You could use BLE the way it is supposed to be used.

In BLE you have a server (called peripheral) and a client (called central).

The peripheral specifies characteristics and services (collection of characteristics). Each characteristic contains a value which you update at whatever rate seems useful.

The central can find all characteristics using a protocol called GATT. It can then read the characteristics at whatever interval it needs them or get notified when a value is updated. The central can even ignore characteristics when it does not need them. Only the values needed are read/transmitted.

But this does not work with Serial to Bluetooth modules. You could use a Arduino Nano 33 BLE or Arduino Nano 33 IoT. There are other boards with BLE support as well.

@Steve: Wow, thanks for this really comprehensive overview over the whole topic!:slight_smile:
I am using an arduino nano and arduino mega, so I hope the float architecture you spoke about is the same for both of them.
I am transmitting sensor values from an MPU 6050. It is not crucial to get every single reading, so I think a retransmission protocol is not necessary.
Is the header you speak about basically the same like the start and end markers from the example that I linked in my post? So can I also view the "D" as start marker and the "S" as end marker of each 12 byte package in your example?

@Klaus: Thanks for your input as well. The Nano BLE sounds promising with the onboard IMU. But it seems like this would not be the right solution, when I want to send data at around 100 Hz, am I right?

You can send the float values with full precision while actually using fewer bytes if you use SerialTransfer.h. The lib does the packet forming and packet parsing automatically for you making serial comms super easy and it comes with several examples.

Power_Broker:
You can send the float values with full precision while actually using fewer bytes if you use SerialTransfer.h. The lib does the packet forming and packet parsing automatically for you making serial comms super easy and it comes with several examples.

Your library indeed works very well! Thank you for sharing!

Glad you like it!