30 I2C: Transactions and Bus Design
30.1 Overview
This first route builds I2C from electrical signaling through addressed transactions and bus constraints.
This is part 1 of 2. Continue with I2C: Bring-Up and Diagnosis for the second focused route.
30.2 Start With Many Chips Sharing Two Wires
Find the First Device Holding the Shared Bus
Picture three sensors sharing two wires until adding a fourth makes every reading stop. A microcontroller means a small computer on one chip that starts transfers and controls the device.
Name each address, pull-up, wire length, bus voltage, clock rate, and expected reply. Test one sensor, all sensors, a duplicate address, and a device holding a line low.
Keep the wiring, settings, address scan, signal edges, acknowledgements, and failure time. This proves one local bus setup, not every board layout; the deeper sections explain transfers, electrical limits, timing, arbitration, and recovery.
I2C is useful because one controller can talk to many nearby devices using only SDA and SCL. The shared bus works only when addresses, pull-ups, capacitance, timing, and acknowledgements all stay inside the design limits.
Follow one read from controller to sensor and back. The story shows why a missing ACK, slow edge, duplicate address, or stretched clock is not a mystery; it is a specific bus promise being broken.
30.4 Learning Objectives
By the end of this section, you will be able to:
- Explain I2C Architecture: Describe the two-wire bus structure with SDA and SCL, and justify why open-drain outputs require pull-up resistors
- Calculate Pull-Up Resistor Values: Apply the RC rise-time formula to select appropriate resistor values for a given bus capacitance and speed mode
- Distinguish I2C Addressing: Identify how 7-bit addresses map to write and read bytes, and select device addresses to avoid bus conflicts
- Implement I2C Transactions: Explain the read and write transaction sequences (START, address frame, ACK, data, STOP) and translate them into test steps
- Diagnose I2C Failures: Analyze bus-level symptoms — missing ACK, slow rise times, address conflicts, clock stretching — and identify their root causes
- Build I2C Applications: Plan and verify sensor/display connections over a shared I2C bus before writing firmware
I2C (pronounced eye-squared-see) is a simple way to connect multiple sensors and chips using just two wires. Think of it as a shared phone line where each device has its own phone number — the main controller calls each device by its address and they take turns sharing information. It is one of the most common ways to connect sensors in IoT projects.
“I love I2C!” said Temperature Terry. “I only need two tiny wires — SDA for data and SCL for the clock — to talk to Max. And I am not alone on those wires. There can be up to 112 of us sensors sharing the same two wires!”
the microcontroller explained how it works. “I am the master. When I want Sammy’s temperature reading, I send his address — say 0x48 — on the bus. Only Sammy responds. Then I send a request, and he sends back the data. Everyone else stays quiet because it was not their address.”
“The pull-up resistors are super important though,” warned the LED. “The wires need them to work properly. If you forget the pull-ups, nothing talks! It is the number one beginner mistake with I2C. And sometimes two sensors accidentally have the SAME address — then you get conflicts.”
“I2C is not the fastest,” admitted the battery, “only 100 to 400 kHz for most IoT work. But it is incredibly simple — just two wires for dozens of sensors! Perfect for when you have a temperature sensor, a humidity sensor, a pressure sensor, and a display all connected to one microcontroller. Minimal wiring, maximum flexibility.”
30.5 Prerequisites
Before diving into this chapter, you should be familiar with:
- Wired Communication Fundamentals: Understanding of synchronous communication, multi-drop topology, master-slave architecture
- Digital Electronics: Understanding of open-drain outputs and pull-up resistors
Follow one shared I2C bus from wiring to release:
- First identify why SDA, SCL, open-drain outputs, and pull-ups make many devices share two wires.
- Then map each device to a unique address and translate the 7-bit address into write and read bytes.
- Next walk the START, ACK, repeated START, data, and STOP sequence that makes a real transaction work.
- After that use scanner and BME280 labs to turn bus symptoms into evidence.
- Finally calculate pull-up limits and build a reliability record for speed, capacitance, lockup, and recovery.
Checkpoints recap the main design decisions; collapsed material deepens the same path.
30.6 I2C Overview
Start with the physical promise: every device sees the same two wires, so the bus only works if each participant releases the lines and waits its turn.
I2C (IIC, I-squared-C) is a popular multi-device communication bus developed by Philips (now NXP) in the 1980s.
Pronunciation: “I-squared-C” or “I-two-C”
Full name: Inter-Integrated Circuit
30.6.1 Characteristics
| Feature | Value |
|---|---|
| Wires | 2 only (SDA + SCL) |
| Topology | Multi-drop (bus) |
| Sync/Async | Synchronous (SCL = clock) |
| Duplex | Half-duplex (SDA is bidirectional) |
| Speed | 100 kHz (standard), 400 kHz (fast), 1 MHz (fast+), 3.4 MHz (high-speed) |
| Distance | <1 meter (same PCB or short cable) |
| Devices | Up to 112 (7-bit addressing) or 1024 (10-bit) |
| Master/Slave | Multi-master capable |
To test characteristics, open the diagram in Figure 30.1. I2C Bus Connections supplies one named condition; Two-Wire Serial Interface (SDA + SCL) supplies the necessary comparison for physical i2c wiring: two lines (sda and scl) run across all devices on the bus. pull-up resistors hold both lines high by default; any device can.
Locate I2C Bus Connections on Figure 30.1 before checking Two-Wire Serial Interface (SDA + SCL). The visual’s third anchor, V CC, completes physical i2c wiring: two lines (sda and scl) run across all devices on the bus. pull-up resistors hold both lines high by default; any device can. Carry I2C Bus Connections into characteristics; use V CC as its limiting condition.
30.7 Why I2C is Popular
Advantages:
- Only 2 wires (minimal pin usage)
- Multiple devices on same bus
- Simple addressing (each device has unique address)
- Bidirectional (master can read/write to slaves)
- Well-supported by sensors, displays, EEPROMs
30.8 I2C Signals
Figure 30.2 makes i2c signals inspectable through I2C Bus Wiring with Pull-Up Resistors and Master MCU. Those diagram labels establish the scope of i2c bus wiring with pull-up resistors.
At I2C Bus Wiring with Pull-Up Resistors in Figure 30.2, compare the diagram with Master MCU; then locate SDA/SCL. That labelled check bounds i2c bus wiring with pull-up resistors. For i2c signals, retain SDA/SCL as evidence for the resulting choice.
SDA (Serial Data):
- Bidirectional data line
- Carries address and data
- Open-drain (requires pull-up resistor)
SCL (Serial Clock):
- Clock signal from master
- Slaves can hold it LOW (“clock stretching”) to slow master
- Open-drain (requires pull-up resistor)
30.9 Pull-Up Resistors
Treat pull-up selection as a bounded electrical calculation. Start with the highest resistor that still charges the measured bus capacitance within the mode’s rise-time limit, then check the lowest resistor that every connected device can safely pull below the permitted low-level voltage. Compare the resulting window with the fitted value, not with a universal favourite. A 4.7 kΩ part is common because it often fits short 100 kHz or 400 kHz boards, but cable length, device count, level shifting, and breadboard capacitance can move the valid window. Verify the decision on SDA and SCL with an oscilloscope at the intended clock rate.
Critical requirement: Both SDA and SCL need pull-up resistors to VCC.
Typical values:
- 4.7 kohm - Most common (400 kHz, few devices, short traces)
- 2.2 kohm - For longer cables, many devices, or fast mode
- 10 kohm - For very short cables, few devices, 100 kHz only
Why needed? I2C uses open-drain outputs - can only pull LOW, not HIGH. Pull-up resistors provide the HIGH level. See the detailed calculation in the Worked Example section for guidance on choosing the right value.
Checkpoint: Shared Bus Basics
You now know:
- I2C gets its pin savings from two shared lines, SDA and SCL, rather than one private wire per peripheral.
- Open-drain signalling means devices pull low or release; pull-up resistors create the high level.
- That same sharing makes capacitance, pull-up strength, and bus length design constraints.
The wiring is only half the contract. Once every device is attached to SDA and SCL, the controller still needs a way to choose exactly one responder.
30.10 I2C Addressing
Each device on the bus needs a unique 7-bit address.
Address space:
- 7-bit addresses: 0x08 to 0x77 (112 addresses)
- Some addresses reserved (0x00-0x07, 0x78-0x7F)
Common I2C device addresses:
| Device | Address (Hex) | Address (Decimal) |
|---|---|---|
| OLED Display (SSD1306) | 0x3C or 0x3D | 60 or 61 |
| BME280 (Temp/Humidity) | 0x76 or 0x77 | 118 or 119 |
| MPU6050 (IMU) | 0x68 or 0x69 | 104 or 105 |
| RTC DS3231 | 0x68 | 104 |
| EEPROM 24C256 | 0x50 - 0x57 | 80 - 87 |
Finding device addresses:
Use an I2C scanner when a board powers up but a sensor library cannot find its device.
| Step | What you check | Expected evidence |
|---|---|---|
| 1. Power and ground | Sensor VCC and GND match the controller voltage | Sensor board powers on; no hot components |
| 2. Bus wiring | SDA to SDA, SCL to SCL, shared ground | Scanner can probe the bus without lockup |
| 3. Pull-ups | SDA and SCL have pull-ups to the correct voltage | Lines idle HIGH on a meter or oscilloscope |
| 4. Address scan | Probe addresses from 0x08 to 0x77 | Known devices appear at their documented addresses |
| 5. Conflict check | Compare detected addresses against the design | Duplicate addresses are resolved with address pins or a mux |
Example scan result:
| Detected address | Likely device | What to do next |
|---|---|---|
0x3C | OLED display | Use the OLED library with address 0x3C. |
0x76 | BME280/BMP280 | Use the sensor library with address 0x76. |
| No addresses | Wiring, pull-up, or power problem | Check SDA/SCL order, VCC, ground, and pull-up resistors. |
30.11 I2C Communication Protocol
To test i2c communication protocol, open the diagram in Figure 30.3. I2C Signal Timing Diagram supplies one named condition; Two-Wire Serial Communication Protocol supplies the necessary comparison for i2c protocol timing: start and stop conditions frame each transaction, with data sampled on scl rising edge. the acknowledgment bit after each byte.
Trace the visual from I2C Signal Timing Diagram to Two-Wire Serial Communication Protocol in Figure 30.3; verify SDA before concluding. Together those labels make i2c protocol timing: start and stop conditions frame each transaction, with data sampled on scl rising edge. the acknowledgment bit after each byte testable. Apply their boundary when working through i2c communication protocol. Start and Stop Conditions:
| Bus event | SDA behavior | SCL behavior | Meaning |
|---|---|---|---|
| Idle bus | HIGH | HIGH | Pull-up resistors are holding both lines released. |
| START | HIGH to LOW | Stays HIGH | The controller claims the bus and begins a transaction. |
| Data bit | Stable while sampled | Pulses LOW/HIGH | The receiver reads SDA while SCL is HIGH. |
| STOP | LOW to HIGH | Stays HIGH | The controller releases the bus after the transaction. |
Data Transfer (1 byte + ACK):
| Phase | Who drives SDA? | What the receiver checks |
|---|---|---|
| 8 data bits | Transmitter | Bits arrive MSB first while SCL pulses. |
| ACK clock | Receiver | Pulls SDA LOW for ACK, leaves it HIGH for NACK. |
| Next byte or STOP | Controller | Continues with another byte, a repeated START, or STOP. |
Data transfer rules:
- SDA can only change when SCL is LOW
- SDA is sampled when SCL is HIGH
- Data transmitted MSB first (most significant bit first)
Pause at Figure 30.4 before carrying i2c communication protocol forward. Its visual vocabulary joins I2C Signal Timing Diagram to START Condition, which frames i2c communication protocol timing showing complete transaction.
Locate I2C Signal Timing Diagram on Figure 30.4 before checking START Condition. The visual’s third anchor, SDA goes low before SCL, completes i2c communication protocol timing showing complete transaction. Carry I2C Signal Timing Diagram into i2c communication protocol; use SDA goes low before SCL as its limiting condition.
30.12 I2C Write Transaction
The next claim about i2c write transaction depends on Figure 30.5. Its diagram makes I2C Write Transaction Sequence and SDA falls while SCL explicit within i2c write transaction sequence.
Compare I2C Write Transaction Sequence with SDA falls while SCL inside the visual at Figure 30.5. Next find high, which completes the scope of i2c write transaction sequence. The decision in i2c write transaction must preserve that labelled boundary.
Steps:
- Master sends START
- Master sends slave address + write bit (0)
- Slave acknowledges (ACK)
- Master sends register address
- Slave ACKs
- Master sends data byte
- Slave ACKs
- Master sends STOP
30.13 I2C Read Transaction
Pause at Figure 30.6 before carrying i2c read transaction forward. Its visual vocabulary joins I2C Read with Repeated START to address + write, which frames i2c read transaction with restart condition.
-
Pete starts the bus and sends the address in write mode.
-
The sensor confirms, then Pete sends the register.
-
A repeated start keeps the same transaction alive.
-
Pete sends the address again in read mode.
-
The sensor sends data, and Pete ends the final byte.
-
A stop releases both shared wires.
Within the diagram, I2C Read with Repeated START opens Figure 30.6; address + write provides the counterpoint, and Register closes the inspection. This reading constrains i2c read transaction with restart condition and supplies the visual evidence for i2c read transaction.
Steps:
- Master sends START
- Master sends slave address + write bit (0)
- Slave ACKs
- Master sends register address to read from
- Slave ACKs
- Master sends REPEATED START (restart without releasing bus)
- Master sends slave address + read bit (1)
- Slave ACKs
- Slave sends data byte(s); master ACKs each except the last
- Master sends NACK on final byte (signals end of read)
- Master sends STOP
The Repeated START (step 6) is essential: it lets the master switch from write mode (selecting the register) to read mode (receiving data) without another device claiming the bus in between.
Checkpoint: Addressed Transactions
You now know:
- A normal 7-bit bus uses usable addresses from 0x08 to 0x77, so duplicate module defaults must be planned before wiring.
- Address 0x76 becomes 0xEC for the write phase and 0xED for the read phase because the direction bit is part of the first bus byte.
- A register read is a two-phase exchange: write the register pointer, issue repeated START, then read the returned data before STOP.
With the bus grammar in place, the next question is practical: can the real board prove that those frames are reaching real devices?
30.14 Arduino/ESP32 I2C Example
The transaction diagrams and address explorer above are the beginner path. Use this sketch only when you are ready to test a real I2C sensor.
Before applying the specification, inspect the real mpu6050 6-axis imu (accelerometer + gyroscope) below: its package, terminals, scale, and installation context are part of the engineering evidence.
Carry those visible constraints into the surrounding analysis; the abstract symbol or capability name does not capture mounting, wiring, protection, or service access.
| Task | I2C concept being tested | Success evidence |
|---|---|---|
| Wire SDA/SCL correctly | Shared two-wire bus | Scanner detects 0x68 or 0x69. |
| Wake the sensor | Write transaction to a control register | The device stops reporting sleep/default values. |
| Select the X-axis register | Write phase before a register read | Logic trace shows address + write, register byte, repeated START. |
| Read two data bytes | Repeated START and read phase | Two bytes arrive and combine into a signed acceleration value. |
| Repeat slowly first | Stable bus before performance tuning | Values update without missing ACKs or bus lockups. |
The visual evidence for optional mpu6050 build checklist sits in Figure 30.7. Find a row of pin headers along one edge beside 0x68 by default or 0x69 before interpreting a gy-521 breakout carrying the mpu6050 — the board this checklist wires up. the scanner step above is checking for exactly this chip’s i2c address,.
Begin Figure 30.7 with a row of pin headers along one edge, then distinguish 0x68 by default or 0x69 and AD0 pulled high. The diagram separates a row of pin headers along one edge from 0x68 by default or 0x69 within a gy-521 breakout carrying the mpu6050 — the board this checklist wires up. the scanner step above is checking for exactly this chip’s i2c address,. Keep both distinctions explicit in optional mpu6050 build checklist.
ESP32 wiring reference:
| ESP32 pin | Sensor pin | Note |
|---|---|---|
| GPIO 21 | SDA | Data line; add a pull-up if the sensor board lacks one. |
| GPIO 22 | SCL | Clock line; keep wires short for reliable fast mode. |
| 3.3 V | VCC | Match the sensor module voltage. |
| GND | GND | All I2C devices need a shared ground. |
30.15 Clock Stretching
Problem: Slave needs more time to process data.
Solution: Slave holds SCL LOW to pause communication.
| Step | What happens on SCL | What the controller should do |
|---|---|---|
| Controller releases SCL | SCL should rise HIGH | Wait for the line to actually go HIGH. |
| Device needs more time | Device holds SCL LOW | Do not force the next clock edge. |
| Device finishes processing | Device releases SCL | Resume the transaction. |
| Timeout exceeded | SCL remains LOW too long | Reset or recover the bus. |
Use case: Slow sensors (temperature readings take time), EEPROM write operations.
Avoiding Address Conflicts:
- Check device datasheets before buying
- Many sensors have address select pins (A0, AD0) to change address
- Use I2C scanner sketch to verify addresses
- Plan device selection to avoid conflicts
Common Conflicts:
- 0x68: MPU6050, DS1307/DS3231 RTC → Use MPU6050 AD0 pin for 0x69
- 0x76/0x77: BMP280, BME280, BME680 → Use SDO pin
- 0x27/0x3F: LCD backpack modules → Check board
Pull-up Resistors:
- 4.7k: Most common (400 kHz)
- 2.2k: Long cables or many devices
- 10k: Short cables, few devices
Pull-up resistor values aren’t arbitrary—they’re calculated from RC time constant requirements.
For I2C fast mode (400 kHz), the rise time must be under 300 ns (from 0 V to 70% of VCC, the I2C sampling threshold). With typical bus capacitance pF (3 devices + PCB traces):
Solving for maximum resistance:
| Step | Value |
|---|---|
| Rise-time limit | 300 ns |
| Bus capacitance | 50 pF |
| Maximum pull-up | 300 ns ÷ (0.8473 × 50 pF) = 7,080 Ω |
The I2C spec also requires minimum current drive capability of 3 mA at 0.4 V LOW level. With 3.3 V supply:
| Step | Value |
|---|---|
| Available voltage across pull-up | 3.3 V - 0.4 V = 2.9 V |
| Allowed sink current | 3 mA |
| Minimum pull-up | 2.9 V ÷ 0.003 A = 967 Ω |
This gives a range of 967 Ω to 7,080 Ω for a 50 pF bus. The standard 4.7 kΩ falls well within this range—which is why it works reliably for most setups. With 100 pF bus capacitance (many devices or long traces), the maximum drops to ~3.5 kΩ, so 2.2 kΩ pull-ups are needed.
30.16 Hands-On Lab: I2C Scanner
Objective: Find all I2C devices connected to your ESP32/Arduino.
| Stage | Student action | Evidence to record |
|---|---|---|
| Baseline | Scan with no external sensor attached | No unexpected addresses, or only built-in board devices. |
| Add display | Connect SSD1306 OLED | New address appears at 0x3C or 0x3D. |
| Add sensor | Connect BME280/BMP280 | New address appears at 0x76 or 0x77. |
| Conflict test | Add a second device with the same address if available | Scanner still shows one address, but both devices may respond at once. |
| Fix | Change address pin or use an I2C multiplexer | Each device becomes uniquely selectable. |
Sample scan interpretation:
| Scanner output | Meaning | Next action |
|---|---|---|
0x3C, 0x76 | OLED and BME280 are both visible | Start the sensor/display application. |
Only 0x3C | Sensor not responding | Check BME280 power, SDA/SCL order, and address pin. |
| No addresses | Bus-level fault | Check pull-ups, ground, VCC, and whether SDA/SCL are swapped. |
30.17 Hands-On Lab: BME280 Temperature Sensor
Objective: Read temperature from BME280 sensor via I2C.
The visual evidence for hands-on lab: bme280 temperature sensor sits in Figure 30.8. Find A small BME280 breakout board beside a square metal-capped sensor package before interpreting a bme280 breakout board like the one this lab targets. the exposed metal-capped sensor is what the scanner below detects at 0x76 or 0x77, and the.
Begin Figure 30.8 with A small BME280 breakout board, then distinguish a square metal-capped sensor package and a row of pin headers. The diagram separates A small BME280 breakout board from a square metal-capped sensor package within a bme280 breakout board like the one this lab targets. the exposed metal-capped sensor is what the scanner below detects at 0x76 or 0x77, and the. Keep both distinctions explicit in hands-on lab: bme280 temperature sensor.
30.18 Continue to Part 2
Continue with I2C: Bring-Up and Diagnosis.
