With Arduino can create large number of projects as you have seen if you read Hwlibre, programming the microcontroller in a simple way. But between the analog and digital connections of this board hardware libre, there are some that are still somewhat unknown to many beginners, such as the true potential of the PWM connections, the SPI, the RX and TX pins of the serial port, or the I2C bus itself. Therefore, with this entry you will be able to at least know everything you need about I2C.
With the I2C bus you can connect and use many third-party devices that have this type of protocol to communicate with the Arduino board. Between them, you can connect accelerometers, displays, counter, compasses, and many more integrated circuits thanks to this Philips invention.
What is I2C?
I2C refers to Inter-Integated Circuit, that is, inter-integrated circuit. It is a serial data communication bus developed in 1982 by the Philips Semiconductors company, which today is NXP Semiconductors after getting rid of this section. At first it was created for televisions of this brand, to communicate several internal chips in a simple way. But since 1990 the I2C has spread and is used by many manufacturers.
Currently used by dozens of chipmakers for multiple functions. Atmel, the creator of the microcontrollers for Arduino boards, introduced the TWI (Two Wired Interface) designation for licensing reasons, although it is identical to I2C. But in 2006, the original patent expired and is no longer subject to copyright, so the term I2C has been reused (only the logo continues to be protected, but its implementation or use of the term is not restricted).
I2C bus technical details
El I2C bus has become an industry standard, and Arduino has implemented it for communication with peripherals that need it. It only needs two lines or cables for its operation, one for the clock signal (CLK) and the other for sending serial data (SDA). This is advantageous compared to other communications compared to the SPI bus, although its operation is somewhat more complex due to the additional circuitry required.
On this bus each device connected to it has an address used to access these devices individually. This address is fixed by hardware, modifying the last 3 bits through jumpers or switch DIPs, although it can also be done by software. Each device will have a unique address, although several of them may have the same address and it may be necessary to use a secondary bus to avoid conflicts or change it if possible.
In addition, the I2C bus has a Master-Slave type architecture, that is, master-slave. This means that when communication is started by a master device, it will be able to send or receive data from its slaves. The slaves will not be able to initiate the communication, only the master can do it, and neither can the slaves talk to each other directly without the master's intervention.
It tienes several teachers on the bus, only one can act as a teacher simultaneously. But it is not worth it, since the change of teacher demands a high complexity, so it is not frequent.
Keep in mind that the master provides the clock signal to synchronize all devices on the bus. That eliminates the need for each slave to have their own watch.
The I2C bus protocol also foresees the use of pull-up resistors in the supply voltage lines (Vcc), although these resistors are not usually used with Arduino pull-up because programming libraries as Wire activates the internal ones with values of 20-30 k. This may be too soft for some projects, therefore the rising edges of the signal will be slower, so lower speeds and shorter communication distances can be used. To correct that you may need to set external pull-up resistors from 1k to 4k7.
Signal
La communication frame of which an I2C bus signal consists of the bits or states (those used in Arduino, since the I2C standard allows others):
- 8 bits, 7 of them of address of the slave device that you want to access to send or receive data from it. With 7 bits, up to 128 different addresses can be created, so 128 devices could theoretically be accessed, but only 112 can be accessed, since 16 are reserved for special uses. And the additional bit that indicates if you want send or receive slave device information.
- There is also a validation bit, if it is not active the communication will not be valid.
- Then the data bytes that they want to send or receive by the slaves. Each byte, as you know, is made up of 8-bits. Keep in mind that for every 8-bit or 1 byte of data sent or received, an additional 18 bits of validation, address, etc. are required, which means that the bus is very limited in terms of speed.
- A final bit of validation of the comunication.
In addition, the clock frequency for transmissions is 100 Mhz as standard, although there is a faster mode at 400 Mhz.
Advantages and disadvantages of the I2C bus
The and advantages are:
- Simplicity by only using two lines.
- Available mechanisms to know if the signal has arrived compared to other communication protocols.
The disadvantages are:
- Speed fairly low transmission.
- It is not a full duplex, that is, you cannot send and receive simultaneously.
- Does not use parity nor any other type of verification mechanism to know if the data bits received are correct.
I2C on Arduino
En Arduino, depending on the model, the pins that can be enabled to use this I2C bus vary. For example:
- Arduino UNO, Nano, MiniPro: A4 is used for SDA (data) and A5 for SCK (clock).
- Arduino Mega: pin 20 for SDA and 21 for SCK.
Remember that to use it you must make use of the library wire.h for your Arduino IDE codes, although there are others like I2C y i2cdevlib. You can read the documents of these libraries or our articles on the projects that interest you to obtain codes of how it would be programmed.
How to know the address of a device to use it with I2C?
Just one last warning, and that is that when you buy ICs from European, Japanese or American manufacturers, you indicate the direction you should use for the device. On the other hand, the Chinese sometimes do not detail it or it is not correct, so it will not work. That can be easily solved with an address scanner to know which direction you should refer to in your sketch.
La arduino community has created this code to scan the address and identify it In a simple way. Although I show you the code right here:
#include "Wire.h" extern "C" { #include "utility/twi.h" } void scanI2CBus(byte from_addr, byte to_addr, void(*callback)(byte address, byte result) ) { byte rc; byte data = 0; for( byte addr = from_addr; addr <= to_addr; addr++ ) { rc = twi_writeTo(addr, &data, 0, 1, 0); callback( addr, rc ); } } void scanFunc( byte addr, byte result ) { Serial.print("addr: "); Serial.print(addr,DEC); Serial.print( (result==0) ? " Encontrado!":" "); Serial.print( (addr%4) ? "\t":"\n"); } const byte start_address = 8; const byte end_address = 119; void setup() { Wire.begin(); Serial.begin(9600); Serial.print("Escaneando bus I2C..."); scanI2CBus( start_address, end_address, scanFunc ); Serial.println("\nTerminado"); } void loop() { delay(1000); }