[SOLVED] Modbus Energy Meter - reading float registers

Well spotted, that man! A sneaky one.

I’d view setting up the config as one block (to include unused registers) as marginally less overhead than setting up multiple virtual slaves.
There is a caveat that your device may reject access of unused registers, so the multiple slave way is more certain.
Doubt there is much in it performance wise, until you get to hundreds of Modbus slaves or want sub-100mS poll rates.

If you are going to have several Modbus serial devices, you will have to juggle baud rates+parity so they are all alike (assuming a single wired bus). Many default to 9600 no-parity these days. This is fairly modest but generally reliable enough for long wiring runs.

Now, I’m having doubts about the config ‘length’ parameter - I thought it should be smart enough to match the chosen datatype. i.e, for a contact, a length of 1 specifies 1 bit only, for a uint16 a single 16bit register, for float32 a pair of 16bit registers.
Is it not working like that? (won’t show up with single-item slaves)

The length is documented as follows in the wiki

number of data items to read. Data items here refers to registers, coils or discrete inputs depending on the slave type. For example, if the goal is to read one item with valuetype=int32, one needs to read two registers (2 * 16bit = 32bit), thus length = 2. If three coils are of interest, one should specify length = 3

So basically you need to define the number of binary values to retrieve (with discrete inputs and coils) or number of registers to retrieve (with input registers and holding registers)

Does this work as expected?

Best
Sami

Hi, it is working as expected now.

yup, works great. I think Rossko was saying it would be nice if the binding automatically calculated length based on valuetype, so if you set it to float32 it would know to read 2 registers. I don’t know if I would like that though, I like having the control to change it manually

I do see point in that, and certainly would be easier for users. However, I’m afraid changing the interpretation of the length parameter would be backwards incompatible and as such would cause issues to our users when upgrading.

This would be good improvement for openhab2 configuration however, since there we could introduce backwards incompatible changes. That’s still quite much in the air, currently one uses openhab1 version of modbus binding with openhab2

Just for the record and to ensure I understood correctly. You would prefer length to denote count of values to read, e.g. Number of float32 values, number of 16bit unsigned integers… Etc?

I do believe we need ability to control the count, otherwise one would always end up as many “slaves” (modbus requests) as there are items…

Best
Sami

On reflection, I do not think changing the nature of ‘length’ (which should/would also be reflected in ‘start’ and ‘index’ ??) is necessary or desirable.
I think for slaves with mixed datatypes it would become a nightmare keeping track of which register actually was meant at start+index

At its heart, Modbus protocol only knows binary (coil/contact) and register (16-bit) types. Anything we layer onto that, like 32-bit or even 64-bit formats, or text blocks, or image code … is just an interpretation.

Keep it simple and consistent; configuration params directly related to “native” Modbus forms. That way will always allow for any desired interpretation on top of the Modbus layer, while the opposite may not be true.

1 Like

Good point about the text and other data formats, I did not even think of those. I think keeping it simple here also means not assuming too much how the data will be used.

Ideally I would like to see the “interpretation” (valuetype) separated from the raw requests (binary data). Since you might want to just query all the registers at once, and then intrerpret some as float32, some as uint16 etc. I think good place to do this kind modification would be openhab2 migration and changes related to that. As far as I understand the new item /thing /channel configuration approach in openhab2 would make this really convenient.

What do you think?

Edit : example of one way how configuration could be structured in openhab2. The post did not comment on valuetype though…

Edit2: yes indeed start denotes the register (or coil / discrete input), so it would make sense that length has the same interpretation. However the read index defined in the item definition is different, see wiki for details. The item read index has different interpretation depending of valuetype.

Lots of elegance in separating “Modbus map” (strictly binaries and 16bit-registers, addressed in standard Modbus style) from “logical map” (bits, bytes, floats, doubles, blah, for use within OH)

In OH-1 terms, valuetype ought really be associated with the Item rather then in the binding cfg. But we got what we got, I am not suggesting any breaking change for OH1!

I have no idea how OH-2 works, but Thing seems like the place for underlying Modbus slave defining? It follows that interpretation datatype logically belongs to the Item still, yes?
I would guess there are sensible defaults that can be assumed, such as that a number-flavour-item would default interpret raw data as uint16.
Would also guess that we would need a means to declare or force the type somehow; and this is where the Channel comes in (as well as selecting from the raw block by index)?.

There is a consistency issue buried in there; when indexing into a “raw Modbus block” of 16bit-registers, should you specify index by raw registers count, or by the chosen format/type count (as we do now)? Either way has its pitfalls and requires the configuring user to have a good understanding.
Mixed types within a block presents bigger pitfalls with mixed indexing?
Yet if you stick to ‘native’ modbus single-register methods, it gets difficult to designate individual bytes - which would be useful for text handling or oddball ACBD 32-bit layouts etc.
Dunno the answer here. Gut instinct is for raw/native indexing (with a Hi/Lo option for the infrequent byte requirement)

My doubt earlier about how existing ‘length’ works was confusion with half-remembered fact of current ‘index’ being of fluid meaning, depending on type.

The old-tech approach of Modbus (a natural legacy of its history) coupled with endless manufacturer variety, is I think always going to require a reasonable level of understanding from the user.

1 Like

Well that was a good summary! I have pretty vague understanding as well when it comes to openhab2 concepts but I think you are on a right way.

Good point about indexing, that is tricky indeed… Perhaps we could solve it by making it more explicit, that you would declare if you want to pick index by bit/word/item? This certainly needs testing when developed…

Best
Sami

Sorry but i dont understand how to configure SDM120 to work with openhab2 by modbus bindig
My configuration:
modbus.cfg

modbus:poll=500
writemultipleregisters=true

modbus:serial.biuroLight.connection=/dev/ttyUSB0:19200:8:none:1:rtu
modbus:serial.biuroLight.type=holding
modbus:serial.biuroLight.id=3
modbus:serial.biuroLight.start=0
modbus:serial.biuroLight.length=1
modbus:serial.biuroLight.valuetype=uint8

modbus:serial.biuroLST.connection=/dev/ttyUSB0:19200:8:none:1:rtu
modbus:serial.biuroLST.type=holding
modbus:serial.biuroLST.id=3
modbus:serial.biuroLST.start=3
modbus:serial.biuroLST.length=2

modbus:serial.sdm120L1V.connection=/dev/ttyUSB0:9600:8:none:1:rtu
modbus:serial.sdm120L1V.type=input
modbus:serial.sdm120L1V.id=11
modbus:serial.sdm120L1V.start=0
modbus:serial.sdm120L1V.length=2
modbus:serial.sdm120L1V.valuetype=float32

item to sdm120

Number L1V "Volt [%.1f V]" (sdm120) {modbus="sdm120L1V:0"}

and a have error:

2017-02-07 12:57:51.905 [ERROR] [t.wimpi.modbus.io.ModbusRTUTransport] - Last request: 0b 04 00 00 00 02 71 61
2017-02-07 12:57:51.907 [ERROR] [t.wimpi.modbus.io.ModbusRTUTransport] - failed to read: Error reading response (EOF)
2017-02-07 12:57:51.909 [ERROR] [pi.modbus.io.ModbusSerialTransaction] - execute try 2/3 error: I/O exception - failed to read. Request: net.wimpi.modbus.msg.ReadInputRegistersRequest@7f9bea (unit$
2017-02-07 12:57:53.448 [ERROR] [t.wimpi.modbus.io.ModbusRTUTransport] - Last request: 0b 04 00 00 00 02 71 61
2017-02-07 12:57:53.450 [ERROR] [t.wimpi.modbus.io.ModbusRTUTransport] - failed to read: Error reading response (EOF)
2017-02-07 12:57:53.453 [ERROR] [pi.modbus.io.ModbusSerialTransaction] - execute try 3/3 error: I/O exception - failed to read. Request: net.wimpi.modbus.msg.ReadInputRegistersRequest@7f9bea (unit$
2017-02-07 12:57:53.455 [ERROR] [pi.modbus.io.ModbusSerialTransaction] - execute reached max tries 3, throwing last error: I/O exception - failed to read. Request: net.wimpi.modbus.msg.ReadInputRe$
2017-02-07 12:57:53.458 [ERROR] [.binding.modbus.internal.ModbusSlave] - ModbusSlave (sdm120L1V): Error getting modbus data for request net.wimpi.modbus.msg.ReadInputRegistersRequest@7f9bea. Error$
2017-02-07 12:57:56.307 [ERROR] [t.wimpi.modbus.io.ModbusRTUTransport] - Last request: 0b 04 00 00 00 02 71 61
2017-02-07 12:57:56.310 [ERROR] [t.wimpi.modbus.io.ModbusRTUTransport] - failed to read: Error reading response (EOF)
2017-02-07 12:57:56.314 [ERROR] [pi.modbus.io.ModbusSerialTransaction] - execute try 1/3 error: I/O exception - failed to read. Request: net.wimpi.modbus.msg.ReadInputRegistersRequest@223b4d (unit$
2017-02-07 12:57:57.855 [ERROR] [t.wimpi.modbus.io.ModbusRTUTransport] - Last request: 0b 04 00 00 00 02 71 61
2017-02-07 12:57:57.858 [ERROR] [t.wimpi.modbus.io.ModbusRTUTransport] - failed to read: Error reading response (EOF)
2017-02-07 12:57:57.862 [ERROR] [pi.modbus.io.ModbusSerialTransaction] - execute try 2/3 error: I/O exception - failed to read. Request: net.wimpi.modbus.msg.ReadInputRegistersRequest@223b4d (unit$
2017-02-07 12:57:59.404 [ERROR] [t.wimpi.modbus.io.ModbusRTUTransport] - Last request: 0b 04 00 00 00 02 71 61
2017-02-07 12:57:59.407 [ERROR] [t.wimpi.modbus.io.ModbusRTUTransport] - failed to read: Error reading response (EOF)
2017-02-07 12:57:59.411 [ERROR] [pi.modbus.io.ModbusSerialTransaction] - execute try 3/3 error: I/O exception - failed to read. Request: net.wimpi.modbus.msg.ReadInputRegistersRequest@223b4d (unit$
2017-02-07 12:57:59.414 [ERROR] [pi.modbus.io.ModbusSerialTransaction] - execute reached max tries 3, throwing last error: I/O exception - failed to read. Request: net.wimpi.modbus.msg.ReadInputRe$
2017-02-07 12:57:59.417 [ERROR] [.binding.modbus.internal.ModbusSlave] - ModbusSlave (sdm120L1V): Error getting modbus data for request net.wimpi.modbus.msg.ReadInputRegistersRequest@223b4d. Error$

i have OH2 build #777
binding-modbus1 - 1.10.0.SNAPSHOT
problem show when i add sdm120L1V slave
Anyone can help me ?

I have not working with OH2, so I don’t know if this is a OH2 issue or not.

But, you cannot have devices on the same serial network with different baud speeds. Your biuroLight and biuroLST are on 19200 baud, so you need to reconfigure SDM120 to 19200 baud as well. But the max baud rate SDM120 can work on is 9600. So you need your to bring down your other two devices to 9600 as well. Other option is to get another USB RS485 converter and run the SDM120 on a different serial line.

I hope this is the issue. I am not a modbus expert.

This is true, so that needs to be solved before even considering anything else.

Refer to this note on the wiki page for more information.

Best
Sami

Hi. I use your post to connect my sdm120 - it works, thank you :slight_smile:
I never deal with modbus, can you share your modbus.cfg with other parameters for sdm120 like apparent power, reactive power, power factor, etc?

Here it is:

# read voltage registers
modbus:serial.sdm120V1.connection=/dev/ttyUSB0:2400:8:none:1:rtu
modbus:serial.sdm120V1.type=input
modbus:serial.sdm120V1.valuetype=float32
modbus:serial.sdm120V1.length=2
modbus:serial.sdm120V1.start=0
modbus:serial.sdm120V1.id=1

# read current registers
modbus:serial.sdm120V2.connection=/dev/ttyUSB0:2400:8:none:1:rtu
modbus:serial.sdm120V2.type=input
modbus:serial.sdm120V2.valuetype=float32
modbus:serial.sdm120V2.length=2
modbus:serial.sdm120V2.start=6
modbus:serial.sdm120V2.id=1

# read power registers
modbus:serial.sdm120V3.connection=/dev/ttyUSB0:2400:8:none:1:rtu
modbus:serial.sdm120V3.type=input
modbus:serial.sdm120V3.valuetype=float32
modbus:serial.sdm120V3.length=2
modbus:serial.sdm120V3.start=12
modbus:serial.sdm120V3.id=1

# read Apparent power registers
modbus:serial.sdm120V4.connection=/dev/ttyUSB0:2400:8:none:1:rtu
modbus:serial.sdm120V4.type=input
modbus:serial.sdm120V4.valuetype=float32
modbus:serial.sdm120V4.length=2
modbus:serial.sdm120V4.start=18
modbus:serial.sdm120V4.id=1

# read Reactive power registers
modbus:serial.sdm120V5.connection=/dev/ttyUSB0:2400:8:none:1:rtu
modbus:serial.sdm120V5.type=input
modbus:serial.sdm120V5.valuetype=float32
modbus:serial.sdm120V5.length=2
modbus:serial.sdm120V5.start=24
modbus:serial.sdm120V5.id=1

# read Power factor registers
modbus:serial.sdm120V6.connection=/dev/ttyUSB0:2400:8:none:1:rtu
modbus:serial.sdm120V6.type=input
modbus:serial.sdm120V6.valuetype=float32
modbus:serial.sdm120V6.length=2
modbus:serial.sdm120V6.start=30
modbus:serial.sdm120V6.id=1

# read Power factor registers
modbus:serial.sdm120V7.connection=/dev/ttyUSB0:2400:8:none:1:rtu
modbus:serial.sdm120V7.type=input
modbus:serial.sdm120V7.valuetype=float32
modbus:serial.sdm120V7.length=2
modbus:serial.sdm120V7.start=70
modbus:serial.sdm120V7.id=1

# read Import active energy registers
modbus:serial.sdm120V8.connection=/dev/ttyUSB0:2400:8:none:1:rtu
modbus:serial.sdm120V8.type=input
modbus:serial.sdm120V8.valuetype=float32
modbus:serial.sdm120V8.length=2
modbus:serial.sdm120V8.start=72
modbus:serial.sdm120V8.id=1

# read Export active energy registers
modbus:serial.sdm120V9.connection=/dev/ttyUSB0:2400:8:none:1:rtu
modbus:serial.sdm120V9.type=input
modbus:serial.sdm120V9.valuetype=float32
modbus:serial.sdm120V9.length=2
modbus:serial.sdm120V9.start=74
modbus:serial.sdm120V9.id=1

# read Import reactive energy registers
modbus:serial.sdm120V10.connection=/dev/ttyUSB0:2400:8:none:1:rtu
modbus:serial.sdm120V10.type=input
modbus:serial.sdm120V10.valuetype=float32
modbus:serial.sdm120V10.length=2
modbus:serial.sdm120V10.start=76
modbus:serial.sdm120V10.id=1

# read Export reactive energy registers
modbus:serial.sdm120V11.connection=/dev/ttyUSB0:2400:8:none:1:rtu
modbus:serial.sdm120V11.type=input
modbus:serial.sdm120V11.valuetype=float32
modbus:serial.sdm120V11.length=2
modbus:serial.sdm120V11.start=78
modbus:serial.sdm120V11.id=1

# read Total active energy registers
modbus:serial.sdm120V12.connection=/dev/ttyUSB0:2400:8:none:1:rtu
modbus:serial.sdm120V12.type=input
modbus:serial.sdm120V12.valuetype=float32
modbus:serial.sdm120V12.length=2
modbus:serial.sdm120V12.start=342
modbus:serial.sdm120V12.id=1

# read Total reactive energy registers
modbus:serial.sdm120V13.connection=/dev/ttyUSB0:2400:8:none:1:rtu
modbus:serial.sdm120V13.type=input
modbus:serial.sdm120V13.valuetype=float32
modbus:serial.sdm120V13.length=2
modbus:serial.sdm120V13.start=344
modbus:serial.sdm120V13.id=1

Hi @fohdeesha

I have rs485 energy meter.
I am getting byte streaming in hex as response correct but I want 3rd parameter from starting address and I have following configurations.

openhab.cfg:

modbus:poll=3000
modbus:writemultipleregisters=true
modbus:serial.sdm120.connection=/dev/ttyUSB0:9600:8:none:1:rtu
modbus:serial.sdm120.type=holding
modbus:serial.sdm120.valuetype=float32
modbus:serial.sdm120.length=12
modbus:serial.sdm120.start=2100
modbus:serial.sdm120.id=1

items:
Number METER {modbus=“sdm120:0”}

i am getting very large number in event log.

my logs:

13:23:38.112 [DEBUG] [i.modbus.io.ModbusRTUTransport:77   ] - Sent: 01 03 08 34 00 0c 06 61 

13:23:38.156 [DEBUG] [i.modbus.io.ModbusRTUTransport:141 ] - Response: 01 03 18 00 01 2c ef 00 00 00 00 43 9c 13 9b 00 00 00 00 00 00 00 00 00 00 00 00 62 d7
13:23:38.163 [INFO ] [runtime.busevents :26 ] - METER state updated to 0.00000000000000000000000000000000000000010795463239311958232689320336707184883770009974022489854039278352258561521903601487792911939322948455810546875
13:23:41.161 [DEBUG] [i.modbus.io.ModbusRTUTransport:77 ] - Sent: 01 03 08 34 00 0c 06 61
13:23:41.206 [DEBUG] [i.modbus.io.ModbusRTUTransport:141 ] - Response: 01 03 18 00 01 2c f2 00 00 00 00 43 9c 14 db 00 00 00 00 00 00 00 00 00 00 00 00 54 5c
13:23:41.208 [INFO ] [runtime.busevents :26 ] - METER state updated to 0.0000000000000000000000000000000000000001079588362885125567781059745558217185860939405260505280877080547274372845922840724597335793077945709228515625
13:23:44.209 [DEBUG] [i.modbus.io.ModbusRTUTransport:77 ] - Sent: 01 03 08 34 00 0c 06 61
13:23:44.254 [DEBUG] [i.modbus.io.ModbusRTUTransport:141 ] - Response: 01 03 18 00 01 2c f5 00 00 00 00 43 9c 16 1a 00 00 00 00 00 00 00 00 00 00 00 00 22 a9

Please tell me the correct settings so that i can get correct value on event bus.

Thanks
shrikant

You might have to reveal which one exactly. Given that you are not looking at the same registers as anyone else, I guess it is not an SDM120 really

Hello.

Hope you can read my poor English writeing. :slight_smile:

I have 14 SDM120 in my fusebox, one for each fuce, and read the results in IndigoSCADA.

There was problems in the start, but it was solved. All 14 is on a single Daisy Chain.

I have also bought some RS-WS-NO1-8 temperature and humidity sensors.

I hope to Connect them to IndigoSCADA, but has not been able to change the Modbus-adress so far.

I have seen Your videos, and tried to find the files (485 parameter configuration tool. exe ) you use on the net, with no luck.

Is it posible to download them here?

Echo Sierra

Hi Echo,

It was a long time ago when I used this sensor the last time. I have zipped all the documents I still have on my laptop and put the files on my Google Drive:
https://drive.google.com/file/d/1j2thtUbN0WLiHZOoF8ymi1iWkI-MjZcO/view?usp=sharing

I hope it helps.

Regards,
Csongor

Hello, and Thank You.

I found it on the net side in a letter from You to another interested guy.

It worked, and I have endred the adress.

Hope You still is makeing the nice interesting movies, I like them. Good work.

Thant You again.

Egil.

Hi everyone! i recently bought a couple of SDM120M for testing, im already reading correct values, but im having trouble changing the ID of the meters. Anyone has done this? Im working directly with a Python script using pymodbus.

Regards,

José

You need to press and hold on the button until the word Set appears on the screen, and you can change the modbus address using function 16, address: 20, quantity: 2 and the value should be the new slave address.