Examples - Electronic Bricks - i2c Interface

Tutorial on the I2C / IIC interface

That program gives you a basic understanding how to communicate with other devices that are using the i2c interface.

If you want Arduino to communication with external module, there are some communication protocols optional: IIC, SPI and UART.

NXP Semiconductors developed a simple bi-directional 2-wire bus for efficient inter-IC control. This bus is called the Inter-IC or I2C-bus. Only two bus lines are required: a serial data line (SDA) and a serial clock line (SCL). Serial, 8-bit oriented, bidirectional data transfers can be made at up to 100 kbit/s in the Standard-mode, up to 400 kbit/s in the Fast-mode, up to 1 Mbit/s in the Fast-mode Plus (Fm+), or up to 3.4 Mbit/s in the High-speed mode. (Description from NXP I2C-bus specification and user manual v3). It’s not a must to know the specific protocol and time sequence, because there is a ready library allows you to communicate with I2C / TWI devices. On most Arduino boards, SDA (data line) is on analog input pin 4, and SCL (clock line) is on analog input pin 5. On the Arduino Mega, SDA is digital pin 20 and SCL is 21. Let’s take a quick look at the functions of the library:

begin() / begin(address) Initiate the Wire library and join the I2C bus as a master or slave.

address :the 7-bit slave address (optional); if not specified, join the bus as a master.
(note: There are both 7- and 8-bit versions of I2C addresses. 7 bits identify the device, and the eighth bit determines if it's being written to or read from. The Wire library uses 7 bit addresses throughout. If you have a datasheet or sample code that uses 8 bit address, you'll want to drop the low bit (i.e. shift the value one bit to the right), yielding an address between 0 and 127.)

  Syntax: wire.begin(0x04); // set a Arduino as a slave which address is 0x04. 
          wire.begin();     //set a Arduino as a master. 



requestFrom(address, count) Request bytes from another device. The bytes may then be retrieved with the available() and receive() functions. quantity: the number of bytes to request.

  Syntax : wire.requestFrom(0x04,4); // A master request the slave which address is 0x04 to return 4 byte. 



beginTransmission(address) Begin a transmission to the I2C slave device with the given address. Subsequently, queue bytes for transmission with the send() function and transmit them by calling endTransmission().

  Syntax: wire.beginTransmissin(0x04);// The master start a transmission with the slave which address is 0x04



endTransmission() Ends a transmission to a slave device that was begun by beginTransmission() and actually transmits the bytes that were queued by send().

  Syntax: wire.endTransmissin();// The master ends a transmission with the slave which connected. 



send() Sends data from a slave device in response to a request from a master, or queues bytes for transmission from a master to slave device (in-between calls to beginTransmission() and endTransmission()).

  Parameters: value: a byte to send (byte)  
  string: a string to send (char *)  
  data: an array of data to send (byte *)  
  quantity: the number of bytes of data to transmit (byte)  
  Syntax : wire.send(“hallow word”);//maser send up the data “hallow” to IIC bus. 



byte available() Returns the number of bytes available for retrieval with receive(). This should be called on a master device after a call to requestFrom() or on a slave inside the onReceive() handler. return the number of bytes available for reading.

  Syntax : if( wire.available())  // check if there is data receive. 



byte receive() Retrieve a byte that was transmitted from a slave device to a master after a call to requestFrom or was transmitted from a master to a slave.

  Syntax : data = receive(); // Retrieve the data that on the wire.



onReceive(handler) Registers a function to be called when a slave device receives a transmission from a master. (handler: the function to be called when the slave receives data; this should take a single int parameter (the number of bytes received from the master) and return nothing, e.g.: void )

  Syntax: wire.onReceive(read);// when the slave receives a data from the master it 

will jump into the function read()

onRequest(handler) Register a function to be called when a master requests data from this slave device. (handler: the function to be called, takes no parameters and returns nothing, e.g.: void myHandler())

  Syntax: wire.onRequest(read); // when the master receives a data from the slave it will jump into the function read() 



Let’s try connecting two Arduino together and communicate. Connect two Arduino with 4 pins cable use the IIC connector on the Chassis. Then the hardware is set.

Program this code into the other Arduino to turn it a receiver, then it become the slave which address is 4. And press “serial monitor” button on the Arduino IDE, you can see the data that slave received. There are many module have the IIC interface, you can use the Arduino to control them easily too. Let’s take the DS1307 RTC module for example: DS1307 is a real time clock IC, it can be set and sent out the clock data by IIC.



#include <Wire.h>

void setup()
{
        Wire.begin(); // join i2c bus (address optional for master)
}

byte x = 0;

void loop()
{
        Wire.beginTransmission(4); // transmit to device #4
        Wire.send("x is ");        // sends five bytes
        Wire.send(x);              // sends one byte
        Wire.endTransmission();    // stop transmitting

        x++;
        delay(500);
}

Program this code into the first Arduino , then this one is the master. And we use it to
sent out data.

#include <Wire.h>
void setup()
{
        Wire.begin(4);                // join i2c bus with address #4
        Wire.onReceive(receiveEvent); // register event
        Serial.begin(9600);           // start serial for output
}

void loop()
{
        delay(100);
}

// function that executes whenever data is received from master
// this function is registered as an event, see setup()
void receiveEvent(int howMany)
{
        while(1 < Wire.available()) // loop through all but the last
        {
                char c = Wire.receive(); // receive byte as a character
                Serial.print(c);         // print the character
        }
        int x = Wire.receive();    // receive byte as an integer
        Serial.println(x);         // print the integer
}