Modbus Things

Just remembered one more thing. The configuration I’m testing now is for an underfloor heating manifold, i.e. the controller operates 6 on/off valves based on temperature measurements. MB reg 81 has information on the status of the relays in the following way (copied from the Modbus manual for the controller):
R1=bit0, R2=bit1…R6=bit7

Now I realised that there are only 6 relays but this register 81 has 8 bits so what are these additional 2 bits for.

I created a poller Thing for polling reg81 (length 1) and MB data Thing with read type unint8. In this data Thing I tried Read Address 81.1 and this Thing was online. With other addresses, e.g. 81.2 the This was offline. I created a number Item and linked it to the data Thing. This number Item had a value of 0 even though relay 1 was on so bit0 should be 1. MB Master also showed 1. If relay 2 is also on, MB master shows 3 but my number item still is 0. So, it is obvious that my number Item doesn’t pick up right value. This relay status is also interesting information because then I would know which relays are ON so then I would know in which room heating is ON.

Edit: Forgot to mention that the controller is an independent thermostat with setpoints so OH is not controlling the relays.

When you are ready, show us your Things and channels code for the problematic relays. We cannot see over your shoulder, your descriptions will not reveal typos or or incorrect assumptions.

I will do this tomorrow. I’m still replicating your logic to my 2nd configuration. I have to say your logic works really nicely. Your help has been paramountal.

Edit: managed to find few Moxa Modbus tcp gateways in Ebay.

Hi, I managed to solve this problem. I thought that I should have uint8 for the Read Value Type because I thought that reg81 has 8bits (R1=bit0, R2=bit1…R6=bit7) but when I changed the Read Value Type to uint16 then I’m getting right value for the relay status and it changes if I open/close relays. I need to do some maths in order to see which relays are open and which ones closed. I guess I could do this in the script for reading reg81 but let’s see. I still have lots of other things to be done with OH. I haven’t started to create my own pages yet.

Somewhat confusing situation but I have made huge progress during the last few days, thanks to you.

No you don’t, The data Thing id quite capable of selecting any one bit from a register using nn.n notation, and linking to an Switch type Item.

Example in documentation -
“Extract individual bits of the 16-bit register”

I tried this. Code for MB data reading Thing:

UID: modbus:data:7abbafdf5b:b07571baea
label: Autotalli rele luku
thingTypeUID: modbus:data
configuration:
  readValueType: uint16
  readTransform: default
  writeTransform: default
  readStart: "81.1"
  updateUnchangedValuesEveryMillis: 1000
  writeMultipleEvenWithSingleRegisterOrCoil: false
  writeMaxTries: 3
bridgeUID: modbus:poller:7abbafdf5b

Code for MB poller Thing:

UID: modbus:poller:7abbafdf5b
label: Autotalli rele poll
thingTypeUID: modbus:poller
configuration:
  length: 1
  start: 81
  refresh: 1000
  maxTries: 3
  cacheMillis: 50
  type: holding
bridgeUID: modbus:tcp:292b702683
location: Autotalli

I get error:
CONFIGURATION_ERROR
readStart=X.Y notation is not allowed to be used with value types larger than 16bit! Use readStart=X instead.

I though that this X.Y notation works but obviously I’m missing something.

Remember, all Modbus registers are 16-bit. We don’t need to tell the data Thing that.
So what is readValueType about? It’s telling the data Thing how we want to deal with data, how we want to interpret it. Signed,unsigned,float,32-bit,1-bit

The above config is nonsense because we ask for 16-bits interpretation using a one-bit target address. That’s what it is telling you.

So you want a binary bit, just say so

  readValueType: bit
  readStart: "81.1"

Really look at examples in docs

That did the trick, although I had to use “81.0” for relay 1 (and not “81.1”). I usually try to read the documentation but in many cases I just don’t understand the written text.

Now when I have lots of these “dummy” Items are there any possibilities to hide them in the built-in pages, e.g. attached screen copy from Miscellaneous page shows some data Things used for MB communication (circled with red line).

These Items will fill up my pages as there will many more new data Things added. Once I start making my own pages I guess I can put into the widgets only those Things which are relevant.

I think I now have all the building blocks for my controllers.

That’s the process. MainUI is dual-purpose, in its “admin” role it is supposed to show you everything. Only in the “user facing” part do you get to prettify and hide machinery.

I thought that I now know how to poll my MB devices but it seems that I don’t. I’m right now trying to read some registers from a controller (Ouman EH203) that is connected using Moxa NPORT gateway, i.e. MB RTU. MB Master can read the registers without any problems.

Code for the MB slave:

UID: modbus:serial:4dd68d96c6
label: Ouman KL MB slave
thingTypeUID: modbus:serial
configuration:
  baud: 38400
  connectMaxTries: 1
  timeBetweenTransactionsMillis: 35
  stopBits: "1.0"
  parity: none
  receiveTimeoutMillis: 1500
  dataBits: 8
  echo: false
  encoding: rtu
  flowControlIn: none
  flowControlOut: none
  port: COM19
  connectTimeoutMillis: 10000
  id: 1
  enableDiscovery: false

Poller:

UID: modbus:poller:4dd68d96c6:5ac7e8ac58
label: Ouman KL 0-4 luku
thingTypeUID: modbus:poller
configuration:
  length: 10
  start: 0
  refresh: 5000
  maxTries: 3
  cacheMillis: 50
  type: holding
bridgeUID: modbus:serial:4dd68d96c6

This polls regs 0-4. MB data Thing:

UID: modbus:data:4dd68d96c6:3028ea06f8
label: KL menovesi luku
thingTypeUID: modbus:data
configuration:
  readValueType: int16
  readTransform: default
  writeTransform: default
  readStart: "0"
  updateUnchangedValuesEveryMillis: 1000
  writeMultipleEvenWithSingleRegisterOrCoil: false
  writeMaxTries: 3
bridgeUID: modbus:serial:4dd68d96c6

This is supposed to read reg 0 which should give year but on the UI page I get following error message:
Status:

OFFLINE

**CONFIGURATION_ERROR**

Thing modbus:data:4dd68d96c6:3028ea06f8 readStart=0, and readValueType=int16 were specified even though the data thing is child of endpoint (that is, write-only)!

Events.log has same error message.

It seems that I don’t understand anything about Modbus. Any ideas?

The binding has a rarely used feature that a write-only data Thing is allowed to be a ‘child’ of a serial or TCP Thing. But it must be write-only, because there is no way to read poll that data Thing - there’s no poller Thing involved.

This data Thing is not linked to your poller (ID 5ac7e8ac58) and does have read parameters - hence the message.

You’ve just linked it wrong.

Sanity might be preserved by giving your Things more meaningful UIDs, although you have to remember to do that at the time you create them.
e.g.
UID: modbus:serial:com19slave01 instead of modbus:serial:4dd68d96c6
UID: modbus:poller:com19slave01:slv19hold00 etc.

Is that not a TCP gateway?

This is what I was also wondering. This can’t be true because I can poll the controller with MB Master, see attached screen copy:

Regs0-3 contain date and time information, e.g. 1MSB is month and 1LSB day.

Moxa Nport is a MB RTU gateway, it doesn’t work as MB TCP. I have to say this is really confusing. I have one Moxa MGate 3180 which is MB TCP.

Getting tired now after spending more or less whole day in setting up different configurations under OH so I may have made mistakes with this MB RTU controller.

What you can and cannot do with a third party utility doesn’t reall tell us much about configuration errors in openHAB?

Here’s the deal -you created a data Thing that is a child of a serial Bridge.
You cannot read any registers when you do that.
If you want to read, you must create your data Thing as a child of a poller .

aha, so 263 = 256 + 7 = month 1 day 7
The binding will let you pick out the bytes in different data Things so you can feed into separate Number Items.
But if you are going to decode in a rule and assemble into a proper datetime you might not want to do that.

Thanks a lot again.

Yeah, I know that with MB Master you can’t check any configuration errors in OH. I just wanted to check that I communication works.

I spotted finally the error which was rather obvious but I must have been rather tired when setting up the polling and reading. Now everything works.

I used the date/time registers only for testing purposes so I don’t need them in my OH setup.

Setting up the MB communication to my controllers really takes lot of time because you have to define every data Thing separately and test that everything works.

EDIT:

The binding will let you pick out the bytes in different data Things so you can feed into separate Number Items.

It seems that I have to use this method because some registers have 2 bits.

Hi Jari,

Out of curiosity, what modbus device are you using? I picked the text ‘Ouman’ from one of your first posts so that gives a direction…

Hi Miika,

I have several Ouman EH686 controllers (8pcs) and one EH203. EH203 is controlling the district heating system. EH686 boxes are controlling the underfloor heating valves, two ventilators, reading pulse data from electricity and energy meter. In addition to this I have two Mitsubishi heat pumps with Procon A1M modbus interface. So, rather complex system. I have been rather happy with these controllers.

It has really been a big job to integrate all these boxes to OH. @rossko57 has been extremely helpful. I’m nearly finished now so next step is to make the UI.

1 Like

I have now somewhat more complex scenario as I need to write first to reg130 and a different number to reg 132. After this another number to reg130 but same number to reg132.

I tried to setup a timer using code:

var IV1_RH1_2 = (IV1_RH1.state as Number) * 100
var Timer myTimer = null
IV1_Reg130.sendCommand(5)
IV1_Reg132.sendCommand(IV1_RH1_2)

myTimer = createTimer(now.plusSeconds(1), [ |
      IV1_Reg130.sendCommand(7)
      IV1_Reg132.sendCommand(IV1_RH1_2)
            ])     

This script is not working at all. I checked with MB Master software the regs and they weren’t updated at all.

I have found command Thread::sleep(1000) on this board but I read from somewhere that this is not recommended to use. However, I tried with following script:

var IV1_RH1_2 = (IV1_RH1.state as Number) * 100
IV1_Reg130.sendCommand(5)
IV1_Reg132.sendCommand(IV1_RH1_2)

Thread::sleep(1000)
  IV1_Reg130.sendCommand(7)
  IV1_Reg132.sendCommand(IV1_RH1_2)

I checked the regs and they were updated correctly so this seems to be working.

I have been using the scenario above quite successfully but today I noticed one glitch with one of my controllers. We discussed about this controller in this topic. I’m using this controller to switch on/off outdoor lighting with two relays. Both relays have a rule:

OHJ_Reg130.sendCommand(9)
Thread::sleep(400)
if (receivedCommand ==ON) {
      OHJ_Reg132.sendCommand(100)
   } else {
      OHJ_Reg132.sendCommand(0)
          }

Only difference between the rules is the value in the first command, either 9 or 13. I have now noticed that if I keep toggling on/off both relays at some point OH seems to get stuck because the Modbus registers are not updated any more for some reason. I can see this with Modbus Master program. I am using same data Things and number Items for each relay so I wonder whether this could be the reason, i.e. I wonder whether I should have separate data Things and number Items for each relay.

As your rule is set up now, it takes about half a second to complete one task i.e. command OHJ_Reg130 then a short while later command OHJ_Reg132.

There is nothing to stop another rule trigger coming along while that is in progress, so what happens then?
Only one instance of an OH3 rule can execute at a time, further triggers are queued up.

So, if we toggle the same relay quickly, you might get

  • command OHJ_Reg130
  • pause 400mS
  • command OHJ_Reg132
  • no pause at all
  • command OHJ_Reg130
  • pause 400mS
  • command OHJ_Reg132

A problem for your device? I’ve no idea.

But if you have two rules, there is no queuing. If you toggle two relays X and Y quickly enough, things like this can happen -

  • command OHJ_Reg130 with X
  • pausing 100mS (of 400), but trigger Y part way through
  • command OHJ_Reg130 with Y by second rule
  • pause 300mS (of 400)
  • command OHJ_Reg132 for X
  • pause 100mS (second rule catches up)
  • command OHJ_Reg132 for Y

which I expect will mess up badly.

I think the least you can do is have just one rule for all shared use of each Reg130.
Along the lines of -
rule triggered
decide what to send to 130 based on what triggered it
pause
send to 132 based on what triggered it
now pause a little more before exit, so that the next 130 cannot bang straight in.

Many thanks for your reply. This hasn’t been a problem. I have tried to switch on/off one relay very quickly and it works perfectly. I think the situation for two relays is exactly what you described. It seems that it’s the OH which gets jammed. Once it’s jammed the values of MB reg 130 and 132 won’t change. I need to restart OH only, not my controller, which is good thing.

Basically I understand how I would need to change my rule but I don’t know yet how to do that in practise. I guess I could add another Trigger under “WHEN” but Idon’t know yet how to choose between 9 or 13 in the first line of the script. I will do some more testing this evening.