198  Serial Communication Protocols

198.1 Learning Objectives

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

  • Compare Serial Protocols: Evaluate I2C, SPI, and UART for different sensor integration scenarios
  • Apply Protocol Selection Criteria: Use pin count, speed, and distance factors to choose appropriate interfaces
  • Implement Multi-Sensor Systems: Design reliable bus architectures for connecting multiple sensors
  • Debug Protocol Issues: Identify and resolve common serial communication problems

198.2 Prerequisites

Before diving into this chapter, you should be familiar with:

NoteCross-Hub Connections

Enhance your learning by exploring related resources:

  • Simulations Hub: Try interactive tools for protocol comparison and signal timing analysis
  • Hands-On Labs Hub: Practice I2C and SPI communication with ESP32 simulations
  • Knowledge Gaps Hub: Clarify common misconceptions about serial protocol trade-offs

Think of serial communication like sending a message through a tube - one letter at a time. Different protocols are like different types of tubes with different rules.

Everyday Analogy: Imagine three ways to pass notes in class:

  • I2C is like passing notes through a single row with seat numbers - many people can share one path, but you need to call out who the note is for
  • SPI is like having a private messenger for each friend - faster delivery, but you need more messengers
  • UART is like two tin cans connected by string - simple, works over longer distances, but only connects two people
Term Simple Explanation
I2C (I-squared-C) A two-wire bus where many devices share the same wires, using addresses to know who’s talking
SPI A four-wire system that’s very fast, with a dedicated “select” wire for each device
UART The simplest two-wire connection between just two devices, like a phone call
Bus A shared communication path, like a road many cars can use
Pull-up Resistor A component that keeps I2C wires at the correct voltage when not actively being used

Why This Matters for IoT: Your temperature sensor uses I2C (2 wires, simple). Your display uses SPI (fast updates). Your GPS module uses UART (comes with built-in protocol). Understanding these helps you wire things correctly and debug problems when sensors don’t respond.

CautionPitfall: Ignoring Serial Protocol Timing in Multi-Sensor Systems

The Mistake: Connecting multiple I2C sensors assuming they will “just work,” then experiencing intermittent data corruption, missed readings, or bus lockups in deployment.

Why It Happens: I2C address conflicts, bus capacitance exceeding limits with long wires, clock stretching incompatibilities between sensors, and missing pull-up resistors all manifest as intermittent failures that rarely appear during bench testing with short jumper wires.

The Fix: Map all I2C addresses before wiring - use a bus scanner script first. Calculate total bus capacitance (each sensor + wire length × 100pF/m) and keep under 400pF for 100kHz I2C. Use appropriate pull-up resistors (2.2k-4.7k for 3.3V systems). Add I2C bus recovery code (clock pulse sequence) for stuck-bus conditions. Consider I2C multiplexers (TCA9548A) for address conflicts. For long runs (>30cm), switch to RS-485 or CAN bus instead.

NoteKey Takeaway

In one sentence: Choose I2C for multiple low-speed sensors (2 wires, 127 devices), SPI for high-speed peripherals like displays and flash (fastest, more pins), and UART for GPS/Bluetooth modules (simplest, point-to-point).

Remember this: I2C = many sensors, few wires. SPI = fast data, more wires. UART = simple modules, two wires.

198.3 Serial Protocol Comparison

%%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#2C3E50', 'primaryTextColor': '#fff', 'primaryBorderColor': '#16A085', 'lineColor': '#16A085', 'secondaryColor': '#E67E22', 'tertiaryColor': '#7F8C8D'}}}%%
graph TB
    subgraph I2C["I2C (Inter-Integrated Circuit)"]
        I2C_Props["2 wires: SDA, SCL<br/>Multi-master capable<br/>Speed: 100kHz-3.4MHz<br/>Max devices: 127"]
        I2C_Use["Use for:<br/>- Multiple sensors<br/>- Short distances<br/>- Moderate speed<br/>- Simple wiring"]
    end

    subgraph SPI["SPI (Serial Peripheral Interface)"]
        SPI_Props["4+ wires: MOSI, MISO,<br/>SCK, CS (per device)<br/>Full-duplex<br/>Speed: 10-100+ MHz<br/>Point-to-point"]
        SPI_Use["Use for:<br/>- High-speed data<br/>- Displays/Flash<br/>- Real-time ADC<br/>- Low latency"]
    end

    subgraph UART["UART (Universal Async RX/TX)"]
        UART_Props["2 wires: TX, RX<br/>Asynchronous<br/>Speed: 9600-921600 baud<br/>Point-to-point"]
        UART_Use["Use for:<br/>- GPS modules<br/>- Bluetooth/Wi-Fi<br/>- Debug console<br/>- Simple comms"]
    end

    style I2C fill:#16A085,stroke:#2C3E50,color:#fff
    style SPI fill:#E67E22,stroke:#2C3E50,color:#fff
    style UART fill:#2C3E50,stroke:#16A085,color:#fff
    style I2C_Props fill:#16A085,stroke:#2C3E50,color:#fff
    style I2C_Use fill:#16A085,stroke:#2C3E50,color:#fff
    style SPI_Props fill:#E67E22,stroke:#2C3E50,color:#fff
    style SPI_Use fill:#E67E22,stroke:#2C3E50,color:#fff
    style UART_Props fill:#2C3E50,stroke:#16A085,color:#fff
    style UART_Use fill:#2C3E50,stroke:#16A085,color:#fff

Figure 198.1: Serial Protocol Comparison: I2C, SPI, and UART Characteristics and Use Cases {fig-alt=“Serial protocol comparison showing three protocols: I2C uses 2 wires (SDA, SCL) for multi-master communication at 100kHz-3.4MHz with up to 127 devices, ideal for multiple sensors and short distances; SPI uses 4+ wires (MOSI, MISO, SCK, CS) for full-duplex point-to-point communication at 10-100+ MHz, ideal for high-speed data, displays, flash memory; UART uses 2 wires (TX, RX) for asynchronous point-to-point communication at 9600-921600 baud, ideal for GPS modules, Bluetooth/Wi-Fi, and debug console”}

198.4 Protocol Selection Matrix

This variant presents I2C, SPI, and UART selection as a multi-criteria decision matrix, helping engineers systematically evaluate trade-offs.

%%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#2C3E50', 'primaryTextColor': '#fff', 'primaryBorderColor': '#16A085', 'lineColor': '#16A085', 'secondaryColor': '#E67E22', 'tertiaryColor': '#7F8C8D', 'fontSize': '11px'}}}%%
graph TB
    subgraph Matrix["PROTOCOL SELECTION CRITERIA"]
        direction TB

        subgraph I2C_Box["I2C"]
            I2C_Score["Pins: 2 *****<br/>Speed: 400K **<br/>Devices: 127 *****<br/>Distance: 1m **<br/>Complexity: ***"]
            I2C_Use["USE: Multiple sensors<br/>temp, humidity, IMU"]
        end

        subgraph SPI_Box["SPI"]
            SPI_Score["Pins: 4+n **<br/>Speed: 80M *****<br/>Devices: CS pins ***<br/>Distance: 3m ***<br/>Complexity: ****"]
            SPI_Use["USE: High-speed<br/>flash, display, ADC"]
        end

        subgraph UART_Box["UART"]
            UART_Score["Pins: 2 *****<br/>Speed: 1M ***<br/>Devices: 1 *<br/>Distance: 15m *****<br/>Complexity: *****"]
            UART_Use["USE: Debug, GPS<br/>Bluetooth modules"]
        end
    end

    I2C_Box --> Decision{Your Priority?}
    SPI_Box --> Decision
    UART_Box --> Decision

    Decision -->|"Many sensors"| I2C_Win["Choose I2C"]
    Decision -->|"High throughput"| SPI_Win["Choose SPI"]
    Decision -->|"Long cable/debug"| UART_Win["Choose UART"]

    style I2C_Box fill:#16A085,stroke:#2C3E50,color:#fff
    style SPI_Box fill:#E67E22,stroke:#2C3E50,color:#fff
    style UART_Box fill:#2C3E50,stroke:#16A085,color:#fff
    style I2C_Win fill:#16A085,stroke:#2C3E50,color:#fff
    style SPI_Win fill:#E67E22,stroke:#2C3E50,color:#fff
    style UART_Win fill:#2C3E50,stroke:#16A085,color:#fff

Figure 198.2: Alternative view: Each serial protocol excels in different dimensions. I2C minimizes wiring for sensor clusters. SPI maximizes throughput for displays and flash. UART provides simplicity and long-distance capability. Selection depends on the dominant constraint in your application.

198.5 Protocol Technical Details

198.5.1 I2C (Inter-Integrated Circuit)

I2C uses a shared bus architecture with just two wires:

Property Value
Wires 2 (SDA data, SCL clock)
Speed Standard 100kHz, Fast 400kHz, Fast+ 1MHz, High-speed 3.4MHz
Addressing 7-bit (127 devices) or 10-bit (1024 devices)
Distance 1-3 meters typical (capacitance limited)
Pull-ups Required (2.2k-10k depending on bus speed)

Best for: Multiple sensors, EEPROMs, RTCs, small displays, low pin count

Common I2C Addresses: - BME280 (temp/humidity): 0x76 or 0x77 - SSD1306 OLED: 0x3C or 0x3D - MPU6050 IMU: 0x68 or 0x69 - DS3231 RTC: 0x68

198.5.2 SPI (Serial Peripheral Interface)

SPI uses a master-slave architecture with dedicated select lines:

Property Value
Wires 4 minimum (MOSI, MISO, SCK, CS per device)
Speed 1-100+ MHz (device dependent)
Topology Master-slave, one CS per slave
Duplex Full-duplex (simultaneous read/write)
Distance 1-3 meters (signal integrity limited)

Best for: Flash memory, SD cards, displays, ADCs, high-speed sensors

198.5.3 UART (Universal Asynchronous Receiver/Transmitter)

UART provides simple point-to-point asynchronous communication:

Property Value
Wires 2 (TX, RX) + ground
Speed 9600-921600 baud typical
Topology Point-to-point only
Distance 15+ meters (with RS-232/RS-485)
Handshaking Optional (RTS/CTS)

Best for: GPS modules, Bluetooth/Wi-Fi modules, debug console, legacy devices

198.6 Hands-On Lab: I2C vs SPI Protocol Selection

Objective: Understand trade-offs between I2C and SPI protocols.

Scenario: Design a weather station with: - 1x Temperature/Humidity sensor - 1x Barometric pressure sensor - 1x Real-time clock (RTC) - 1x EEPROM for data logging - 1x Flash memory (4MB) for firmware updates

Tasks:

  1. Design two versions:
    • Version A: All devices on I2C bus
    • Version B: Sensors on I2C, Flash on SPI
  2. Calculate for each version:
    • Total pin count required
    • Maximum theoretical data throughput
    • Firmware complexity (protocol handling)
  3. Simulate I2C bus:
    • Create I2C devices for all sensors
    • Scan bus and verify addressing
    • Read from all devices
    • Calculate total transaction time
  4. Simulate SPI version:
    • Create SPI flash device
    • Simulate firmware read (1KB)
    • Compare speed with I2C EEPROM

Expected Results: - I2C version: Simpler wiring, lower pin count, adequate for sensor data rates - SPI version: Faster firmware updates, slightly more complex

198.7 Hands-On Lab: ADC Resolution Determination

Objective: Calculate required ADC resolution for various sensors.

Scenario: Design precision sensors for:

  1. Medical thermometer: 35-42°C range, 0.1°C accuracy
    • Sensor: TMP117 (10mV/°C)
    • ADC reference: 3.3V
  2. Industrial pressure sensor: 0-100 PSI, 0.5 PSI accuracy
    • Sensor: 0.5-4.5V output for 0-100 PSI
    • ADC reference: 5.0V
  3. pH sensor: pH 0-14, 0.01 pH accuracy
    • Sensor: 414mV per pH unit
    • ADC reference: 3.3V

Tasks:

  1. For each sensor, calculate:

    • Required voltage resolution
    • Required ADC bits
    • Actual achievable resolution with standard ADC (10-bit, 12-bit, 16-bit)
  2. Select minimum ADC resolution for each application

  3. Calculate total system cost with different ADC options:

    • 10-bit ADC: $3
    • 12-bit ADC: $5
    • 16-bit ADC: $12
  4. Determine if a single high-resolution ADC can serve all sensors or if multiple ADCs are needed

Deliverables: - ADC requirement table for each sensor - Cost-benefit analysis - Recommendation for ADC configuration

198.8 Knowledge Check

Question 1: You’re wiring multiple low-speed sensors (temperature, humidity, IMU) on the same board and want minimal pin count. Which serial bus is the best fit?

I2C is designed for multiple devices on a shared two-wire bus with addressing, making wiring simple for sensor clusters. SPI is faster but needs more pins (and usually a chip-select per peripheral).

Question 2: Your design includes an external flash chip for fast firmware updates and high-speed data logging. Which interface is most appropriate?

SPI is commonly used for external flash, displays, and high-rate peripherals due to its higher clock rates and full-duplex transfers. I2C is typically “fast enough” for many sensors but is slower for bulk flash operations.

198.9 Summary

This chapter explored serial communication protocols for IoT sensor integration:

  • I2C: A two-wire bus protocol supporting up to 127 devices on shared SDA/SCL lines. Ideal for multiple low-speed sensors (temperature, humidity, IMU) with minimal wiring. Requires pull-up resistors and has distance limitations (~1m).
  • SPI: A high-speed four-wire protocol with dedicated chip-select per device. Best for flash memory, displays, and high-bandwidth peripherals. Faster than I2C but requires more GPIO pins.
  • UART: Simple asynchronous two-wire point-to-point communication. Standard interface for GPS modules, Bluetooth/Wi-Fi modules, and debug consoles. Works over longer distances but connects only two devices.
  • Protocol Selection: Match protocol to requirements - I2C for sensor clusters, SPI for high-speed peripherals, UART for module interfaces. Consider pin count, speed, distance, and device count.
  • Common Pitfalls: I2C address conflicts, bus capacitance limits, missing pull-ups, and clock stretching issues can cause intermittent failures that are hard to debug in deployment.

Deep Dives: - Communication and Protocol Bridging - Higher-level protocol concepts - Sensor Fundamentals - ADC and sensor interfaces - Prototyping Hardware - Development board interfaces

Comparisons: - Hardware Platform Selection - MCU interface availability

198.10 What’s Next

Having covered serial communication protocols, the next chapter examines Development Workflow and Tooling, exploring IDEs, debugging techniques, CI/CD pipelines, and Over-The-Air (OTA) update strategies for professional IoT development.

Continue to Development Workflow and Tooling →