The I2C bus is a synchronous serial protocol that allows connecting multiple devices sharing only two lines. Its great advantage is that it drastically reduces wiring and makes it very convenient to chain sensors, memories, or displays.
If UART was a private call between two people, I2C is more like a shared room where one master asks questions and the others respond when it’s their turn. That’s why it’s one of the most used buses in embedded electronics.
The Wires: SDA and SCL
Physically, the I2C bus consists of two lines (plus the common GND):
- SDA (Serial Data): Data (zeros and ones) travels here. It is bidirectional (the master asks, the slave answers).
- SCL (Serial Clock): This is the clock signal.
- Unlike UART, I2C is Synchronous.
- The controller generates the clock, and data is read at that pace. All devices must support the frequency used; some peripherals can stretch a low clock level through clock stretching.
Controllers and Peripherals
- Controller: Usually your microcontroller (Arduino/ESP32). It controls the clock (SCL) and initiates all conversations.
- Peripherals: The peripherals (Sensor, OLED Display, EEPROM Memory). They stay silent listening to the bus until the Master calls them by their name.
The Concept of Address
If all sensors are connected to the same two wires, how does the temperature sensor know I’m talking to it and not the display?
Thanks to hexadecimal addresses. Each I2C chip comes from the factory with a unique 7-bit “identification number”.
- Typical OLED Display:
0x3C - MPU6050 Sensor (Accelerometer):
0x68 - DS3231 RTC Clock:
0x68(Beware, conflicts!)
The protocol works like this:
The Controller shouts on the SDA line: “Attention address 0x3C!”
All sensors listen.
The accelerometer (0x68) says: “That’s not me” and goes back to sleep.
The display (0x3C) says: “That’s me!” and sends an acknowledgment signal (ACK).
From there, the Controller and Display exchange data while the others remain silent.
I2C Scanner: If you don’t know a chip’s address (or think it’s broken), there’s a basic Arduino code called “I2C Scanner” that tests all possible addresses and tells you which ones received a response. It’s the number one diagnostic tool.
Bus Physics: Open-Drain and Pull-ups
In the GPIO article, we saw the Open-Drain configuration. I2C uses this topology.
This means the chips only know how to connect the wire to Ground (GND) to create a “0”. But they don’t know how to connect the wire to 5V to create a “1”. They simply “release” the wire.
Why? Because if one chip tried to set 5V and another tried to set 0V simultaneously, we would have a short circuit. With Open-Drain, the worst that happens is that 0 wins.
The Pull-up Resistors
Since no one “pushes” towards 5V, we need external help.
The bus needs pull-up devices on SDA and SCL, whether they are on the main board, a module, or added externally.
- When no one is talking, the resistors “pull” the voltage up → The line is HIGH.
- When someone wants to send a “0”, they connect the line to ground and overcome the resistor → The line goes LOW.
Many commercial modules (breakout boards) already come with these resistors soldered on. But if you use bare chips and forget the resistors, I2C will not work. Typical values: 4.7kΩ (for 5V) or 2.2kΩ (for 3.3V and high speed).
The Conversation (The Frame)
A typical transmission has these steps:
- Start Condition: The Master pulls SDA low while SCL is still high.
- Address Frame: The Master sends the 7-bit address + 1 bit indicating if it wants to Read (1) or Write (0).
- ACK/NACK: The Slave responds by pulling the SDA line low for an instant (ACK) to say “I heard you”. If no one responds, the line stays high (NACK), and the Master knows there’s an error.
- Data Frames: Data bytes (8 bits) are sent, each confirmed by an ACK.
- Stop Condition: The Master releases the line.
Advantages and Disadvantages
| Feature | I2C | UART |
|---|---|---|
| Wires | 2 (for many devices) | 2 (per pair) |
| Speed | Medium (100kHz - 400kHz standard) | Low/Medium |
| Complexity | Medium (Addresses, Pull-ups) | Low |
| Distance | Very Short (PCB, < 30cm) | Short |
| Robustness | Sensitive to electrical noise | More robust |
I2C is great, but it’s “slow” for moving large amounts of data (like video or audio) and sensitive to noise.
If we need raw speed and robustness to talk to an SD card or a fast color display, we need the Ferrari of protocols: SPI.