Sunday, March 29, 2015

SDM220 Power Meter, MODBUS, Python, RS485

The Eastron SDM220 is a very inexpensive one-phase power/energy meter, which can be readout via RS485. I got myself one to play with, and there are a few observations I wanted to write down.

From Chris’ Miscellanea

From Chris’ Miscellanea

From Chris’ Miscellanea

It's actually a pretty nifty meter, measuring power and energy in both directions, voltage and line frequency. Furthermore it outputs power-factor (cosϕ) and reactive or apparent power (which is basically the same thing, just represented differently).

One thing that cost me some time to resolve, especially as I used a selfmade RS485 adapter in the first place about the correctnes of which I was unsure are: The RS485 terminals are wired incorrectly, B and A are swapped, this has been verified with an industrial/commercial interface. Connectors 7, 8 and 9 are GND, A and B. In that order. If the link is idle, B will be positive with respect to A.

There's an existing modbus library for Python (pymodbus) which works perfect, so far. The serial modbus link is instantiated like this (if the modbus runs with parity = None).

    cl = pymodbus.client.sync.ModbusSerialClient('rtu',
        port='/dev/ttyUSB1', baudrate=9600,

The values stored in the device are actually IEEE754 floating point values, which can be converted to python floats very conveniently, they are fetched as two consecutive 16bit register, concatenated to a 32bit field, and then reinterpreted as the 32bit float:

    resp = client.read_input_registers(basereg,2, unit=1)
    return struct.unpack('>f',struct.pack('>HH',*resp.registers))

The documentation for the SDM220 is actually quite comprehensive, but it took me quite a while until I really figured out what they meant... So here are the register numbers I sucessfully used to get date off the device:

        # Symbol    Reg#  Format
        ( 'V',      0x00, '%6.2f' ), # Voltage [V]
        ( 'Curr',   0x06, '%6.2f' ), # Current [A]
        ( 'P[act]', 0x0c, '%6.0f' ), # Active Power ("Wirkleistung") [W]
        ( 'P[app]', 0x12, '%6.0f' ), # Apparent Power ("Scheinl.") [W]
        ( 'P[rea]', 0x18, '%6.0f' ), # Reactive Power ("Blindl.") [W]
        ( 'PF',     0x1e, '%6.3f' ), # Power Factor   [1]
        ( 'Phi',    0x24, '%6.1f' ), # cos(Phi)?      [1]
        ( 'Freq',   0x46, '%6.2f' )  # Line Frequency [Hz]