13  Sensor Communication Protocols

I2C, SPI, and Serial Interfaces for IoT Sensors

sensing
protocols
i2c
spi
interfaces
Author

IoT Textbook

Published

July 21, 2026

Keywords

I2C, SPI, UART, serial communication, sensor interface, ESP32, Arduino, bus protocol

Start With the Measurement Story

A sensor bus is a conversation with timing, addressing, voltage, and error rules. Before wiring I2C, SPI, or UART, decide who talks, who listens, how conflicts are avoided, and how a failed read will be detected.

13.1 In 60 Seconds

Sensor communication protocols (I2C, SPI, UART) are the “languages” sensors and microcontrollers use to exchange data. I2C uses just two wires and supports dozens of sensors on one bus, while SPI trades extra wires for much faster data transfer. Choosing the right protocol depends on your speed needs, available GPIO pins, and how many sensors you are connecting.

Phoebe the physics guide

Phoebe’s Why

I2C’s SDA and SCL lines are open-drain: a device can only pull the line low, never drive it high. The pull-up resistor and the bus’s own parasitic capacitance – wire, pins, ESD structures – are what pull the line back up, and that recovery is not instant. It is a first-order RC charging transient, the same time constant \(\tau=RC\) that governs any resistor charging a capacitor. The I2C specification cares whether the line crosses from its low threshold to its high threshold before the next clock edge needs it there, which is exactly why this chapter’s own key-concepts line hedges its pull-up value with a clock speed – “4.7 kohm at 100 kHz” – instead of naming one resistor for every mode. The wire itself is a separate story: at I2C’s clock frequencies, and even its fast edge-rate harmonics, the bus is only a tiny fraction of a wavelength long, so it behaves as a lumped RC network rather than a transmission line – which is why I2C design worries about capacitance and pull-up value, not the cable matching an RF antenna feed line must have.

The Derivation

Open-drain rise through a pull-up into bus capacitance:

\[V(t) = V_{DD}\left(1-e^{-t/RC}\right), \qquad \tau=RC\]

I2C rise time is specified between \(0.3V_{DD}\) and \(0.7V_{DD}\):

\[t_r = RC\,\ln\!\left(\frac{0.7}{0.3}\right) \approx 0.847\,RC\]

A bus stays a lumped element, not a transmission line, while its physical length is much shorter than the signal wavelength:

\[\ell \ll \lambda = \frac{c}{f}\]

Worked Numbers: This Chapter’s Own Bus Numbers

  • Worst case per spec: \(R=4.7\text{k}\Omega\), \(C=400\) pF (the standard/fast-mode ceiling this chapter’s own bus-capacitance estimator checks against): \(\tau=RC=1.88\ \mu\text{s}\), \(t_r=0.847\times1.88\ \mu\text{s}=1.59\ \mu\text{s}\) – slower than even the 1000 ns Standard-mode rise-time limit. A bus that actually reaches 400 pF cannot run reliably at 4.7 kohm even at 100 kHz, which is why 400 pF is a hard ceiling, not a target.
  • Realistic multi-sensor bus (this chapter’s own calculator defaults: 30 cm wire + 3 sensors at 10 pF each \(\approx60\) pF): \(\tau=4700\times60\text{pF}=282\) ns, \(t_r=0.847\times282\text{ns}=239\) ns – inside the 300 ns Fast-mode limit, which is why the “typically 0.5-2 meters” wiring guidance above works in practice.
  • Solving the Fast-mode limit backwards at the 400 pF ceiling: \(R\le300\text{ns}/(0.847\times400\text{pF})=885\ \Omega\) – far below 4.7 kohm, which is exactly why fast, heavily-loaded buses use smaller pull-ups (often 1-2.2 kohm) instead of the beginner-friendly 4.7 kohm value.
  • Electrically-short check: even a 10 MHz edge-rate harmonic has \(\lambda=c/f=30.0\) m in free space; a 2 m bus is \(2/30.0=6.67\%\) of that wavelength – short enough for the lumped RC model above to hold. An RF feedline anywhere near a wavelength long would need transmission-line matching instead; a bus this short never does.
Key Concepts
  • I2C (Inter-Integrated Circuit): A two-wire serial protocol (SDA data, SCL clock) supporting multiple devices on one bus using 7-bit addresses; standard speed 100 kHz, fast mode 400 kHz, fast-plus 1 MHz
  • SPI (Serial Peripheral Interface): A four-wire full-duplex protocol (MOSI, MISO, SCK, CS) offering higher speed than I2C (up to tens of MHz) but requiring a dedicated chip-select line per device
  • UART (Universal Asynchronous Receiver/Transmitter): An asynchronous two-wire protocol (TX, RX) using agreed baud rates; simple and universal but limited to point-to-point connections with no inherent bus topology
  • 1-Wire: A single-wire protocol (plus ground) supporting multiple addressable devices; commonly used by DS18B20 temperature sensors; slow but minimal wiring
  • Pull-Up Resistors on I2C: I2C SDA and SCL lines use open-drain signaling and require external pull-up resistors (typically 4.7 kohm at 100 kHz) to define the HIGH state between transactions
  • Address Conflicts: Two I2C devices with the same address on the same bus cause data corruption. Check all sensor addresses before designing a multi-sensor board; some sensors offer address-select pins
  • Clock Stretching: An I2C feature where a slow slave holds SCL low to pause the master while preparing data; not all masters support it — check the microcontroller documentation before relying on this feature
  • Logic Level Compatibility: Mixing 3.3 V and 5 V devices on the same I2C or SPI bus can damage 3.3 V inputs. Use bidirectional level shifters or verified series-resistor approaches when mixing voltage domains

13.2 Learning Objectives

By the end of this chapter, you will be able to:

  • Differentiate between I2C, SPI, and UART communication protocols based on wiring, speed, and topology
  • Configure an I2C bus with correct pull-up resistors and address assignments for multi-sensor applications
  • Implement SPI communication with proper mode selection for high-speed sensor data transfer
  • Diagnose common protocol issues including address conflicts, missing pull-ups, and SPI mode mismatches
  • Evaluate and justify the appropriate protocol for specific sensor requirements and constraints

13.3 Introduction

Sensor communication protocols are the foundation of IoT data acquisition. Every sensor reading must travel from the physical sensor to your microcontroller through a defined communication interface. Understanding these protocols enables you to design reliable, efficient sensor networks.

Think of communication protocols like different languages. Just as people need to speak the same language to understand each other, sensors and microcontrollers need to “speak” the same protocol to exchange data. The most common “languages” are I2C (pronounced “eye-squared-see” or “eye-two-see”), SPI (“spy”), and UART (“you-art”). Each has different rules about how many wires to use, how fast to talk, and how to address specific devices.

13.4 I2C Communication Protocol

15 min | Intermediate | P06.C09.U01a

I2C (Inter-Integrated Circuit) is a two-wire synchronous protocol perfect for connecting multiple sensors using minimal GPIO pins. It uses:

  • SDA (Serial Data): Bidirectional data line
  • SCL (Serial Clock): Clock signal from master
  • 7-bit addressing: Up to 112 usable device addresses (128 total, 16 reserved)
  • Pull-up resistors: Required on both lines

13.4.1 I2C Protocol Sequence

I2C protocol sequence diagram showing master-slave communication: START condition, 7-bit address with write bit, register address, repeated START, read data byte, NACK, and STOP condition with key protocol elements explained.
Figure 13.1: I2C Protocol Sequence: Reading Temperature from BMP280 Sensor
Geometric diagram of I2C bus architecture showing master microcontroller, multiple slave devices with unique addresses, shared SDA and SCL lines, pull-up resistors, and bidirectional data flow for multi-device sensor networks
Figure 13.2: I2C bus architecture for multi-sensor networks

13.4.2 Key I2C Protocol Elements

  • START Condition: SDA goes LOW while SCL is HIGH (signals transaction start)
  • STOP Condition: SDA goes HIGH while SCL is HIGH (signals transaction end)
  • ACK (Acknowledge): Receiver pulls SDA LOW during 9th clock pulse (data received successfully)
  • NACK (Not Acknowledge): Receiver leaves SDA HIGH (last byte or error)
  • Repeated START: START without preceding STOP (direction change from write to read)

13.4.3 I2C Implementation Example

Reading sensor data over I2C follows a two-phase pattern: first write the register address you want to read, then request the data bytes. The endTransmission(false) sends a Repeated START instead of a STOP, keeping the bus locked for the subsequent read.

For learning, trace the transaction before reading code:

I2C Read Transaction
  1. Send START.
  2. Send the sensor address with the write bit.
  3. Send the register address you want to read.
  4. Send REPEATED START.
  5. Send the sensor address with the read bit.
  6. Read the data bytes.
  7. Send STOP.

13.4.4 Optional C++ Pattern

#include <Wire.h>

#define I2C_SDA 21
#define I2C_SCL 22
#define BMP280_ADDR 0x76
#define BMP280_CHIP_ID_REG 0xD0

void setup() {
  Serial.begin(115200);
  Wire.begin(I2C_SDA, I2C_SCL);

  // Read chip ID register to verify communication
  uint8_t chipId;
  readI2CRegister(BMP280_ADDR, BMP280_CHIP_ID_REG, &chipId, 1);
  Serial.print("BMP280 Chip ID: 0x");
  Serial.println(chipId, HEX);  // Should print 0x58 for BMP280
}

void readI2CRegister(uint8_t addr, uint8_t reg, uint8_t* data, uint8_t len) {
  Wire.beginTransmission(addr);
  Wire.write(reg);                // Phase 1: Write register address
  Wire.endTransmission(false);    // Repeated START (no STOP)

  Wire.requestFrom(addr, len);    // Phase 2: Read data bytes
  for(int i = 0; i < len; i++) {
    if(Wire.available()) {
      data[i] = Wire.read();
    }
  }
}

void loop() { }

Estimate total bus capacitance to determine if your I2C bus will work reliably. The I2C specification limits bus capacitance to 400 pF for standard mode and fast mode.

This simulation demonstrates how I2C bus scanning works. Add devices to the bus, then click “Scan Bus” to see the master controller query each address and detect ACK/NACK responses.

13.5 SPI Communication Protocol

15 min | Intermediate | P06.C09.U01b

SPI (Serial Peripheral Interface) is a synchronous, full-duplex communication protocol using four lines: MISO (Master In Slave Out), MOSI (Master Out Slave In), SCK (Serial Clock), and CS (Chip Select). Unlike I2C, SPI supports simultaneous bidirectional data transfer.

SPI protocol diagram showing four-wire full-duplex communication between master ESP32 and slave SD card with MOSI, MISO, SCK, and CS signal lines and bidirectional data flow.
Figure 13.3: SPI Protocol Communication: Full-Duplex SD Card Read Transaction

13.5.1 SPI vs I2C Comparison

Feature I2C SPI
Wires 2 (SDA, SCL) 4+ (MISO, MOSI, SCK, CS per device)
Speed 100 kHz - 3.4 MHz (standard/fast/high-speed) 1-100 MHz
Topology Multi-master, multi-slave Single master (typical), multi-slave
Addressing 7-bit addresses (112 usable) Hardware CS pins (limited by GPIO)
Data Transfer Half-duplex (sequential) Full-duplex (simultaneous)
Protocol Overhead START, STOP, ACK/NACK Minimal (just CS selection)
Typical Use Multiple sensors, displays High-speed: SD cards, displays, ADCs
GPIO Efficiency High (2 pins for many devices) Low (3 shared + 1 CS per device)

Calculate the effective data throughput for your SPI configuration based on clock speed and transaction overhead.

13.5.2 When to Choose Each Protocol

Choose I2C when:

  • Multiple sensors needed (temperature, pressure, IMU, light)
  • Limited GPIO pins available
  • Moderate data rates sufficient (<50 kB/s)
  • Moderate cable length (limited by 400 pF bus capacitance; typically 0.5-2 meters depending on number of devices and wire type)

Choose SPI when:

  • High-speed data transfer required (>1 MB/s)
  • Large data blocks (SD cards, displays)
  • Real-time requirements (<1 ms latency)
  • Plenty of GPIO pins available
Try It: GPIO Pin Budget Calculator

Plan your wiring by entering how many I2C, SPI, and UART devices you need. The calculator shows total GPIO pin usage and whether your microcontroller has enough pins.

I2C vs SPI for Sensor Nodes

Option A: I2C bus (BME280 + BH1750 + MPU6050): Wire count 2 (SDA, SCL shared), GPIO usage 2 pins total for 3+ sensors, max speed 400kHz (~44kB/s), read latency ~100-200us per sensor at 400kHz (address + register overhead), power during transfer ~1mA, cable length up to 1-3 meters with 4.7k pull-ups

Option B: SPI bus (BME280 + SD card + TFT display): Wire count 3 shared + 1 CS per device = 6 pins for 3 devices, max speed 10-40MHz (1-5MB/s), read latency ~10us per sensor (direct register access), power during transfer ~5-10mA (higher clock), cable length 10-30cm max at high speeds

Decision Factors: For battery-powered environmental monitoring nodes with 3-5 slow sensors, I2C saves pins and power while 400kHz is adequate for 100Hz sensor reads. For data logging to SD card (500kB/s sustained), displays (30fps video), or high-speed ADCs (1MSPS), SPI is mandatory. Hybrid approach: use I2C for slow sensors, SPI for SD/display. Watch for I2C address conflicts - BME280 has only 2 addresses (0x76, 0x77), limiting you to 2 per bus without multiplexer.

13.6 UART Serial Communication

10 min | Intermediate | P06.C09.U01c

UART (Universal Asynchronous Receiver/Transmitter) is the simplest serial protocol, using just two wires for point-to-point communication without a clock signal. Unlike I2C and SPI, UART is asynchronous – both sides must agree on the baud rate (bits per second) beforehand.

13.6.1 UART Key Characteristics

  • TX (Transmit) and RX (Receive): Two unidirectional lines (cross-connected between devices)
  • Asynchronous: No shared clock; both devices must use the same baud rate
  • Point-to-point only: Connects exactly two devices (no bus topology)
  • Common baud rates: 9600, 19200, 38400, 57600, 115200 bps
  • Frame format: Start bit + 8 data bits + optional parity + 1-2 stop bits

13.6.2 When to Use UART

UART is commonly used for GPS modules (NMEA sentences at 9600 bps), Bluetooth modules (HC-05 AT commands), GSM/cellular modems, and debug/logging output. Many sensors provide UART as a simpler alternative to I2C/SPI, though at lower data rates.

13.6.3 Optional ESP32 UART Example

Open this only after you understand the wiring rule: sensor TX connects to MCU RX, sensor RX connects to MCU TX, and both devices must use the same baud rate.

// Reading GPS data over UART (Serial2 on ESP32)
#define GPS_RX 16
#define GPS_TX 17

void setup() {
  Serial.begin(115200);           // USB debug output
  Serial2.begin(9600, SERIAL_8N1, GPS_RX, GPS_TX);  // GPS at 9600 baud
}

void loop() {
  while (Serial2.available()) {
    char c = Serial2.read();
    Serial.print(c);  // Forward GPS NMEA sentences to USB
  }
}

Calculate the effective data throughput for a UART connection based on baud rate and frame configuration.

13.6.4 I2C vs SPI vs UART Quick Reference

Feature I2C SPI UART
Wires 2 3 + 1/device 2
Topology Bus (multi-device) Bus (multi-device) Point-to-point
Clock Synchronous (shared) Synchronous (shared) Asynchronous (agreed)
Speed 100 kHz - 3.4 MHz 1-100 MHz 9600 - 921600 bps
Duplex Half-duplex Full-duplex Full-duplex
Best For Many slow sensors High-speed data Simple serial devices
Protocol Selector

Select your project requirements and see which protocol is the best fit. The tool scores each protocol across your priorities and highlights the recommended choice.


13.7 Bus Protocol Diagnostics

The troubleshooting, bus-budget, and worked-example material is now a focused child chapter instead of a second treatment inside this page.

13.8 Summary

Key protocol takeaways:

  1. I2C saves pins - Use it when many low-to-moderate-speed sensors can share SDA and SCL.
  2. SPI buys speed and determinism - Use it when bandwidth, full-duplex transfer, or device-specific chip-select timing matters.
  3. UART is point-to-point and simple - Use it for modules that stream text or binary frames over TX/RX.
  4. Diagnostics deserve their own pass - Move to the child chapter when the design depends on pull-up sizing, bus capacitance, SPI modes, or address conflicts.

13.9 What’s Next

Chapter Focus
Protocol diagnostics and bus design Troubleshoot and budget real sensor buses
Sensor Data Processing Turn raw readings into reliable data
Sensor Calibration Correct offset, gain, and drift
Sensor Labs Practice wiring and code with real sensors