Introduction: I2C Between Arduinos

Maybe sometimes we want to share the workload of one Arduino with another. Or maybe we want more digital or analog pins. Inter-Integrated Circuit or I2C (pronounced I squared C) is the best solution.

I2C is an interesting protocol. It's usually used to communicate between components on motherboards in cameras and in any embedded electronic system.

Here, we will make an I2C bus using two Arduinos. We will program one master Arduino to command the other slave Arduino to blink its built-in LED once or twice depending on the received value.

In order to build this we need the following "ingredients":

  • 2 Arduinos
  • Jumper cables
This instructable and many more can be found in my Arduino Development Cookbookavailable here. :D

Step 1: How to Connect Them

Follow these steps to connect two Arduino UNOs using I2C:

  1. Connect pins A4 and A5 on one Arduino to the same pins on the other one.
  2. The GND line has to be common for both Arduinos. Connect it with a jumper.

We also have a schematic and a "breadboard" implementation, both easy to follow. Luckily, it's a simple implementation.

Remember never to connect 5 V and 3.3 V Arduinos together. It won't
hurt the 5V Arduino, but it will certainly annoy its 3.3 V brother!

Step 2: Code

The following code is split in two parts: the master code and the slave code, which run on two different Arduinos. First, let's take a look at the master code:

// Include the required Wire library for I2C<br>#include 
int x = 0;
void setup() {
  // Start the I2C Bus as Master
  Wire.begin(); 
}
void loop() {
  Wire.beginTransmission(9); // transmit to device #9
  Wire.write(x);              // sends x 
  Wire.endTransmission();    // stop transmitting
  x++; // Increment x
  if (x > 5) x = 0; // `reset x once it gets 6
  delay(500);
}

And here is the slave code that interprets the characters sent from the master:

// Include the required Wire library for I2C<br>#include <Wire.h>
int LED = 13;
int x = 0;
void setup() {
  // Define the LED pin as Output
  pinMode (LED, OUTPUT);
  // Start the I2C Bus as Slave on address 9
  Wire.begin(9); 
  // Attach a function to trigger when something is received.
  Wire.onReceive(receiveEvent);
}
void receiveEvent(int bytes) {
  x = Wire.read();    // read one character from the I2C
}
void loop() {
  //If value received is 0 blink LED for 200 ms
  if (x == '0') {
    digitalWrite(LED, HIGH);
    delay(200);
    digitalWrite(LED, LOW);
    delay(200);
  }
  //If value received is 3 blink LED for 400 ms
  if (x == '3') {
    digitalWrite(LED, HIGH);
    delay(400);
    digitalWrite(LED, LOW);
    delay(400);
  }
}

Step 3: Code Breakdown

First, let's look at the master. We need to include the required Wire.h library:

#include <Wire.h> 

Then, in the setup function, we begin the I2C bus using the Wire.begin() function. If no argument is provided in the function, Arduino will start as a master.

Lastly, we send a character x, which is between 0 and 5. We use the following functions to
begin a transmission to the device with the address 9, write the character, and then stop the transmission:

Wire.beginTransmission(9); // transmit to device #9
Wire.write(x);             // sends x
Wire.endTransmission();    // stop transmitting 

Now let's explore the slave Arduino code. We also include the Wire.h library here, but now we start the I2C bus using Wire.begin(9). The number in the argument is the address we want to use for the Arduino. All devices with address 9 will receive the transmission.

Now we need to react somehow when we receive an I2C transmission. The following function appends a trigger function whenever a character is received. Better said, whenever the Arduino receives a character on I2C, it will run the function we tell it to run:

Wire.onReceive(receiveEvent); 

And this is the function. Here, we simply store the value of the received character:

void receiveEvent(int bytes) { 
   x = Wire.read();
}

In loop(), we simply interpret that character to blink the built-in LED at different speeds depending on the received character.

Step 4: More About I2C

To briefly go through the theory, I2C requires two digital lines: Serial Data line (SDA) to transfer data and Serial Clock Line (SCL) to keep the clock. Each I2C connection can have one master and multiple slaves. A master can write to slaves and request the slaves to give data, but no slave can directly write to the master or to another slave. Every slave has a unique address on the bus, and the master needs to know the addresses of each slave it wants to access.

Each I2C bus can support up to 112 devices. All devices need to share GND. The speed is around 100 kb/s—not very fast but still respectable and quite usable. It is possible to have more than one master on a bus, but it's really complicated and generally avoided.

A lot of sensors use I2C to communicate, typically Inertial Measurement Units, barometers,
temperature sensors, and some Sonars. Remember that I2C is not designed for long cable lengths. Depending on the cable type used, 2 meters might already cause problems.

I2C is a complicated transmission protocol, but it's very useful. All Arduinos implement it, with a few differences in pin mappings:

Board I2C pins

Uno, Pro Mini A4 (SDA), A5 (SCL)

Mega, Due 20 (SDA), 21 (SCL)

Leonardo, Yun 2 (SDA), 3 (SCL)

Step 5: Connecting More Devices

If we need to connect more than two devices on an I2C bus, we just have to connect all SDA and SCL lines together. We will need the address of every slave to be addressed from the master Arduino.

Here is a video of a personal implementation using 1 master and 3 slaves.

More topics regarding Arduino communications such as Wireless Serial, SD cards or Ethernet can be found in my Arduino Development Cookbook available here. :D

Comments

author
Mr+innovative made it!(author)2016-10-10

Hey how to know the address of arduino board ..??

author
cliquot22+ made it!(author)2017-03-28

In the slave code, we start the I2C bus using Wire.begin(9). The number in the argument is the address we want to use for the Arduino.

author
SalbaheJim made it!(author)2017-06-19

One thing I find useful when using I2C is to set a global variable at the top of my sketch called "I2C_Addr". That way when I go over my sketch later it's easier to understand what that number represents, and makes it easier to change it if you want to use multiple slave devices with the same code on the same bus.

author
LukeS170 made it!(author)2017-04-14

For those wanting to use longer cables (I used a 5m cat5 cable), you will need to use pull up resistors. My breadboard has a 5v rail, so added a 4.7k resistor from that to pin 4 and another to pin 5. I didn't actually have a 4.7k resistor, so used 2 10k in parallel to give ~5k resistance. This worked straight away.

author
SalbaheJim made it!(author)2017-06-19

One thing to keep in mind is that the !2C protocol, if I recall correctly, has a capacitance limit of 600pF for the conductors. The longer the wires, the higher the capacitance. If you need a REALLY long cable length, try an I2C booster IC. They boost the signal on the bus and greatly extend the max transmission distance reliably while overcoming the capacitance limitations.

author
GustavoC140 made it!(author)2017-05-17

Can i use like 3 or 4 Arduinos as slaves and use the same adress to all of them? Would they make the same thing or would it make all the system go nuts?

Assuming unilateral communication (only master send info to the slaves. Slaves just do the job)
Sorry for the bad english!

author
SalbaheJim made it!(author)2017-06-19

While that's not a bad concept, you have to keep in mind that !2C is a bus with everybody on at the same time. If you give two devices the same address they'll both respond to any commands sent by the master, which would be fine as long as the command sent doesn't expect a reply or acknowledgement. As soon as two devices with the same address try to respond at the same time you'll get a crash of garbled information coming back to the master. Also, if the two slave devices have opposing polarity (one sets the bus to LOW while the other to HIGH) you can overload the IO pins. If you need to send the same signal to several slaves, give them each a unique, sequential ID (4, 5, 6, 7, etc), then use a FOR-NEXT loop to count through the slave addresses and send the same command to each slave inside the loop. Arduinos are fast enough that you probably won't see any delay from when the first slave responds to when the last one does. I hope this helps.

author
tony55555 made it!(author)2017-05-15

let's say i want connect two arduinos with one analog switch, on one side is RF 433 receiver with led on pin 13 and on another arduino is transmitter and i want to put between them one physical analog switch that when i turn on switch transmitter send impuls to receiver and led turns on?

author
hjsalom made it!(author)2017-05-01

Awesome,

I find it impossible to explain this easier than this.

Thanks.

author
CaoN3 made it!(author)2017-04-22

Is there any resistors in this circuit ??

author
michelkeijzers made it!(author)2017-03-29

Replace in the example the conditions from x == '0' and x == '3' to x == 0 and x == 3, otherwise it does not work.

author
MaAnnQ made it!(author)2017-01-27

What can i do to use I2c between arduinos 5-6 meters apart?

author
kadagm made it!(author)2017-03-14

https://www.youtube.com/watch?v=7rcVeFFHcFM

author
HerminiusM made it!(author)2017-02-10

I think that max. distance for I2C communication is around 35 meters.

author
s1003117s made it!(author)2017-02-14

When I enter the given code, I get an error message that says

exit status 1
'Wire' was not declared in this scope

I'm new to Arduino, what's missing?

author
Parker4312 made it!(author)2017-02-26

You have to put #include at the very top of the program (before any void) or you have brackets misplaced

author
Schrd1 made it!(author)2017-02-14

The most likely cause for this kind of message would be that the Arduino IDE doesn't recognize the Wire library. Try reinstalling the Wire library and / or make sure it is placed in the correct "library folder" on your hard drive.

author
BesTCooL made it!(author)2016-11-09

or example ı want master arduino 1. pin home lamb on off slave arduino 2. pin saloon lamb on off how write code ? on master arduino

author
saddamh8 made it!(author)2016-10-12

Hello I want to cannect arduino mega and arduino nano 3.3v via i2c with SparkFun Logic Level is it possible

author
saddamh8 made it!(author)2016-10-12

Hello I want to cannect arduino mega and arduino nano 3.3v via i2c with SparkFun Logic Level

author
Raphango made it!(author)2016-09-08

congratulations! Thanks!

author
VishalM17 made it!(author)2016-07-25

helllo i am ussing these code and testing it using proteus but when i run proteus only one time data is received by slave, i have connected i2c terminal, thus can say master is properly sending the data

author
Arb%C3%ABrE made it!(author)2016-07-05

Hello!
I'm new to arduino and I want to start a project in which I will use a lot of vibration sensors that will change the color or turn ON/OFF the led strip or led lamp and maybe a buzzer !
The sensors with LEDs and the buzzer will be attached to panels that after being hit with with a ball the led will turn on or of or maybe change the color!

Can someone help with this project!
What arduino boards should I use, what kind of vibration sensors and so one!

Thank you very much!

IMG_2178.JPG.jpegmaxresdefault.jpg
author
GyulaG made it!(author)2016-06-14

Thanks a lot, it was really helpful for me!

IMG_9863.JPG
author
JoeCreditINSTRUCT made it!(author)2016-03-19

I have connected a standard Arduino Uno with a RedBoard Uno precisely as shown. The Standard UNO is the slave and the RedBoard UNO is the master. Everything checks (numerous times) but after loading the sketches, after power up - nothing. Anybody have advice on what I left out? -Thanks

author
Joel777 made it!(author)2016-03-29

It would be nice to know if both boards' I2C ports are working. You can test this by connecting to any other I2C devices you may have lying around or else spend a few dollars to buy something like an I2C LCD panel on eBay.

author
AlG14 made it!(author)2015-11-28

If i want to do sensors in I2C, I see a lot of info that the sensors need to be "I2C sensors". But is it possible to use a simple sensor like a photocell (or a LM35 temperature sensor) and put it into the slave arduino? If this is done, the slave has an address(the slave arduino address), so the "address" requirement is met; but if this wouldn't work, why not?

author
Joel777 made it!(author)2016-03-29

Here is a very good article where he did exactly that: http://www.techbitar.com/how-to-network-many-arduinos-with-sensors-using-i2c.html

author
mhz-radio made it!(author)2015-11-15

Trying to download the PDF and I'm asked to login. I'm already logged in but unable to access the PDF. What's up with this???

author
liza+zaini made it!(author)2015-11-06

hello. im just learning how to use arduino. i got a question. how to connect multiple analog sensors to slave arduino uno. the master is also another arduino uno. i try it. but i only read one analog output from slave. but i want more then that. can anyone tell me how??? by the way, im using i2c and wire.h method. thanks.

author
wbanz made it!(author)2015-10-20

Hi, I have set this up and it works very well transferring data from the Master to the Slave and Serial Printing it.

But, I want to 'print' it to a TFT and this does not work.

My sketch for the slave writes header text to the TFT and then should write text sent from the master.

The header writes OK, however, as soon as the wire.onReceive event is triggered the TFT screen goes blank.

Anyone know why this may be?

Bill

author
pradipkhare made it!(author)2015-06-22

Hi Cornel,

First of all thank you very much for explaining the I2C concept using Arduino in a simple and straight forward way. I used your example and it worked like a charm (but after replacing old methods with read() and write() in new version of Arduino).

You helped me to generate interest in using the i2C communication than USART, where I struggled lots of to get the right values and not the garbled data.

However, I have a question, in my case, if master also has to receive response from the slave after they performed the action- let's called it acknowledgement. Could you pls provide your an expert advice how to achieve this? In other words, how to achieve bidirectional communication by Master and Slave ?

Currently, in UART, we can achive this by using both Tx & Rx at the same time.

Once again thanks for your support and publishing this topic here.

Regards,

Pradip

author
ThomasK19 made it!(author)2015-08-29

Hi Pradip,

Just implement the according protocol. You can send data to the slave and you can read data. So send a command to provide the data at a certain address. Eventually you need to instruct the slave to provide byte after byte.

author
XydenK made it!(author)2015-07-21

Hi,

I dunno any one asked before,so I asked again.

How to make Slave to Sent data to Master Arduino??

author
cornelam made it!(author)2015-07-22

Hi,

The Slave cannot directly write to the Master.
However, the master can request data from the Slave.
Here is a link to the procedure:
https://www.arduino.cc/en/Tutorial/MasterReader

author
tayebz1 made it!(author)2015-07-20

good

author
abhishekbaghel made it!(author)2015-07-16

hi,can anyone tell hoe to send a variable string using I2c protocol??

I want to send the variable type String name dataString using i2c protocol,wire library, Wire.write() function

author
cornelam made it!(author)2015-07-17

Write a for loop from 0 to the length of the string you want to write and for each iteration just put Wire.wirte(dataString[index]);

author
esg.827 made it!(author)2015-07-14

hello im quite new to arduino im trying to build a slider for my camera, with a tft screen and a stepper motor, i own a leonardo and a UNO is it possible to link these 2 together for one to work with the motor and the other to work with the screen?

author
cornelam made it!(author)2015-07-14

Yes, it is possible and I2C is one of the possible communication protocols which can connect them.

author
Mody+Ashraf made it!(author)2015-07-14

Thanks For explaining the i2c concept

author
pmap93 made it!(author)2015-05-19

Good Day!

This is really interesting, thanks for sharing!

Question though, how's the pin assignments ? Like, if MEGA is master then UNO is slave. D1 on Mega remains as pin 1 and the D1 of UNO would be what in coding?

Sorry if it doesn't seem clear, I'm learning Arduino :D

author
cornelam made it!(author)2015-05-19

Hello,

I don't really understand your question.
The digital pins have nothing to do with I2C, however, in general the pin numbers are the same across Arduinos.
For example, if you do digitalWrite(10, HIGH); It will do the same thing on all Arduino models - make pin 10 High...

Hope this helps.

You can also check my newly published book: Arduino Development Cookbook by Cornel Amariei on Amazon.

Best regards,
Cornel

author
pmap93 made it!(author)2015-05-20

OH, because I have an arduino UNO where the pins are all used up (CNC machine). I plan to buy another to incorporate an LCD display to my project, therefore I'll need to connect the LCD pins on another UNO.

But since Im connecting the two Arduinos together, do I still have to program them both separately or add the LCD codes to the master?

author
firermans93 made it!(author)2015-05-14

hello i want to make 1 master using mega 2560 and slave using 2 unit uno,how can my mega recognize the address of the uno to avoid sending data mistake,please help me

regard

author
cornelam made it!(author)2015-05-15

Hello,

The Mega has to be set as master and it has to know the addresses of the 2 Uno slaves.
Each Uno slave will have a different address.

Best regards,
Cornel

author
anirudh.mehlawat made it!(author)2015-04-10

hi....i want to rum two DC servo motors with arduino uno board, but i know that one uno board can move only two servo motors, but by interfacing two arduino uno, can i able to move 4 servo motors ... with some time delays ofcourse.

help me plz..in this regard

author
Live2Tinker made it!(author)2015-03-12

Hello, I'm not sure if anyone has asked this or not, but doesn't the arduino uno have 2 pins above pin AREF labeled SCL and SDA? Can't these pins be used without interfering with other pins? Plus, is it possible to use the internal pull-ups over externat ones?

author
KHIRUL+ALAMM made it!(author)2015-03-30

In the arduino uno analog pin A4 and analog pin A5 work as SDL and SCL

author
cornelam made it!(author)2015-03-12

Hello,

Yes, If you have a newer R3 board with independent SDA and SCL pins you can use those.
Also, no external resistors are required anymore, as they are built in.

Best regards,
Cornel

About This Instructable

515,988views

561favorites

License:

Bio: Inventor, Author, Senior R&D Engineer, Entrepreneur, Forbes 30 Under 30
More by cornelam:Arduino Servo MotorsArduino Distance SensorsArduino Stepper Motors
Add instructable to: