smbus2 write_i2c_block_data: what is the “cmd” byte for an ADS1115?
Garden node project: Pi Zero 2 W, ADS1115 at 0x48, AIN0 is a capacitive soil probe and AIN1 the 12 V battery through a divider. The script posts both to Hermetry every 5 minutes.
I wanted to skip the big libraries and talk to the ADS1115 with smbus2 myself. I copied this from a forum post:
bus.write_i2c_block_data(0x48, 0x01, [0xC3, 0x83])
time.sleep(0.01)
data = bus.read_i2c_block_data(0x48, 0x00, 2)
raw = data[1] << 8 | data[0]
It runs, but the numbers are nonsense: the soil value jumps between about 900 and 52,000 when nothing changes. The smbus2 docs describe the second argument as cmd. What command? The ADS1115 datasheet does not mention commands anywhere, only registers. I feel like I’m missing something basic.
Isn’t cmd a code the chip defines, like “start conversion”?
+1, never understood that argument either.
“cmd” is SMBus naming. In an SMBus block write the first byte after the address is called the command byte, and for register-based chips like the ADS1115 that byte is the register pointer. So your first line puts the pointer on the Config register (0x01) and writes 0xC3 then 0x83 into it. On the wire: start, 0x90, 0x01, 0xC3, 0x83, stop.
0xC383 means: start a single conversion, AIN0 against GND, ±4.096 V range, single-shot mode, 128 samples/s. The read sets the pointer to 0x00 (Conversion register) and reads two bytes.
Your bug is the byte order. The ADS1115 sends the most significant byte first, and the result is signed:
data = bus.read_i2c_block_data(0x48, 0x00, 2)
raw = (data[0] << 8) | data[1]
if raw > 0x7FFF:
raw -= 0x10000
volts = raw * 4.096 / 32768
With the bytes swapped, a small change in the low byte becomes a huge jump, which is your 900 vs 52,000. For AIN1 change the MUX bits: [0xD3, 0x83]. And 10 ms is enough at 128 SPS (one conversion is about 8 ms), so the sleep is fine.
Tip from commissioning skids: while you’re testing, send the raw count next to the volts. When a reading looks wrong in three months you can tell a gain mistake from a sensor problem straight from the chart.
Byte order it was. Swapped them and the soil value sits at 1.62 V, steady. I added soil.raw next to soil.v like Keisha said, and the battery on AIN1 reads 12.7 V after the divider maths. Also understand now what that argument is, thanks Aoife.
- You must be logged in to reply to this topic.
Join the conversation
Sign in to ask and answer, like helpful posts and mark the reply that solved your problem. Every contribution earns points and levels.

