Sending "float" 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 "float" data (ex: 91.25) 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>
void bytesToInt(byte b0, byte b1); //converts bytes to int
int a; //converted int is stored here
void setup()
{
Wire.begin(); //only for master to create communication
Serial.begin(9600); //MCU & Serial Monitor communication start
}
void loop()
{
Wire.requestFrom(0x52, 2);
while(Wire.available()>0)
{
byte b0=Wire.read(); //reads data
byte b1=Wire.read(); //reads data
bytesToInt(b0, b1); //converts incoming bytes to integer
float f= (float) a/100; //integer to float
Serial.println(f);
}
}
void bytesToInt(byte b0, byte b1)
{
a = (b0 << 8) | (b1); //using Bitwise operators
}
ArduinoB (Slave)
#include<Wire.h>
void intToBytes(int x); //converts int to bytes
byte b0,b1; //stores incoming data
void setup()
{
Wire.begin(0x52); //slave address to call by Master
Serial.begin(9600); //MCU & Serial Monitor communication starts
Wire.onRequest(sendData);
}
void loop()
{
float f=91.25;
int x= f*100;
intToBytes(x); //converts integer to bytes before sending
Serial.print(b0, HEX);
Serial.println(b1, HEX);
}
void sendData()
{
Wire.write(b0); //sending data at request
Wire.write(b1);
}
void intToBytes(int x)
{
b0= (x >> 8); //bitwise operation
b1= x & 0xFF;
}
Code Explanation:
At Master
void bytesToInt(byte b0, byte b1);
We can not directly send the "integer/float" type data from Slave. All Serial Communication is only possible with "byte" type data(ex: 0x12). So we first convert the float to integer then integer to bytes. Then only the bytes data is sent to Master Arduino. We created this user defined function which will take the incoming 2-byte type of data as input and convert those to one integer. So at the Master's monitor, we will see the same float data that was sent from Slave Arduino.
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.
At Slave
void intToBytes(int x)
We first convert the float to integer then integer to bytes. We created this user-defined function which will take an integer input then will split it into 2 data bytes. We use the Bitwise (>>, &) operator to make this happen.
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.
Result:
Master's Serial Monitor
See More Examples:
Comments