# I2C vs SPI vs UART in robotics: picking the right bus

> Speed, wiring, device count and failure modes for the three buses robotics projects use, with a simple selection table.

Canonical: https://roboticsengineering.in/i2c-spi-uart-robotics/ | Published: 2026-10-27 | Updated: 2026-10-27 | Author: Jignesh Panchal

**Use I2C for several slow sensors on two shared pins, SPI for one device that needs speed and sits close, and UART for a link that has to travel or connect two boards.** Picking by reputation goes wrong in both directions: SPI buys bandwidth with extra pins and short wires, and UART survives a metre of cable because it was designed for exactly that.

## The three buses in one table

| Bus | Pins used | Typical clock | Practical distance | How a device is selected | Good for |
| --- | --- | --- | --- | --- | --- |
| I2C | 2 shared (SDA, SCL) plus ground | 100 kHz standard, 400 kHz fast mode, 1 MHz fast mode plus on newer parts | 30–100 cm on breadboard jumpers | 7-bit address sent on the wire | Many slow sensors, OLED, RTC, port expander |
| SPI | 3 shared (SCK, MOSI, MISO) plus one chip-select per device | 1–50 MHz depending on device and wiring | Under 30 cm at high clock | Dedicated chip-select line pulled low | SD card, colour display, fast IMU logging, radio module |
| UART | 2 per link (TX to RX, RX to TX) plus ground | 9,600 to 921,600 baud in practice | Metres with good wiring, much further through RS-485 transceivers | None, it is point to point | GPS, Bluetooth module, serial servo, second microcontroller |

*Clock figures follow the I2C-bus specification (NXP UM10204); SPI and UART limits come from the device datasheets, which differ widely.*

Two consequences follow. I2C costs almost nothing in pins, so it is the default for a robot with four or five sensors. SPI’s speed depends on short, tidy wiring: at 20 MHz a few centimetres of loose jumper turns a clean square wave into ringing, and the device returns garbage that looks like a software bug.

## Addressing is where I2C earns and loses its keep

Every I2C device listens on a 7-bit address, so devices share two wires without a chip-select each. The limit arrives the moment you want two of the same sensor: two identical IMU boards set to the same address cannot both answer, and the bus returns nonsense or nothing. Many breakout boards expose a solder jumper or an address pin that moves the device to a second address, which is why buying two boards of the same model usually works and buying two of a fixed-address model does not.

The addresses people quote, like 0x3C for a small OLED or 0x68 for a common IMU, are the defaults a module ships with. Clones copy them, some clones ship with a different one, and a few boards have a level shifter that fails and takes the address with it. Scan the bus and print what is actually there before you debug anything else.

```
#include <Wire.h>

void setup() {
  Serial.begin(115200);
  Wire.begin();          // ESP32 default is SDA 21, SCL 22
  Wire.setClock(100000); // drop to 100 kHz while debugging
}

void loop() {
  byte found = 0;
  for (byte addr = 1; addr < 127; addr++) {
    Wire.beginTransmission(addr);
    if (Wire.endTransmission() == 0) {
      Serial.print("found 0x");
      Serial.println(addr, HEX);
      found++;
    }
  }
  if (found == 0) {
    Serial.println("nothing found: check power, ground, SDA/SCL, pull-ups");
  }
  delay(2000);
}
```

## Pull-ups, capacitance and voltage levels

I2C lines are open drain, which means a device can pull a line low but cannot drive it high. Resistors pull the line back up, and the value of those resistors sets how fast the line rises. The I2C-bus specification limits total bus capacitance to 400 pF for standard and fast mode, and every centimetre of jumper wire, every breadboard row and every extra board adds capacitance. When the pull-up is too weak for the capacitance, the rise is slow, edges round off, and the bus fails intermittently in a way that looks like a bad sensor.

Most breakout boards already carry a pull-up pair, often 10 kΩ. Chain four and the effective value is 2.5 kΩ, stronger than the specification wants and harder on devices that must sink the current. A useful approximation for the rise time is 0.847 times the resistance times the capacitance. With 10 kΩ and 200 pF that is about 1.7 microseconds, acceptable on a 100 kHz bus and marginal for 400 kHz, where the specification allows only 300 ns, against 1,000 ns in standard mode. If you are adding your own, start at 2.2 kΩ to 4.7 kΩ, keep the wiring short, and treat anything past a metre of unshielded cable as a design change rather than a wiring detail.

Voltage is the other quiet failure. An Arduino Uno runs its I2C at 5 V. An ESP32 runs at 3.3 V. A module with an onboard regulator and level shifter tolerates both; a bare chip usually does not, and 5 V on a 3.3 V-only sensor can damage it. A bidirectional level shifter costs roughly ₹40–100 as a planning range, check current prices, which is cheaper than replacing the sensor. Ground must be common across every device on the bus, including the ones on a separate supply.

## Practical picks for a student robot

- **IMU:** I2C at 100 to 200 Hz is plenty for balancing and heading. Move to SPI only if you want a kilohertz logging rate, and expect to shorten the wires when you do.
- **Distance:** a time-of-flight sensor over I2C for short range indoors. An ultrasonic module needs two ordinary GPIO pins and no bus at all, which is covered in the [HC-SR04 guide](https://roboticsengineering.in/components/hc-sr04-ultrasonic-sensor/).
- **Display:** a small OLED over I2C for status. A colour TFT over SPI, because pushing pixels over I2C is painfully slow.
- **Logging:** an SD card over SPI. It is the one device where the extra pins are worth it.
- **Radio and GPS:** UART. Bluetooth modules, GPS receivers and long-range radio modules all speak UART at a fixed baud rate you must match exactly.
- **Motor driver:** neither bus. A driver like the [L298N](https://roboticsengineering.in/components/l298n-motor-driver/) takes PWM and direction pins, and no amount of bus design changes that.

## Why is my I2C scanner showing nothing?

Work through this in order, because most silent buses come down to wiring.

- **SDA and SCL swapped.** The most common cause. Check the labels on the module, not the colours of your jumpers.
- **No common ground.** The signals have no reference and the bus floats.
- **No pull-ups at all.** A bare chip on a breadboard with no resistors will never answer.
- **Wrong supply voltage.** A 5 V-only module fed 3.3 V may power up its LED and stay mute.
- **Scanner running before the sensor finishes booting.** Some modules need a few hundred milliseconds. Add a delay in setup().
- **Wrong pins on the board.** An ESP32 defaults to GPIO 21 and 22, but many boards are wired differently and you must pass the pins to Wire.begin().
- **Cable too long, or a breadboard with a worn row.** Try one short jumper pair with a single device before adding the rest.

If the scanner finds the device but the library errors, the bus works and the problem is the driver, register address or sample rate. A device at an unexpected address usually means a different chip than the listing claimed.

## Multiplexers, second ports and when UART is the right answer

When you need three identical sensors, use an I2C multiplexer such as the TCA9548A, roughly ₹150–250 as a planning range, check current prices. It gives you eight downstream channels, one at a time, and you write a single byte to select the channel before talking to the sensor. It works, and it adds a device’s worth of capacitance and one more thing to debug. An ESP32 has two hardware I2C controllers, so a second bus on other pins is often the cleaner answer than a multiplexer.

UART wins whenever distance or an existing protocol decides for you: a GPS module streams at 9,600 baud over two wires, a serial bus servo expects a packet at 1 Mbaud, and two microcontrollers talk with TX crossed to RX. It is also the easiest bus to debug, because you can watch the bytes arrive in a terminal. The catch is that it is strictly one device per port, and on an AVR board the software serial library can only listen on one port at a time and its reliability falls as the baud rate rises, so keep it at 19,200 or below for anything you depend on. If you need three UART devices on an Uno, you need a different board.

Never hot-plug a sensor on a powered bus. Pull the power, rewire, then power up. It costs ten seconds and saves the module. If you are still deciding which board hosts all this, the [ESP32 DevKit guide](https://roboticsengineering.in/components/esp32-devkit-v1/) lists the default I2C and SPI pins.

## Common questions

### Can I use I2C and SPI at the same time?

Yes. They are separate peripherals with separate pins, and a typical robot runs an OLED on I2C while logging to an SD card over SPI. Sharing the SPI pins between two devices is fine as long as each has its own chip-select line, and you never pull two chip-selects low together.

### Why does my sensor work on an Uno but not on an ESP32?

Usually voltage or pins. The ESP32 is 3.3 V, so a module that needs 5 V may not start, and a module that outputs 5 V on SDA or SCL needs a level shifter. Then check the pin numbers: the default ESP32 I2C pins are 21 and 22, but plenty of boards expect you to declare them.

### How fast can I sample an IMU over I2C?

At 400 kHz a 14-byte read plus addressing overhead occupies roughly 0.4 ms of bus time, so a few hundred samples per second is realistic on a bus with one device. Add a second device and the bus time is shared. If your control loop needs more than that, move the IMU to SPI or reduce the number of registers you read per sample.

Related: [robotics tools and calculators](https://roboticsengineering.in/tools/), [all learn guides](https://roboticsengineering.in/learn/).

## Sources and further reading

Documents used to check the numbers on this page:

- [NXP I2C-bus specification (UM10204)](https://www.nxp.com/docs/en/user-guide/UM10204.pdf) — bus behaviour and limits.
- [Arduino Language Reference](https://docs.arduino.cc/language-reference/) — pin functions, timings and library behaviour.

Last reviewed: October 2026. Bus limits follow the I2C-bus specification and device datasheets; clone modules vary. Prices are planning ranges, not quotes.
