Reading from a SDM120 meter using EmonHub

In my admin panel, I only had emonhub, redis-server and mosquitto. So I took your link (thanks again), but needed to modify it a bit for my odd setup. The good news: it works (did I already thank you?)! I have my inputs! I quickly tried to make a feed, but that didn’t work yet. First I’ll read myself into it. I’ll beter use a new topic I guess if I have some troubles.

The steps to enable emoncms_mqtt (I tried some things and used this topic, so it might be they are not complete):

sudo ln -s /var/www/html/emoncms/scripts/services/emoncms_mqtt/emoncms_mqtt.service
/lib/systemd/system
sudo nano -w /etc/systemd/system/emoncms_mqtt.service (changed USER=pi and a path)
sudo apt-get install libmosquitto-dev
sudo pecl install Mosquitto-alpha
sudo phpenmod mosquitto
sudo systemctl daemon-reload
systemctl status emoncms_mqtt.service
1 Like

The graph module was missing, but I managed to install it. Now I have nice graphs. Thanks again @borpin!!

To experiment more with emoncms is the first on my 2DO list (might take a while). But to stay on topic: next is adding another SDM120 and a SDM630 in a modbus daisy chain. As far as I understand the EmonHubMinimalModbusInterfacer.py currently can’t handle this as the modbus adress is hard coded (self._rs485 = minimalmodbus.Instrument(device, 1)). Are there any plans to integrate that?

No immediate plans I’m afraid, your welcome to see if you can modify it to get this to work if you would like to give it a go? I did want to try something similar for the MBUS interfacer, but havent had a chance to look at that yet.

I’ll try to make it support modbus daisy chain reading. Might take a while :roll_eyes:. I’m just wondering if eg. these settings could work out as a base?

[[SDM120]]
    Type = EmonHubMinimalModbusInterfacer
    [[[init_settings]]]
        device = /dev/ttyUSB0
        baud = 9600
        bytesize = 8
        parity   = PARITY_NONE
        stopbits = 1
        timeout  = 1
    [[[runtimesettings]]]
        pubchannels = ToEmonCMS,
        read_interval = 10
        nodename1 = heatpump
        modbus_addr1 = 1
        registers1 = 0,6,12,18,30,70,72,74,76
        names1 = V,I,P,VA,PF,FR,EI,EE,RI
        precision1 = 2,3,1,1,3,3,3,3,3
        nodename2 = pv
        modbus_addr2 = 2
        registers2 = 0,6,12,18,30,70,72,74,76
        names2 = V,I,P,VA,PF,FR,EI,EE,RI
        precision2 = 2,3,1,1,3,3,3,3,3

But then the runtimesettings would have 2 or more nodenames. And maybe that is impossible because of the internal workings of emonhub?

Another idea would be a [[SDM120_1]] and a [[SDM120_2]]. But then one must avoid that they read /dev/ttyUSB0 at the same time, because there is only one RS485 USB adapter at /dev/ttyUSB0. At least that is what I think the error is when I try to run my own script when the emonhub service in running in the background: minimalmodbus.NoResponseError: No communication with the instrument (no answer). Most of the time I don’t get that error, but I guess it happens when emonhub is reading as well (I see some null-values in emoncms as well).

Good question, that does get a bit tricky but your suggestion might work, these settings are all internal to the modbus interfacer and so it can choose to handle these in the way you suggest without requiring changes elsewhere in emonhub…

I wonder if this might work, might be easier to manage in terms on the implementation?:

[[SDM120]]
    Type = EmonHubMinimalModbusInterfacer
    [[[init_settings]]]
        device = /dev/ttyUSB0
        baud = 9600
        bytesize = 8
        parity   = PARITY_NONE
        stopbits = 1
        timeout  = 1
    [[[runtimesettings]]]
        pubchannels = ToEmonCMS,
        read_interval = 10
        [[[[devices]]]]
            [[[[[heatpump]]]]]
                modbus_addr = 1
                registers = 0,6,12,18,30,70,72,74,76
                names = V,I,P,VA,PF,FR,EI,EE,RI
                precision = 2,3,1,1,3,3,3,3,3
            [[[[[pv]]]]]
                modbus_addr = 2
                registers = 0,6,12,18,30,70,72,74,76
                names = V,I,P,VA,PF,FR,EI,EE,RI
                precision = 2,3,1,1,3,3,3,3,3

The [[SDM120]] wouldn’t be correct anymore with several kWh meters. Maybe [[ttyUSB0]] is better? Is that name within [[]] actually used somewhere or is it just an informative name? And maybe just like with other nodes it might be better to add units = V, A, W, ...?

I don’t know if the following, a bit different approach is better (like I said: newbe here :slight_smile: ):

[interfacers]
[[ttyUSB0]]
    Type = EmonHubMinimalModbusInterfacer
    [[[init_settings]]]
        device = /dev/ttyUSB0
        baud = 9600
        bytesize = 8
        parity   = PARITY_NONE
        stopbits = 1
        timeout  = 1
        nodeids = 27, 28, #must match the nodes in de [nodes] section
    [[[runtimesettings]]]
        pubchannels = ToEmonCMS,
        read_interval = 10        
        
[nodes]
## See config user guide: https://github.com/openenergymonitor/emonhub/blob/emon-pi/conf/emonhub.conf
[[27]]
    nodename = heatpump
    modbus_addres = 1
    [[[rx]]]
        registers = 0,6,12,18,30,70,72,74,76 # normally not present
        names = V,I,P,VA,PF,FR,EI,EE,RI
        # datacodes = h, h, h, h, h, h, h, h, h, h, L --> not necessary?
        # scales = 1,1,1,0.01,0.1,0.1,0.1,0.1,0.1,0.1,1
        precision = 2,3,1,1,3,3,3,3,3   # a bit like 'scales'?
        units = V, A, W, ...

[[28]]
    nodename = pv
    modbus_addres = 2
    [[[rx]]]
        registers = 0,6,12,18,30,70,72,74,76 # normally not present
        names = V,I,P,VA,PF,FR,EI,EE,RI
        precision = 2,3,1,1,3,3,3,3,3 # a bit like 'scales', but still not the same?
        units = V, A, W, ...       

I’m trying to test a python script with 2x SDM120 daisy chained on the same serial link. But I still have to add a try part and the SDM630 (see my question at stackoverflow). I’ll keep you updated.

@TrystanLea, any chance that you’ll find time for a different approach?

I also include three scripts I wrote:

  • sdm120.txt (2.1 KB) : just to test one SDM120.
  • sdm120_daisychain_sleep.txt (2.3 KB);: to test multiple daisy chained modbus meters. It uses time.sleep to avoid a minimalmodbus.NoResponseError.
  • sdm120_daisychain_alt.txt (2.6 KB) : to test multiple daisy chained modbus meters. This alternative uses try-except to avoid a minimalmodbus.NoResponseError.

I don’t understand much of the inner workings of emonhub nor EmonHubMinimalModbusInterfacer.py, but I hope you can use the last script to enable daisy chaining for EmonHubMinimalModbusInterfacer.py.

At the moment you could already help me if EmonHubMinimalModbusInterfacer.py could allow the modbus address to be set in emonhub.conf, eg:

        device = /dev/ttyUSB0
        address = 2
        ...

It would make my steps at topic Reading modbus kWh meters using EmonHub (SDM120 and SDM630) a tad shorter :slight_smile: .

I think (i.e. I’m not entirely sure) the cause of your timeouts is that you’re reading the same instrument rapidly in succession vice reading both instruments.

Here’s a code snippet from a script I use to read two WattsOn kWh meters via minimalmodbus.
I’ve never had an issue reading both meters, and I’ve never needed to use a delay between readings.

#!/usr/bin/python
import threading, datetime, time, logging, minimalmodbus, requests, os, os.path
from apscheduler.scheduler import Scheduler
from influxdb import InfluxDBClient as idbc

wattson1 = minimalmodbus.Instrument("/dev/USB0", 1)
wattson1.serial.baudrate = 9600
wattson2 = minimalmodbus.Instrument("/dev/USB0", 2)
wattson2.serial.baudrate = 9600

Note that you need a definition for each instrument you want to read.

You read the instruments like this:

VOLT = wattson1.read_float(792)        # voltage C-N
WHWH = wattson2.read_float(768)        # water htr Wh

Everything in this block except for the Baud rate is a minimalmodbus default.
The rest of the items don’t really need to be declared explicitly, although there’s
definitely no harm in doing so.

instrument.serial.baudrate = 9600         # Baud
instrument.serial.bytesize = 8
instrument.serial.parity   = minimalmodbus.serial.PARITY_NONE
instrument.serial.stopbits = 1
instrument.serial.timeout  = 1          # seconds
instrument.mode = minimalmodbus.MODE_RTU   # rtu or ascii mode

I have tried it before, but even with different definitions for each instrument, I couldn’t get it to work (see my initial post at stackoverflow). A user responds with “The Modbus specification established this value at 3.5 characters (the time it takes to send 3 and a half characters serially on the bus at the baud rate you are using). Unfortunately, some manufacturers do not stick to this rule. So some of those devices just take longer than 3.5 characters time to release control of the bus.

I know, but while I was testing I wanted to make sure every setting really was the correct one and that I didn’t overlook some setting :-). But thanks for the feedback!

Thanks @m2ts for this scripts and the great documentation of what you have done here Reading modbus kWh meters using EmonHub (SDM120 and SDM630). I will take a closer look at this and see what I can do. I have now merged the minimalmodbus branch into the master branch of emonhub which is one step forwards.

I haven’t tested this but hopefully the following should work for setting the address: https://github.com/openenergymonitor/emonhub/compare/minimalmodbus_address this is in a development branch so that it can be tested before merging.

I’ve just updated that to read from multiple addresses and tested reading from a single sdm120 that I have here, which still works fine. Let me know if it works for you @m2ts, should just need setting of addresses in the conf file like so:

[[SDM120]]
    Type = EmonHubMinimalModbusInterfacer
    [[[init_settings]]]
        device = /dev/ttyUSB0
        baud = 2400
    [[[runtimesettings]]]
        pubchannels = ToEmonCMS,
        read_interval = 10
        nodename = sdm120
        # prefix = sdm_
        addresses = 1,2,
        registers = 0,6,12,18,30,70,72,74,76
        names = V,I,P,VA,PF,FR,EI,EE,RI
        precision = 2,3,1,1,3,3,3,3,3

@TrystanLea, if I understand correctly this new code allows me to set the modbus address by editing emonhub.conf instead of EmonHubMinimalModbusInterfacer.py. But it doesn’t allow me to use daisy chaining yet. Correct?

I’m a bit confused about the addresses = 1,2,, shouldn’t it be address = 1 or address = 2 or …?

I’m just at my baby steps in using git, so I’m not sure how I can use the new code. The following didn’t seem to work.

cd /opt/openenergymonitor/emonhub
git fetch --all
git checkout minimalmodbus_address
git pull
sudo service emonhub restart

I got an error:

 error: Your local changes to the following files would be overwritten by checkout:
        src/interfacers/EmonHubMinimalModbusInterfacer.py
Please commit your changes or stash them before you switch branches.
Aborting

This means you have edited that file, correct?

I am guessing you can specify several addresses at once. Note the trailing comma is important.

daisy chaining should hopefully work… I copied the implementation that you put together in your code

Yes, indeed. I don’t know how I “override” that with a git command, but I renamed EmonHubMinimalModbusInterfacer.py to EmonHubMinimalModbusInterfacer.py.old and did the git-command again. This workaround seems to work as I now see the new code in EmonHubMinimalModbusInterfacer.py.

@TrystanLea, thanks! I have tried the new code, but at emoncms > Inputs, I only see the values (eg. P 5.7 W) of address 2.

What I don’t understand is that I can have a setting of multiple adresses (eg. addresses = 1,2,), but only one nodename. I would expect to also have two possible nodenames (eg. heatpump and solar). I would also expect to be able to have other registers for address 2 then 1 (eg. the SDM630 has some extra registers that the SDM120 doesn’t have). Or am I missing something? My config says:

[[SDM120]]
    Type = EmonHubMinimalModbusInterfacer
    [[[init_settings]]]
        device = /dev/ttyUSB_household
        #modbus_addres = 1
        baud = 9600
    [[[runtimesettings]]]
        pubchannels = ToEmonCMS,
        read_interval = 10
        nodename = heatpump
        # prefix = sdm_
        addresses = 1,2,
        registers = 0,6,12,18,30,70,72,74,76
        names = V,I,P,VA,PF,FR,EI,EE,RI
        precision = 2,3,1,1,3,3,3,3,3

IIRC if you do a git status it will give you the command. You need to checckout the original file from the upstream repository.

A little late to the party with this, but to avoid any confusion (for future readers of this thread)
M-Bus refers to Meter Bus.

Ref: https://m-bus.com/
M-Bus (Meter-Bus) is a European standard (EN 13757-2 physical and link layer, EN 13757-3 application layer) for the remote reading of water meter, gas or electricity meters. M-Bus is also usable for other types of consumption meters.

Not the same as, and incompatible with, Modbus.

[quote=“m2ts, post:118, topic:16475”]

@TrystanLea, any chance to have a look at the code. I still think that daisy chaining (namely reading the two SDM120s and one SDM630 on one serial line) isn’t possible with that code. A config-file like your post at 13 April or mine just after your post seems more logical to me. But again: I am a total newbie.

At the moment my SDM630 is already mounted in the fuse board. The two SDM120 aren’t, as I can experiment with them more easily. But I hope to be able to mount them soon :wink: .

Will hopefully get a chance to look at this soon, I will wire up a couple of modbus meters and see what I get. Im working on the similar requirement for multiple devices on a bus for the MBUS interfacer so will hopefully be able to apply what I learn from that to the modbus interfacer.

1 Like