Freezer at -12.5 C shows up as 65411 after going through my Modbus slave
Student, first Modbus project. Arduino Mega reads a freezer probe and acts as a Modbus RTU slave (ModbusRTUSlave library). I store the temperature times 10 in holding register 0 so I keep one decimal. A Raspberry Pi polls it with pymodbus and sends temp to Hermetry.
Positive temperatures are perfect: 4.2 C goes in as 42 and comes out as 4.2. But the freezer is below zero, and there I get nonsense. -12.5 C turns into 6541.1 in Hermetry. Raw register value on the Pi is 65411.
rr = client.read_holding_registers(0, count=1, slave=3)
temp = rr.registers[0] / 10 # 6541.1 ??
On the Arduino I write holdingRegisters[0] = temp * 10; where temp is a float. What am I doing wrong?
Maybe Modbus just doesn’t do negative numbers? Could you add 100 to everything and subtract it again later?
An offset works, people do it, but you don’t need it here. The number is fine, it’s the reading side.
Had the exact same thing in a lab last term with a fridge logger. Modbus registers are just 16 bits, they don’t know about signs. Your Arduino stores -125 as two’s complement, which is 0xFF83, and as an unsigned number that’s 65411. The Pi then reads it as unsigned.
So convert it back on the Pi:
raw = rr.registers[0]
if raw > 32767: # top bit set means negative in int16
raw -= 65536
temp = raw / 10 # -12.5
Or let pymodbus do it, the client has a helper for this (in 3.x):
temp = client.convert_from_registers(rr.registers, data_type=client.DATATYPE.INT16) / 10
On the Arduino side, cast before the register so rounding is explicit: holdingRegisters[0] = (uint16_t)(int16_t)lround(temp * 10);. With int16 x10 you have -3276.8 to 3276.7 C, plenty for a freezer.
If a gateway polls it instead of your script, set that register’s type to signed 16-bit in the gateway config and it does the same conversion.
Same goes for 32-bit values split over two registers, then you also have to get the word order right. Fun times.
The raw -= 65536 fix works, Hermetry shows -12.5 now and the chart doesn’t jump to 6000 anymore. Yesterday’s 6541 points are still sitting in the history, but everything new is right lol. 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.

