smbus2
smbus2 is a pure-Python replacement for the kernel's SMBus bindings and the standard way to talk to I²C chips from a Pi. PyRasp ships an smbus2 module with the same classes and methods as smbus2 0.4.x, so driver code from a real project usually runs unchanged. The real library's documentation is at smbus2.readthedocs.io.
Only I²C bus 1 exists, on GPIO2 (SDA) and GPIO3 (SCL), as on a Pi with I²C enabled. The older smbus module is also provided: import smbus gives you the same smbus.SMBus served by the same code, for drivers that still import it (RPLCD does, for example).
Reading a device
Every operation goes through an SMBus object. Reading a register is the common case — here a BME280's chip ID at register 0xD0 should read 0x60:
from smbus2 import SMBus
with SMBus(1) as bus:
chip_id = bus.read_byte_data(0x76, 0xD0)
print(hex(chip_id)) # 0x60
Reads and writes raise OSError number 121 (Remote I/O error) when no powered device answers at that address — the same EREMOTEIO the real kernel driver produces.
A BME280-style block read
Environmental chips keep calibration and measurement data in blocks of registers. Write the starting register, then read a run of bytes — the pointer auto-increments:
from smbus2 import SMBus
with SMBus(1) as bus:
calibration = bus.read_i2c_block_data(0x76, 0x88, 24) # calib data
raw = bus.read_i2c_block_data(0x76, 0xF7, 8) # press, temp, hum
temperature_msb = raw[3]
print(calibration[0], temperature_msb)
read_i2c_block_data() can read at most I2C_SMBUS_BLOCK_MAX (32) bytes and raises ValueError past that; i2c_rdwr() has no such limit.
The SMBus calls
| Call | What it does |
|---|---|
write_quick(addr) | zero-byte transaction, for devices that trigger on address alone |
read_byte(addr) / write_byte(addr, value) | one byte, no register |
read_byte_data(addr, reg) / write_byte_data(addr, reg, value) | one register |
read_word_data(addr, reg) / write_word_data(addr, reg, value) | 16-bit little-endian value |
process_call(addr, reg, value) | write a word, read a word back |
read_block_data(addr, reg) / write_block_data(addr, reg, data) | count-prefixed block, ≤ 32 bytes |
read_i2c_block_data(addr, reg, length) / write_i2c_block_data(addr, reg, data) | plain byte run |
i2c_rdwr(*messages) | combined transaction with repeated starts |
i2c_rdwr() takes i2c_msg objects and is the tool for devices that do not follow the register-pointer convention, or for reads longer than 32 bytes. The i2c_msg.read() result is filled in place:
from smbus2 import SMBus, i2c_msg
with SMBus(1) as bus:
read = i2c_msg.read(0x48, 2)
bus.i2c_rdwr(i2c_msg.write(0x48, [0x01]), read)
print(list(read))
The usual address map in the shop: LCD 0x27 (PCF8574) or 0x3F (PCF8574A), OLED 0x3C/0x3D, BME280 0x76/0x77, MPU-6050 0x68, ADS1115 0x48–0x4B. I²C basics are in the bus primer.
Going deeper
SMBus(1) (or opening /dev/i2c-1) is the only bus: SMBus(0), SMBus(2) and so on raise FileNotFoundError. Calling a method on a bus that was never opened raises OSError (Bad file descriptor).
Address conflicts: when two powered parts answer at the same address, the simulator warns ("Two devices answer at I²C address 0x…") and the first one found answers every transaction, so you get plausible but wrong readings. Change one device's address (solder jumpers, props) or unplug it.
Simulator vs real hardware
- Transaction-level, not wire-level. The simulator handles whole transactions and answers at register level for the parts that model buses (BME280, ADS1115, MPU-6050, SSD1306, LCD1602). There is no clock stretching, no bus arbitration and no timing: transactions complete instantly in simulated time.
- Missing devices fail the same way. No powered device at the address raises
OSError121; the transaction also shows up markedNACKin the Lab's bus sniffer. On real hardware you can hang on a stuck bus or getErrno 5; the simulator only produces 121. - PEC is not implemented. The methods accept
forcefor compatibility, but the packet-error checking variants of smbus2 are not provided; code that relies on PEC will not find the arguments. read_block_data()strips the count byte and returns the payload, as smbus2 does; the raw transaction on the wire is the length-prefixed block the chip sent.read_i2c_block_data()returns exactlylengthbytes.- Shared bus etiquette matters on hardware, less here. Real I²C needs one
SMBusper bus per process; the simulator tolerates several objects and even several drivers talking at once.