Reading values EASTRON SDM220-modbus power meter

could one of these objects connected to my two sd230 modbuss work?

Hey Bard,
I’m struggling long time to read reliable data from the SDM120.
Ive tried it with node-red solution as well as modbus-implementation of ha.
But not reliable.
I would try your node-red implementation but importing ends wit an Unexpected token “ in JSON at position 2
Can you help me, please.
Regards Uwe

Hi @UBS-P sorry for delay, I’ll prepare a quick procedure for insert the code manually.
First of all:

  • do you have already last available node-red addon in your system?

  • have installed the library: node-red-contrib-modbus?

Anyway you can try to load this code:
https://flows.nodered.org/flow/75a4715fb6a3595057343a92abc493e4
this guy prepared also a nice video explaining the configuration of the sdm120 and then the nodered part

when i developed the code I started from this code and then I modified a little the code in order to reduce the number of reading and then demux the data read in one block of code

let me know

Hey Bard,
thanks for supporting.
The code works fine!
Especially the -formerly annoying- error message in lovelace is gone!
Regards
Uwe

good to hear that! if you want to check my code:

  • I’m reading 72 register
  • I’ll demux: power,frequency,current,voltage
    *I will send data to HA using mqtt only if the value is changed
  • every 30min I’ll force data send anyway trough mqtt
[
    {
        "id": "c233fe31.d746b",
        "type": "inject",
        "z": "c5d09c5.47fefe",
        "name": "",
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "repeat": "5",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "x": 150,
        "y": 100,
        "wires": [
            [
                "78678abc.6260ac"
            ]
        ]
    },
    {
        "id": "78678abc.6260ac",
        "type": "function",
        "z": "c5d09c5.47fefe",
        "name": "sdm120 config",
        "func": "msg.payload = { value: msg.payload, 'fc': 4, 'unitid': 1, 'address': 0 , 'quantity': 72 } \nmsg.topic =\"sdm120\"\nreturn msg ",
        "outputs": 1,
        "noerr": 0,
        "x": 340,
        "y": 100,
        "wires": [
            [
                "10575b73.1e080d"
            ]
        ]
    },
    {
        "id": "10575b73.1e080d",
        "type": "modbus-flex-getter",
        "z": "c5d09c5.47fefe",
        "name": "sdm120Read",
        "showStatusActivities": true,
        "showErrors": true,
        "logIOActivities": false,
        "server": "e022a16d.7d87e",
        "useIOFile": false,
        "ioFile": "",
        "useIOForPayload": false,
        "emptyMsgOnFail": false,
        "x": 540,
        "y": 100,
        "wires": [
            [
                "c2897480.708678"
            ],
            []
        ]
    },
    {
        "id": "c2897480.708678",
        "type": "function",
        "z": "c5d09c5.47fefe",
        "name": "",
        "func": "var rawData = new ArrayBuffer(4);\nvar intView = new Uint16Array(rawData);\nvar fltView = new Float32Array(rawData);\n\n\nintView[0] = msg.payload[1]; //low\nintView[1] = msg.payload[0]; //high\n\nvar msg1 = { payload:Math.round(parseFloat(fltView[0].toFixed(1))) };\nmsg1.topic = \"smd/1/voltage\";\n\n\n\nintView[0] = msg.payload[7]; //low\nintView[1] = msg.payload[6]; //high\n\nvar msg2 = { payload:parseFloat(fltView[0].toFixed(1)) };\nmsg2.topic = \"smd/1/current\";\n\n\n\nintView[0] = msg.payload[13]; //low\nintView[1] = msg.payload[12]; //high\nvar msg3 = { payload:Math.round(parseFloat(fltView[0].toFixed(1))) };\nmsg3.topic = \"smd/1/power\";\n\n\n\nintView[0] = msg.payload[71]; //low\nintView[1] = msg.payload[70]; //high\n\nvar msg4 = { payload:parseFloat(fltView[0].toFixed(1)) };\nmsg4.topic = \"smd/1/frequency\";\n\n\n\nreturn [msg1, msg2, msg3 , msg4 ];\n\n",
        "outputs": 4,
        "noerr": 0,
        "x": 770,
        "y": 100,
        "wires": [
            [
                "f7a9ca52.3640d8"
            ],
            [
                "450203de.5d6c8c"
            ],
            [
                "76a2743f.cd745c"
            ],
            [
                "22d0c38e.84ee4c"
            ]
        ]
    },
    {
        "id": "f7a9ca52.3640d8",
        "type": "function",
        "z": "c5d09c5.47fefe",
        "name": "payload is changed",
        "func": "var mem=context.get(\"memory\");\nvar forceCall=global.get(\"force_call\");\n\nnode.status({shape:\"ring\",fill:\"green\",text:\"msg: \"+msg.payload +\" | msg_old:\"+ mem + \" | fc: \"+forceCall});\n\nif ((msg.payload != mem || forceCall)) {\n        context.set(\"memory\",msg.payload);\n        return msg;       \n    }\n\nreturn null;\n\n",
        "outputs": 1,
        "noerr": 0,
        "x": 1010,
        "y": 80,
        "wires": [
            [
                "25585f16.519318"
            ]
        ],
        "info": "if msg payload is changed then return the msg.payload otherwise return null "
    },
    {
        "id": "25585f16.519318",
        "type": "mqtt out",
        "z": "c5d09c5.47fefe",
        "name": "",
        "topic": "sdm120/1/voltage",
        "qos": "0",
        "retain": "true",
        "broker": "3c4f987a.7246",
        "x": 1250,
        "y": 80,
        "wires": []
    },
    {
        "id": "3347fd0.b2d7284",
        "type": "mqtt out",
        "z": "c5d09c5.47fefe",
        "name": "",
        "topic": "sdm120/1/current",
        "qos": "0",
        "retain": "true",
        "broker": "3c4f987a.7246",
        "x": 1250,
        "y": 140,
        "wires": []
    },
    {
        "id": "a9167b3c.ced7f8",
        "type": "mqtt out",
        "z": "c5d09c5.47fefe",
        "name": "",
        "topic": "sdm120/1/power",
        "qos": "0",
        "retain": "true",
        "broker": "3c4f987a.7246",
        "x": 1250,
        "y": 200,
        "wires": []
    },
    {
        "id": "ced7c462.eda5d8",
        "type": "mqtt out",
        "z": "c5d09c5.47fefe",
        "name": "",
        "topic": "sdm120/1/frequency",
        "qos": "0",
        "retain": "true",
        "broker": "3c4f987a.7246",
        "x": 1300,
        "y": 320,
        "wires": []
    },
    {
        "id": "22d0c38e.84ee4c",
        "type": "function",
        "z": "c5d09c5.47fefe",
        "name": "payload is changed",
        "func": "var mem=context.get(\"memory\");\nvar forceCall=global.get(\"force_call\");\n\nnode.status({shape:\"ring\",fill:\"green\",text:\"msg: \"+msg.payload +\" | msg_old:\"+ mem + \" | fc: \"+forceCall});\n\nif ((msg.payload != mem || forceCall)) {\n        context.set(\"memory\",msg.payload);\n        return msg;       \n    }\n\nreturn null;\n\n",
        "outputs": 1,
        "noerr": 0,
        "x": 1010,
        "y": 320,
        "wires": [
            [
                "ced7c462.eda5d8"
            ]
        ],
        "info": "if msg payload is changed then return the msg.payload otherwise return null "
    },
    {
        "id": "76a2743f.cd745c",
        "type": "function",
        "z": "c5d09c5.47fefe",
        "name": "payload is changed",
        "func": "var mem=global.get(\"actPower\");\nvar forceCall=global.get(\"force_call\");\n\nnode.status({shape:\"ring\",fill:\"green\",text:\"msg: \"+msg.payload +\" | msg_old:\"+ mem + \" | fc: \"+forceCall});\n\nif ((msg.payload != mem || forceCall)) {\n        global.set(\"actPower\",msg.payload);\n        return msg;       \n    }\n\nreturn null;\n\n",
        "outputs": 1,
        "noerr": 0,
        "x": 1010,
        "y": 200,
        "wires": [
            [
                "a9167b3c.ced7f8",
                "46985845.386ec8"
            ]
        ],
        "info": "if msg payload is changed then return the msg.payload otherwise return null "
    },
    {
        "id": "450203de.5d6c8c",
        "type": "function",
        "z": "c5d09c5.47fefe",
        "name": "payload is changed",
        "func": "var mem=context.get(\"memory\");\nvar forceCall=global.get(\"force_call\");\n\nnode.status({shape:\"ring\",fill:\"green\",text:\"msg: \"+msg.payload +\" | msg_old:\"+ mem + \" | fc: \"+forceCall});\n\nif ((msg.payload != mem || forceCall)) {\n        context.set(\"memory\",msg.payload);\n        return msg;       \n    }\n\nreturn null;\n\n",
        "outputs": 1,
        "noerr": 0,
        "x": 1010,
        "y": 140,
        "wires": [
            [
                "3347fd0.b2d7284"
            ]
        ],
        "info": "if msg payload is changed then return the msg.payload otherwise return null "
    },
    {
        "id": "7d61ce1e.d8198",
        "type": "inject",
        "z": "c5d09c5.47fefe",
        "name": "",
        "topic": "",
        "payload": "true",
        "payloadType": "str",
        "repeat": "1800",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "x": 170,
        "y": 460,
        "wires": [
            [
                "73731ab6.b5b21c"
            ]
        ]
    },
    {
        "id": "73731ab6.b5b21c",
        "type": "function",
        "z": "c5d09c5.47fefe",
        "name": "",
        "func": "var temp = msg.payload;\nnode.status({shape:\"ring\",fill:\"green\",text:temp});\nif ((temp == \"true\")) {\n        global.set(\"force_call\",true);\n        msg.payload =temp;\n        return msg;       \n    }\n\n",
        "outputs": 1,
        "noerr": 0,
        "x": 390,
        "y": 460,
        "wires": [
            [
                "2859bbe0.5b77a4"
            ]
        ]
    },
    {
        "id": "2859bbe0.5b77a4",
        "type": "delay",
        "z": "c5d09c5.47fefe",
        "name": "",
        "pauseType": "delay",
        "timeout": "10",
        "timeoutUnits": "seconds",
        "rate": "1",
        "nbRateUnits": "1",
        "rateUnits": "second",
        "randomFirst": "1",
        "randomLast": "5",
        "randomUnits": "seconds",
        "drop": false,
        "x": 580,
        "y": 460,
        "wires": [
            [
                "91bb4da7.934a"
            ]
        ]
    },
    {
        "id": "91bb4da7.934a",
        "type": "function",
        "z": "c5d09c5.47fefe",
        "name": "",
        "func": "var forceCall=global.get(\"force_call\");\nif ((forceCall === true)) {\n        global.set(\"force_call\",false);\n        msg.payload =\"false\";\n        return msg;       \n    }\n\n",
        "outputs": 1,
        "noerr": 0,
        "x": 750,
        "y": 460,
        "wires": [
            []
        ]
    },
    {
        "id": "e022a16d.7d87e",
        "type": "modbus-client",
        "z": "",
        "name": "Serial_9600_8_N_1",
        "clienttype": "serial",
        "bufferCommands": true,
        "stateLogEnabled": false,
        "queueLogEnabled": false,
        "tcpHost": "127.0.0.1",
        "tcpPort": "502",
        "tcpType": "DEFAULT",
        "serialPort": "/dev/ttyUSB1",
        "serialType": "RTU-BUFFERD",
        "serialBaudrate": "9600",
        "serialDatabits": "8",
        "serialStopbits": "1",
        "serialParity": "none",
        "serialConnectionDelay": "100",
        "unit_id": "",
        "commandDelay": "30",
        "clientTimeout": "2000",
        "reconnectOnTimeout": true,
        "reconnectTimeout": "5000",
        "parallelUnitIdsAllowed": false
    },
    {
        "id": "3c4f987a.7246",
        "type": "mqtt-broker",
        "z": "",
        "name": "",
        "broker": "localhost",
        "port": "1883",
        "clientid": "",
        "usetls": false,
        "compatmode": false,
        "keepalive": "60",
        "cleansession": true,
        "birthTopic": "",
        "birthQos": "0",
        "birthPayload": "",
        "closeTopic": "",
        "closeQos": "0",
        "closePayload": "",
        "willTopic": "",
        "willQos": "0",
        "willPayload": ""
    }
]
1 Like

Hey Matteo,
sounds good to read all registers in one go.
The bus load is higher but the flow looks clearer :slight_smile:
Since I’m using node red in production system only testing new nodes takes time.
What happens if a bus error occurs and the value is unknown?
Is there a MQTT message triggered?
Regards
Uwe

after the last update to 2021.7 the reading of the estron via modbus no longer works. has anyone solved it?

Hi, the modbus config syntax changed. Did you check that?

yes, i have updated with the new configuration but it doesn’t work anyway. serial connection

Oke had to change too but i’m using rtuovertcp. This is (part of) my config now. Maybe it will help you:

  - type: rtuovertcp
    host: 192.168.5.20
    port: 3001
    name: lifzolder
    sensors:
      - name: solarkwh_v
        unit_of_measurement: V
        address: 0
        input_type: input
        count: 2
        slave: 1
        precision: 2
        data_type: float

      - name: solarkwh_a
        unit_of_measurement: A
        address: 6
        input_type: input
        count: 2
        slave: 1
        precision: 2
        data_type: float

solved thanks to oliver, for those like me who have a serial connection, place my configuration

modbus:
  - type: serial
    method: rtu
    port: /dev/ttyUSB0
    baudrate: 9600
    stopbits: 1
    bytesize: 8
    parity: N
    name: eastron
    sensors:
      - name: voltaggio eastron
        unit_of_measurement: V
        address: 0
        input_type: input
        count: 2
        slave: 1
        precision: 0
        data_type: float
modbus:
  - name: sdm
    type: serial
    method: rtu
    port: /dev/ttyUSB0
    baudrate: 9600
    stopbits: 1
    bytesize: 8
    parity: N
    sensors:
      - name: 630 Phase 2 line to neutral volts
        precision: 2
        register: 2
        register_type: input
        slave: 1
        unit_of_measurement: Volts
        count: 2
        data_type: float

configuration check:

Invalid config for [modbus]: [register] is an invalid option for [modbus]. Check: modbus->modbus->0->sensors->0->register. (See /config/configuration.yaml, line 19).

Hi ebyna,

register is now address.
Some of the options changed, this is one of them.

Hi, could you show me your full configuration of this meter in your HA ?
Im fighting with it long time :frowning: -(
Wthat thats means?

The system cannot restart because the configuration is not valid: Invalid config for [modbus]: value must be one of [<DataType.CUSTOM: ‘custom’>, <DataType.FLOAT16: ‘float16’>, <DataType.FLOAT32: ‘float32’>, <DataType.FLOAT64: ‘float64’>, <DataType.INT16: ‘int16’>, <DataType.INT32: ‘int32’>, <DataType.INT64: ‘int64’>, <DataType.INT8: ‘int8’>, <DataType.STRING: ‘string’>, <DataType.STRING: ‘string’>, <DataType.UINT16: ‘uint16’>, <DataType.UINT32: ‘uint32’>, <DataType.UINT64: ‘uint64’>, <DataType.UINT8: ‘uint8’>] for dictionary value @ data[‘modbus’][0][‘sensors’][0][‘data_type’]. Got ‘float’. (See /config/configuration.yaml, line 12).

### Modbus / Solar ###
modbus:
  - type: rtuovertcp
    host: 1.1.1.1
    port: 3001
    name: NAME
    sensors:
      - name: solarkwh_v
        unit_of_measurement: V
        address: 0
        input_type: input
        count: 2
        slave: 1
        precision: 2
        data_type: float32

      - name: solarkwh_a
        unit_of_measurement: A
        address: 6
        input_type: input
        count: 2
        slave: 1
        precision: 2
        data_type: float32
        #A = +

      - name: solarkwh_w
        unit_of_measurement: W
        address: 12
        input_type: input
        count: 2
        slave: 1
        precision: 2
        data_type: float32
        # reverse_order: true

      - name: solarkwh_hz
        unit_of_measurement: Hz
        address: 70
        input_type: input
        count: 2
        slave: 1
        precision: 2
        data_type: float32

      - name: solarkwh_kwhtotal
        unit_of_measurement: kWh
        address: 342
        input_type: input
        count: 2
        slave: 1
        precision: 2
        data_type: float32

      - name: solarkwh_kwhimport
        unit_of_measurement: kWh
        address: 72
        input_type: input
        count: 2
        slave: 1
        precision: 2
        data_type: float32

      - name: solarkwh_kwhexport
        unit_of_measurement: kWh
        address: 74
        input_type: input
        count: 2
        slave: 1
        precision: 2
        data_type: float32
        state_class: total_increasing
        device_class: energy
1 Like

Something still is wrong on my HA :frowning:
2022-08-30 16:32:06.005 ERROR (MainThread) [homeassistant.components.ipp.coordinator] Error fetching ipp data: Invalid response from API: Timeout occurred while connecting to IPP server.

I think meter and RS converter working well because on Domoticz everything was ok.

What converter are you using?

i hve got somenting like this:
https://www.google.com/imgres?imgurl=http%3A%2F%2Feliptor.pl%2Fgalerie%2Fk%2Fkonwerter-usb-rs485-ft232-ftdi_1819.jpg&imgrefurl=https%3A%2F%2Felecena.pl%2Fproduct%2F15802089%2Fkonwerter-usb-rs485-ft232-ftdi-z-zabezpieczeniami&tbnid=FVTn5lVNupEcbM&vet=12ahUKEwiohcnLl-_5AhXWrIsKHdj9Br4QMyg4egUIARCFAg..i&docid=AeAIwH3OMLFFXM&w=606&h=577&q=modbus%20converter%20ttl%20rs485&client=firefox-b-d&ved=2ahUKEwiohcnLl-_5AhXWrIsKHdj9Br4QMyg4egUIARCFAg
but with classic USB-A. It was working great with domoticz.
Now i think everything working well but i dont know where to find this data in HA. What should i do ?:wink:
I have modified configuration.yaml as you wtore with small modification - now everything is working (there aro noerror messages) but i dont know how to showi it in my dashboard.
Im the really begginer and i cannot find a propper manual on internet.

Ah I see.
You changed my config, right? Becuase I’m using a network connected converter.

That’s right. i have chacnged your config and it looks like bellow.
I was checked modbus communication with my notebook and it is working.

modbus:
  - name: eastron
    type: serial
    method: rtu
    port: /dev/ttyUSB0
    baudrate: 2400
    stopbits: 1
    bytesize: 8
    parity: N
    sensors:
      - name: Volts
        unit_of_measurement: V
        address: 0
        input_type: input
        count: 2
        slave: 1
        precision: 2
        data_type: float32
      - name: Current
        unit_of_measurement: A
        address: 6
        input_type: input
        count: 2
        slave: 1
        precision: 2
        data_type: float32
      - name: Active_Power
        unit_of_measurement: W
        address: 12
        input_type: input
        count: 2
        slave: 1
        precision: 2
        data_type: float32
      - name: Frequency
        unit_of_measurement: Hz
        address: 70
        input_type: input
        count: 2
        slave: 1
        precision: 2
        data_type: float32
      - name: Import_Active_Energy
        unit_of_measurement: kWh
        address: 72
        input_type: input
        count: 2
        slave: 1
        precision: 2
        data_type: float32
      - name: Total_Active_Energy
        unit_of_measurement: kWh
        address: 342
        input_type: input
        count: 2
        slave: 1
        precision: 2
        data_type: float32

So how can i show this values in homeassistant now ?

edit:
I have found sensors and everything is working now :slight_smile: Thank you all.

1 Like