Project 6: I2C Mapmaker - Multi-Sensor Bus Explorer

Scan and profile an I2C bus, detect devices, measure timing, and recover from bus faults.

Quick Reference

Attribute Value
Difficulty Level 2: Intermediate
Time Estimate 10-15 hours
Main Programming Language C++
Alternative Programming Languages C
Coolness Level Level 3: Genuinely Clever
Business Potential 2. The “Component” Business
Prerequisites C/C++ basics, Teensyduino setup, basic electronics, ability to use a multimeter/logic analyzer
Key Topics I2C bus, addressing, pull-ups, fault recovery

1. Learning Objectives

By completing this project, you will:

  1. Explain the core question for this project in your own words.
  2. Implement the main workflow and validate it with measurements.
  3. Handle at least two failure modes and document recovery.
  4. Produce a deterministic report that matches hardware behavior.

2. All Theory Needed (Per-Concept Breakdown)

I2C Bus Physics, Addressing, and Robust Scans

Fundamentals I2C is a two-wire open-drain bus where devices share SDA and SCL. Pull-up resistors are required because devices only drive the bus low. Each transaction includes an address and acknowledgments. Reliability depends on pull-ups, wiring length, and device behavior like clock stretching.

Deep Dive into the concept Open-drain signaling means rise time depends on pull-up value and bus capacitance. If the rise time is too slow, the bus violates timing specs and errors appear. Many sensors have configurable addresses, so address conflicts are common. A robust scan attempts all addresses, checks ACKs, and records timing. Clock stretching allows a slow device to hold SCL low; firmware must either allow it or time out and recover. A stuck bus can be recovered by toggling SCL as GPIO until the slave releases SDA. This project turns I2C into an observable system with error logs, timing measurements, and recovery routines rather than a best-effort library call.

How this fit on projects This concept directly powers the implementation choices and validation steps in this project.

Definitions & key terms

  • Open-drain: Signaling method where devices only pull lines low.
  • ACK/NACK: Acknowledgment bits indicating success or failure.
  • Clock stretching: Slave holds SCL low to delay the master.
  • Repeated start: I2C sequence that keeps control of the bus between ops.

Mental model diagram (ASCII)

Master -> SDA/SCL bus -> Multiple sensors

How it works (step-by-step)

  1. Calculate pull-up value for bus capacitance.
  2. Scan all 7-bit addresses and log ACKs.
  3. Read device IDs and verify timing.
  4. Handle NACKs and recover from bus lockups.

Minimal concrete example

Wire.beginTransmission(addr);
Wire.write(reg);
Wire.endTransmission(false);
Wire.requestFrom(addr, 2);

Common misconceptions

  • I2C works at any wire length.
  • All devices handle clock stretching the same way.
  • A scan is enough to guarantee a healthy bus.

Check-your-understanding questions

  • Why do pull-ups affect maximum I2C speed?
  • What does a NACK tell you about a device?
  • How do you recover a stuck bus?

Check-your-understanding answers

  • Slow rise times violate timing and reduce reliable speed.
  • The device did not respond or was not ready.
  • Toggle SCL manually and re-init the bus.

Real-world applications

  • Sensor networks
  • EEPROM access
  • Power management ICs

Where you’ll apply it

References

  • I2C specification (NXP)
  • The Book of I2C (Randall Hyde)

Key insights

I2C reliability depends on electrical details as much as software.

Summary

A good I2C master measures, logs, and recovers from bus faults.

Homework/Exercises to practice the concept

  • Calculate pull-up for a 200 pF bus at 400 kHz.
  • Write a bus recovery routine and test a stuck bus.

Solutions to the homework/exercises

  • Use tr = 0.8473RC to estimate R.
  • Switch SCL to GPIO and pulse until SDA releases.

3. Project Specification

3.1 What You Will Build

Scan and profile an I2C bus, detect devices, measure timing, and recover from bus faults.

3.2 Functional Requirements

  1. Scan all 7-bit addresses and detect devices.
  2. Measure bus rise time and adjust pull-ups.
  3. Recover from a stuck SDA/SCL line.
  4. Export a bus map report.

3.3 Non-Functional Requirements

  • Performance: Meet the target timing/throughput for the project.
  • Reliability: Detect errors and recover without undefined behavior.
  • Usability: Provide clear logs and a repeatable workflow.

3.4 Example Usage / Output

./P06-i2c-mapmaker-multi-sensor-bus-explorer --run

3.5 Data Formats / Schemas / Protocols

CSV with columns: address, ack, rise_time_ns, notes

3.6 Edge Cases

  • Two devices with same address
  • Clock stretching by slow device
  • Bus stuck low

3.7 Real World Outcome

You will run the project and see deterministic logs and measurements that match physical hardware behavior.

3.7.1 How to Run (Copy/Paste)

cd project-root
make
./P06-i2c-mapmaker-multi-sensor-bus-explorer --run

3.7.2 Golden Path Demo (Deterministic)

Use a fixed input configuration and a known test signal. Capture output for 60 seconds and verify it matches expected values.

3.7.3 If CLI: exact terminal transcript

$ ./P06-i2c-mapmaker-multi-sensor-bus-explorer --run --seed 42
[INFO] I2C Mapmaker - Multi-Sensor Bus Explorer starting
[INFO] Report saved to data/report.csv
[INFO] Status: OK
$ echo $?
0

Failure Demo (Deterministic)

$ ./P06-i2c-mapmaker-multi-sensor-bus-explorer --run --missing-device
[ERROR] Device not detected
$ echo $?
2

4. Solution Architecture

4.1 High-Level Design

Inputs -> Acquisition -> Processing -> Output/Log

4.2 Key Components

Component Responsibility Key Decisions
Acquisition Configure peripherals and capture data Use stable clock settings
Processing Convert raw data to meaningful values Apply calibration/filters
Output/Log Emit reports and logs CSV for reproducibility

4.3 Data Structures (No Full Code)

struct Sample {
    uint32_t timestamp_us;
    uint32_t value;
    uint32_t flags;
};

4.4 Algorithm Overview

Key Algorithm: Measurement + Report

  1. Initialize hardware and verify configuration.
  2. Capture data and record timestamps.
  3. Compute metrics and write report.

Complexity Analysis:

  • Time: O(n) in samples
  • Space: O(n) for log storage

5. Implementation Guide

5.1 Development Environment Setup

# Arduino IDE + Teensyduino must be installed
# Optional CLI workflow
arduino-cli core update-index
arduino-cli core install teensy:avr

5.2 Project Structure

project-root/
├── src/
│   ├── main.ino
│   ├── hw_config.h
│   └── measurements.cpp
├── tools/
│   └── analyze.py
├── data/
│   └── samples.csv
└── README.md

5.3 The Core Question You’re Answering

“How do I make an I2C bus reliable and observable?”

5.4 Concepts You Must Understand First

Stop and research these before coding:

  1. I2C bus, addressing, pull-ups, fault recovery
  2. Data logging and measurement techniques
  3. Basic timing math and error analysis

5.5 Questions to Guide Your Design

  1. What pull-up value matches your bus capacitance?
  2. How will you detect clock stretching?
  3. How will you recover from a stuck bus?

5.6 Thinking Exercise

Compute expected rise time for two pull-up values and compare to measurement.

5.7 The Interview Questions They’ll Ask

  1. Why is I2C open-drain?
  2. What is a repeated start?
  3. How do you handle NACKs?

5.8 Hints in Layers

  • Start with a single sensor and add devices one by one.
  • Use a logic analyzer to measure rise time.
  • Implement a GPIO-based bus reset routine.

5.9 Books That Will Help

| Topic | Book | Chapter | |——-|——|———| | I2C basics | The Book of I2C | Ch. 1-3 | | Embedded buses | Making Embedded Systems | Ch. 6 | | Digital design | Digital Design and Computer Architecture | Ch. 4 |

5.10 Implementation Phases

Phase 1: Foundation (4 hours)

Goals:

  • Implement address scan
  • Measure rise time

Tasks:

  1. Implement address scan
  2. Measure rise time

Checkpoint: Bus map started

Phase 2: Core Functionality (6 hours)

Goals:

  • Add fault recovery
  • Log timing

Tasks:

  1. Add fault recovery
  2. Log timing

Checkpoint: Robust scan tool

Phase 3: Polish (3 hours)

Goals:

  • Document bus map
  • Compare pull-ups

Tasks:

  1. Document bus map
  2. Compare pull-ups

Checkpoint: Final report

5.11 Key Implementation Decisions

| Decision | Options | Recommendation | Rationale | |———-|———|—————-|———–| | Buffering | Single buffer, double buffer | Double buffer | Avoids data loss during processing | | Logging format | CSV, binary | CSV | Human-readable while still scriptable | | Clock speed | Default, overclock | Default | Keeps peripherals in spec |


6. Testing Strategy

6.1 Test Categories

| Category | Purpose | Examples | |———-|———|———-| | Unit Tests | Validate math, parsing, and conversions | Timer math, CRC checks | | Integration Tests | Verify peripherals and pipelines | DMA -> buffer -> log | | Edge Case Tests | Handle boundary conditions | Brownout, missing sensor |

6.2 Critical Test Cases

{test_cases}

6.3 Test Data

Use a fixed test input pattern and record outputs to data/report.csv

7. Common Pitfalls & Debugging

7.1 Frequent Mistakes

| Pitfall | Symptom | Solution | |———|———|———-| {pitfalls}

7.2 Debugging Strategies

{debug_strats}

7.3 Performance Traps

Large buffers improve stability but increase latency. Measure both throughput and jitter to choose the right size.


8. Extensions & Challenges

8.1 Beginner Extensions

{ex_begin}

8.2 Intermediate Extensions

{ex_inter}

8.3 Advanced Extensions

{ex_adv}


9. Real-World Connections

9.1 Industry Applications

{industry_apps}

{open_source}

9.3 Interview Relevance

{interview_rel}


10. Resources

10.1 Essential Reading

{resources}

10.2 Video Resources

  • Embedded systems timing walkthrough (YouTube)
  • Teensy hardware deep dive (Conference talk)

10.3 Tools & Documentation

  • Teensyduino: Toolchain for Teensy boards
  • Logic Analyzer: Timing verification
  • Multimeter: Voltage and current measurement

{related_projects}


11. Self-Assessment Checklist

11.1 Understanding

  • I can explain the main concept without notes.
  • I can explain why the measurements match (or do not match) expectations.
  • I understand at least one tradeoff made in this project.

11.2 Implementation

  • All functional requirements are met.
  • All critical test cases pass.
  • Logs and reports are reproducible.
  • Edge cases are handled.

11.3 Growth

  • I documented lessons learned.
  • I can explain this project in a job interview.
  • I identified one improvement for next iteration.

12. Submission / Completion Criteria

Minimum Viable Completion: {comp_min}

Full Completion: {comp_full}

Excellence (Going Above & Beyond): {comp_ex}