Hey everyone, I am looking to send multiple variables between an Android phone and an ESP32 via classic Bluetooth. I am looking for two-way communication since both devices will be sending one another different data. After following some tutorials I have a basic version going where I'm sending a text string between the two devices.
My initial thought was to combine all the variables into a string, send this string to the receiving device, and then have the receiver parse the data to assign them to individual variables. Would this be the best approach for what I'm trying to achieve or would you guys suggest something else?
Sending the character data may be easier to develop and debug than sending the data in a struct. You may lose some efficiency, but how much data are you sending/exchanging and how fast do you need to do this?
I would recommend a review of Robin2's excellent tutorial on how to send the Serial data as a character string with start and stop markers.
What are you running on the Android side. Is it a custom app? Did you use app inventor? Do you know how to handle a struct on the Android side if you chose to go that route?
If your variables can be organized into groups, use different structure for each group, plus an identifier for the group.
Be aware that there may be some size difference for variables that are used in each device.
scanf(), one 's', is intended for processing standard input. So it needs to handle all possible input and can get out of sync
sscanf() extracts values from a string. later parts of the string can be ignored.
It may be more common, less troublesome to read complete lines of input using Serial.readBytesUntil() or gets() (unix) and then use sscanf() to process the input after some quick analysis.
for example, you could do a simple comparision of the beginning of a string that can identify the type of data and then use various sscanf() formats to read one or more addition values of various types (e.g. int, float, char*).
I don´t think the way I did it is better than what everyone has suggested above because I know them all are more experienced than I am. But what I did is to send unpacked 3 bytes of info, being the first byte an identifier of the variable and the other two their values (useful for x and y coordinates for example). In the other side I simply wait for 3 bytes, read them and assign them to their respective variables in order.
It has its limitations (each value cannot be higher than 255, there´s a risk of loosing bytes, etc...), but it´s been working fine and it´s easy to implement at APP Inventor.
doubt that you'd loose bytes, but how do you insure that you're in sync, always reading the 1st byte. Will there ever be a need to restart the receiver in the middle of receiving data?
this isn't a serious problem when sending an ascii string because the end of the string can always be terminated with a unique char, linefeed. corrupted or missing data could simply be discarded, knowing that the next message will start with the 1st byte following the linefeed.
of course you can do the same with binary data, in fact it's by far the most common. other mechanisims are used to recognize the start of a message/packet/frame, check for errors and even have error correction.
but i agree with @StefanL38, that sending data as ascii is easier to test and debug. it can be manually generated as well
That´s the point of "losing bytes", I cannot ensure that I´m in sync. But reading the buffer of 3 bytes looks faster than bluetoothing them. I believe that´s why it has been working fine.
you can be out-of-sync without loosing bytes because the receiver was started after transmission started. yes, this is technically loosing bytes, but it's really a startup issues.
another way to avoid this is to only send data when requested or acknowledged, ACK. send an ACK to indicate when ready to receive data.