Lesson 4 of 5 · 22 min
I2C and sensors
A Pi has 26 usable GPIO pins, but a robot can easily carry a temperature sensor, an IMU, a distance sensor, a current monitor and an OLED display. Giving each one its own pins would use up the header in no time. I2C (pronounced "I squared C") solves this by letting many chips share just two wires. Once you understand I2C, you can use thousands of different sensors, because most of them speak it.
How the bus works
I2C uses two signal lines plus ground:
- SDA: serial data, GPIO2 (physical pin 3)
- SCL: serial clock, GPIO3 (physical pin 5)
One device is the controller (the Pi), which generates the clock on SCL. The others are targets. Every target has a 7-bit address, so the bus can hold up to 128 addresses, about 112 of them usable after reserved ones are removed. The controller starts a transfer by sending an address and a read or write bit. Only the target with that address answers. The rest ignore the traffic.
The standard speed is 100 kHz, and fast mode is 400 kHz. At 100 kHz a byte takes about 90 microseconds including the acknowledge bit, which is plenty for reading a temperature a few times per second.
Why pull-up resistors are required
I2C lines are open-drain: each device can only pull a line down to ground, never drive it up to 3.3 V. A line returns to HIGH only because a pull-up resistor connects it to 3.3 V. Without pull-ups the lines never go high and the bus does not work at all.
Pull-up size sets a trade-off. The wire and chip inputs act as a small capacitor, and the rise time is about t = 0.85 x R x C. With R = 1.8 kΩ and a bus capacitance of 100 pF, that is about 150 ns, well inside the 1000 ns the 100 kHz standard allows. A smaller resistor gives faster edges but forces devices to sink more current when pulling low, and the spec limits that to 3 mA: 3.3 V / 1.8 kΩ = 1.8 mA, which is safe.
The Pi already has 1.8 kΩ pull-ups on GPIO2 and GPIO3 on the board, and many sensor breakout boards add their own as well. Two or three in parallel is fine, but a dozen breakouts with pull-ups on each can lower the total resistance until the bus cannot be pulled low.
Wiring and enabling
Connect four wires from the sensor: 3V3 to VCC, GND to GND, SDA to SDA, SCL to SCL. Then enable the interface:
sudo raspi-config
# Interface Options, I2C, Yes
sudo apt install -y i2c-tools python3-smbus
ls /dev/i2c-1
If /dev/i2c-1 exists, the kernel driver is ready.
Scanning the bus
Before writing any code, check that the sensor is physically alive:
i2cdetect -y 1
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- 48 -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- --
Each number is an address in hexadecimal that answered. Here, devices sit at 0x48 and 0x68. If nothing appears, check power, then swap SDA and SCL, then check for a missing pull-up. If two sensors share an address, many boards have an address pin, such as ADD0 or AD0, that you can tie to GND or VCC to pick between two addresses.
Reading a sensor
The TMP102 temperature sensor at 0x48 is a good example. With the library smbus2 (install with pip install smbus2), reading it takes four lines:
from smbus2 import SMBus
TMP102_ADDR = 0x48
TEMP_REG = 0x00
with SMBus(1) as bus: # 1 = /dev/i2c-1
data = bus.read_i2c_block_data(TMP102_ADDR, TEMP_REG, 2)
print(data) # for example [25, 0]
The call writes the register address to the device, then reads back 2 bytes. For popular sensors such as the BME280 or MPU6050 there are ready libraries, for example from Adafruit, that do this decoding for you. Libraries are a good idea. Knowing what they do inside is better, because when a reading looks wrong you can find out why.
Reading the datasheet
The datasheet is the only source of truth. For an I2C sensor, look for:
- The I2C address and which pins change it.
- The register map: a table of register numbers and what each holds.
- The data format: how many bits, which byte comes first, and whether the value is signed.
- The scale factor: how many degrees, g or lux each count represents.
- Timing: how long a conversion takes before the result is valid.
For the TMP102 temperature register, the datasheet says the result is a 12-bit two's complement number, left-aligned in 16 bits (the high byte arrives first), and each count is 0.0625 degrees Celsius. So the conversion has three steps: join the two bytes, shift right by 4 to drop the unused bits, then handle the sign. A 12-bit value with the top bit set is negative, so subtract 4096.
Work through the first sample by hand: 0x1900 shifted right by 4 gives 0x190, which is 400, and 400 x 0.0625 is 25.0 degrees. The 0xE700 sample is 0xE70, which is 3696. The top bit is set, so subtract 4096 to get -400, and the temperature is -25.0.
Check yourself
Why does an I2C bus need pull-up resistors?
Check yourself
A sensor sends the bytes 0x19 and 0x00, as a left-aligned 12-bit value with 0.0625 degrees per count. What temperature is it?