top of page
Writer's pictureTasnemul Hasan Nehal

Sending "String" data - I2C bus

Objective:

Here we will learn how to establish a I2C bus serial communication between 2 Arduinos and how a Slave Arduino can send "String" data (ex: "Forum") to Master Arduino.


Theory:

Before we go for coding, we must know the basics of I2C bus and how it works. I highly recommend you to go through Scott Campbell's article on I2C bus to understand it better.


Hardware Setup:

Full Code:

ArduinoA (Master)


#include<Wire.h>

char x[20];                 //so that maximum 20 character can be saved

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

void loop() 
{
  Wire.requestFrom(0x52,5);    //requesting 5 bytes [Forum=5 character]
  if (Wire.available())
  {
    byte m = Wire.readBytesUntil('\0', x,20);
    x[m] = '\0';  //to make "x" a string from array
    Serial.println(x);
  }

}


ArduinoB (Slave)

#include<Wire.h>                     //main library

void setup() 
{
  Wire.begin(0x52);                  //slave address to call by Master
  Serial.begin(9600);
  
  Wire.onRequest(sendData); 
}

void loop() 
{
  ;
}

void sendData()
{
  char m[]="Forum";  //sending messege
  int l = sizeof(m);
  Wire.write(m, l);
}


Code Explanation:


At Master

char x[20]; 

Let's say we don't know how many characters will come from the sender, so we assume a maximum of 20 characters can come. No character will be saved after that.

Wire.requestFrom(0x52, 1);

Requesting Slave no-0x52 send 1byte data

byte n = Wire.requestFrom(0x52, 1);

Requesting Slave no-0x52 send 1byte data. If the slave 0x52 is online on the bus, then n=1, not necessary any data to come. This value "1" is used to allocate memory space for incoming data.

byte n = Wire.requestFrom(0x52, 5);

Here n=5. Which means the Master allocated 5 bytes of data where incoming data will be stored. Now if 2/3 bytes data comes then the rest of the memory location will be auto-filled with 0xFF (in decimal = 255)

while( Wire.available() > 0 ) 

Till there are data coming from Slave/data is available to receive, this loop will run to receive & store incoming data.

byte m = Wire.readBytesUntil('\0', x,20);

This command will read incoming "byte" data until it finds '\0' (Null) character. And all the incoming data will be stored in x variable which can take a maximum of 20 characters. Here the "m" gives us the number of total bytes received. If we send "Forum", at the receiver m=5.

x[m] = '\0';

After receiving data, x[] will remain a character array but the sender sent a string. So we insert a '\0' (null) character at the end of the x[] to make it a string. For the example of "Forum". x[0] to x[4] = main data, and x[5] = '\0'




At Slave

Wire.onRequest(sendData);   

When the Master asks to send any data by terminating "Wire.requestFrom(0x52, 1)" in the Master side code, the "sendData" function will run automatically to send the requested data. This function works only for Slaves. Masters dont have this type of sending function. "sendData" is a regular function name, it can be replaced by any name that follows the Variable naming rules.

Wire.write(m, sizeof(m));

Normally we sent only "byte" type data using .write( ) function. But it is also possible to directly send an array of characters (String) by this command. Unlike integer, the size of a 'character' is 1byte, thus it's possible to directly send a character. Since we are sending multiple 'characters' (array) one by one at the same time we need to mention the total data size so that the receiver knows how many memory locations it should reserve for incoming bytes.



Result:

Master's Serial Monitor




See More Examples:


Comments


Commenting has been turned off.
bottom of page