5

I want to launch a communication between two Arduinos, in which case the first Arduino (S) sends data to the second one (R). The type of the data is mixed, consisting of integers, longs, floats and maybe some text. For example:

{125, 1250, 12500, 125000, 1.25, 12.5, 125.0, "some text"}  
  • I thought about converting each one value to string, adding up all strings to a big one, and send the final string with Serial.print(Big_string). In that case I reckon that it would be difficult for the Receiver to extract the string to the exact substrings and convert them to real values.

  • A second thought was to convert all values to bytes and create a byte (or char) array, but each value would be limited to 0-255 (let alone floats and text)

  • A third thought was to convert them to word type (let alone the text), but I think that Serial.print( ) sends only bytes, not words.

In any case, which is the best way to send mixed data over serial?

Any thoughts would be appreciated.

  • Please, tell us a little bit more about those data types. Are they always the same (e.g. always 2 ints, 2 longs, 3 floats and 1 string)? Do you know the maximum possible length of the string? Is it small enough that padding to that length would not be too wasteful? Can you guarantee that the string will have no embedded comma (or semicolon, or other char that you could use as a field separator)? – Edgar Bonet Jul 9 '16 at 13:16
  • I didn't have enough reputation to make a comment! you can check out the answer to this post. Ask me if you had any questions. – Amir Jul 9 '16 at 13:45
  • @ Edgar Bonet Yes, alwayws the same. Small string. No commas or other "strange" character. – user3060854 Jul 9 '16 at 14:52
3

I think the easiest way to solve your problem is using a separator and transmit the array values one after the other. That means having a for loop and in every iteration sending one value of the array with

Serial.println(array[i]).

The function will

  • convert numbers into Strings so you will get "125", "1250", ...
  • append a carriage return character (ASCII 13, or '\r') and a newline character (ASCII 10, or '\n')

On the receiver side you can simply wait for Serial.read() to equal the number 13 and (immediately afterwards) 10 and split the messages there. That works unless your transmitted strings contain new lines.

The disadvantage is, that numbers are of course transmitted in an unefficient way. If you want to transmit them as real numbers instead of strings you have to write your own protocol. This video "Wireless Module Multiple Receivers" goes into that direction, it's using a fixed packet length but it gives an idea of how such a thing works.

  • I didn't expect so many answers, thus I need some time to work them out. Thank you. – user3060854 Jul 11 '16 at 12:12
3

I have a library that does exactly what you want. It can also work with RS-485 and RS-422 multi-drop networks.

You can even get it communicating with a Linux computer (such as a Pi or BeagleBone Black) with the Linux library:

You can use it to send data of any kind between nodes and trigger specific functions to be executed (like RPC) at the remote end.

  • I didn't expect so many answers, thus I need some time to work them out. Thank you. – user3060854 Jul 11 '16 at 12:11
2

If you want to communicate between 2 arduino's with similar cpu (for instance uno and mega) I would go for binary data in a struct. When using a struct you can not use the String class but you can use a char array. Consider this struct as example

struct SerialDataPacket
{
        int someIntegerData;
        long someLongData;
        int someMoreIntegerData;
        char aString[20];
};

You can send this struct as follows:

String myString;
SerialDataPacket transmissionPacket;
transmissionPacket.someIntegerData=1;
transmissionPacket.someLongData=millis();
transmissionPacket.someMoreIntegerData=2;
strncpy(transmissionPacket.aString,myString.c_str(),min(20,myString.length()));
Serial.write((uint8_t *) &transmissionPacket, (uint16_t) sizeof(SerialDataPacket));

you can receive the struct at the other side as follows:

Serial.readBytes((uint8_t *) &transmissionPacket, (uint16_t) sizeof(SerialDataPacket));
myString=transmissionPacket.aString;

Again this method will only work if you have possessors with the same memory byte order. If the processors have a different bit (8 16 32 bit) you lust use processor independent types for it to work.

  • @jante I didn't expect so many answers, thus I need some time to work them out. Thank you. – user3060854 Jul 11 '16 at 12:13
1

If your primary concern is transmission speed, you might consider turning everything into bytes and reversing the process at the other end. If speed is not important, you can use sprintf() to create a character string and sscanf() to parse out the character string at the other end.

Turning everything into bytes is a very custom / specific approach. A character would turn into 1 byte, an integer into 2 bytes, ect. You would have to write custom code to encode this and remember to write code at the other end to do exactly the reverse process. The advantage is that you would only be sending your data and no other information. But this approach is not vary flexible. If you were able to fit your data into 1 byte then suddenly needed 2 bytes (for example, a value once always less than 255 was now 300), you would have to re-write your code at both ends of the connection.

Turning everything into a string with sprintf() is very similar to printing out all your data. You will be including extra characters like commas and / or space for delineation. At the other end sscanf() is used to parse out the character string. At both ends, if done properly, all string assembly and parsing should be done by only these 2 calls. And some issues are taken care of automatically. For instance, the number 100 is 3 characters long and the number 10 is 2 character long. But the sprintf() and sscanf() calls automatically compensate for these (reasonable) variations and continue to work as expected.

added later...

FYI: Even though sscanf() is available for the Arduino, it is not clear to me if it is well supported. You might try testing (create and parse a string in the same sketch) what you want to send / receive before actually committing to this method.

  • If you are going to send binary between two Arduinos, no need to encode anything: just send the data as it is in memory. This is explained in jantje's answer. – Edgar Bonet Jul 9 '16 at 18:24
  • @st2000 I didn't expect so many answers, thus I need some time to work them out. Thank you. – user3060854 Jul 11 '16 at 12:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.