iioRobot

Open Source multi-axis robot

Arduino • I2C Communication & JSON format

- Posted in Software by

As we have seen previously, communications between Arduino's are done using the I2C protocol. The theoretical range of 1 meter is sufficient in our context. However, we will have to remove various constraints:

  1. The I2C protocol only transmits characters, which prevents us from natively transferring numbers. Therefore, we will convert these numbers into characters during transmission, and these characters into numbers during reception;
  2. Transferring a message from a sender to a receiver is easy. What then of several variables? We will therefore associate these pairs of keys / values ​​in an object. The best format for doing this is JSON, so we chose it.
  3. The association of points 1 and 2 above is done by serialization of the data, which makes it possible to send, without altering the contents, the data to the receiver. Deserializing the data on arrival recreates the JSON object, which itself can be decorticated into variables.

First, we load the I2C library (https://www.arduino.cc/en/reference/wire):

#include <Wire.h>

Then we tell the Mega that it is the I2C bus master with:

void setup() {
   Wire.begin();
}

For each Nano "slave", we integrate it into the I2C bus like this:

unsigned int idMotor = 10;

void setup() {
   Wire.begin(idMotor);
   Wire.onReceive(receiveEvent);
}

Note that the idMotor of each "slave" must be unique, > 8 and <127 according to the I2C specifications.

Now, we can therefore send a message from the "Master" to the "Slave":

char message[13] = "Hello Word!";
Wire.beginTransmission(10);
Wire.write(message);
Wire.endTransmission();

And receive it in the reception function declared previously "receiveEvent":

void receiveEvent(uint8_t byteCount) {
    char message[byteCount];
    int iMessage = 0;
    while (Wire.available()) {
        message[iMessage] = Wire.read();
        iMessage++;
    } 
}

We now have a system for sending and receiving a message, following a table of characters. Note that the use of "char [xx]" is recommended because the function of sending strings of type "String" is not allowed by the I2C library.

Just have to encode our data in the JSON format we want to use, serialize it (= transform it into a series of characters to form an array of characters) and send it through the function we have just performed , instead of the "message" variable.

To do this, we need the JSON format management library (https://arduinojson.org/):

#include <ArduinoJson.h>

In order, we need to create a JSON document, convert it to an object, associate it with the keys / values ​​we want to communicate, serialize it, and voila:

StaticJsonDocument<256> docJson;
JsonObject objectJson = docJson.to<JsonObject>();
objectJson["Key1"] = Value1;
objectJson["Key2"] = Value2;
char json[256];
serializeJson(docJson, json);

Finally send the JSON instead of the message from the previous paragraph:

Wire.beginTransmission(idMotor); // Transmission to engine
Wire.write(json);
Wire.endTransmission(); 

On receipt, our JSON must be shelled, with the same library. Here is the code for retrieving values:

StaticJsonDocument<256> docJson;
deserializeJson(docJson, json);
JsonObject objectJson = docJson.as<JsonObject>();

int Value1 = objectJson["Key1"];
float Value2 = objectJson["Key2"];

We now have a complete inter-Arduino's data transmission system that takes formats into account.

We will see later what it will be useful to us ...