Help with modbus binding and transformation

Tags: #<Tag:0x00007f2fc08743e8>

Hello,

I configure modbus TCP, and want to manage my bassein with openhab. I can read registers, but little bit struggle with writing, and transformation. i have this attached file from vendor, and want to see it and manage in openhab.
Maybe someone help me, how to convert unsigned int16 to bits, and read/write them?


…etc I can send .xls file for details. using openhab 2.5
Ed

I’ve written a guide on bitwise working with openHAB and Modbus.

Reading individual bits is straightforward. Start with something simple like a read only register.

Writing bits is complicated - that’s due to how Modbus works, not openHAB.
Using individual bits in registers is an odd design choice, given that Modbus provides a way to address individual bits anyway. But we have to work with what we’ve got.

I’m a bit worried about the talk of “pulse” in the chart you have shown us. Are these bits you have to turn on and then turn off again?

Hello,

yes, and for 3 seconds.

Ed

Okay, well if you are patient we can work something out. What can we try for simple experiments, “Light” perhaps?

First though, have a try at setting up Modbus poller and items/channels for that read-only status register (20?). Getting a “Pool Opened” Item working might be rewarding :smiley:

I would recommend using xxx.things files for this, because this will get complicated. And xxx.items files, because I expect we shall make use of the version 1.x expire binding.
Its fine to use PaperUI for anything else, but it is difficult to get an overview of many channels like we will need here.

Obviously bit masks are not really that odd a design choice given it’s the most efficient way to store a set of boolean values.

Would MODBus providing individual bit access not require additional programming of the MODBus layer to implement such a feature in the particular instance? It may have firmware overheads, complexity overheads, storage overheads etc. Also with the bits being stored in a 16 bit register they can be read together in one read, rather than individually reading 16 different boolean values.

That said, reading, updating and then writing a 16 bit register to update a single bit field opens you to race conditions and I don’t believe MODBus supports transactions or locking (could be wrong). This is something the OP needs to be aware of when updating these values that he is sure there will only be one single threaded device writing to these values or they could be corrupted in race conditions.

Having worked a little at the hardware level you will find that things are done VERY differently that you would expect looking at it from a high level software perspective. With something like MODBus being primarily a hardware interface layer/protocol it is not unexpected to find some of the hardware weirdness to leak though.

Hello,

I know, that modbus have bits, but in my case it’s int16. and I ask for help, can we do something about it.

pulse mean i need to write ‘1’, then return ‘0’.
pulse for 3 seconds, i need to write ‘1’ keep it for 3 seconds, and then return ‘0’ back

Ed

Modbus protocol natively supports reading and writing of single bits as “coil” and “discrete” 1-bit registers. It was specifically designed in the 1970s to support general binary actions like “heater on” without fuss.
But as I said, it’s a designer decision and we must work with what we got.

hello,

any help, how i can transform from int16 to boolean, and read/write?

Ed

Consider:
ENABLE_FILTRATION 1
MANUAL_FILTER_BACKWASH 2
COMMAND_OPENPOOL 4
COMMAND_CLOSEPOOL 8

FIELD_03_06 = modbus.read( address )
FIELD_03_06 |= ENABLE_FILTRATION
modbus.write( address, FIELD_03_06 )

This sets the ENABLE_FILTRATION to 1.

The key is to “OR” the 16 bit int with another 16 bit int with only the correct bit set to 1. Bits being 1, 2, 4, 8, 16, 32 etc.

EDIT: To determine if a bit IS set of not, then you AND the 16 bit with another 16 bit which has that bit (and only that bit) set to 1. eg:

10011
AND
10000
Will give you
10000

So in the form of pysedo code above:
FIELD_03_06 = modbus.read( address )
IF FIELD_03_06 &= COMMAND_OPENPOOL == COMMAND_OPENPOOL
then
COMMAND_OPEN_POOL is active

As to how to do that in OH I’ll defer to others.

Did you see this? It is a linked thread, if you click on it there is more detail.

I am prepared to help you with this, but I’m not going to write it all for you.
Please have a try at reading that status register into openHAB Items, and let us know how you get on. We will help. This is complicated, but if we go step by step there is a path to make it work.

Agreed.

My point was more about how things differ at the hardware level. Put simple, while you may often find an IC that provides you ModBUS interface layer and you just write stuff to it and flash a definition of your registers to it, these things vary a lot. ( I have not used an MODBus interface IC specifically).

A high level software person would, usually, just install “lib_modbus” and be done with it, but if you design has a Microcontroller with only 4K of RAM that is probably not an option. So “fudges” or partial implementations of interface layers are very common.

Hello,

i know, how to manipulate with bits. for me is clear OR, AND, XOR… my question is from where to start.

i can read int16 into openhab2 variable. for example I read 16 address into variable, and see 1…
means for me in16=1, bit 0 is set to 1, means filtration is enabled.

but how to use transformation??? what i need to put into modbus data objects? i install transformation plugin, but not sure, how to use it.

how I can get my 16 boolean varibles from than int16??? and then how to write them back to modbus. I do not need full help, i just need to understand how to start

Ed

I think the bottom of Ross’s post covers this in the sections above and below:

hvac.rules

The bits are split out for OH processing but the code provided in the rules combines them back into a single register for sending.

OK. let me be stuppid. where in interface i need to click.

to which folders i need to have files.

sorry… i just need to understand from where to start. i am using openhab2.5,

You can do this via PaperUI, if you wish.

I find PaperUI rather clumsy when you need to look at a lot of Items, channels, Things, at the same time.
PaperUI does not allow you to link Items to version 1.x bindings either. I think we will find the expire binding useful for making ‘pulses’, and that happens to still be version 1.x

So instead, we can set up Items and Things using text files.
Obviously, you will need some kind of text editor for that. Almost certainly you will also want (or already have) use a text editor to customise your sitemap for BasicUI? What are you using for that?

When you come to make rules (and we will need rules here), assuming you want to use the standard rules language (“DSL”), you will need some text editor for that as well.

Sitemaps live in a folder something like openhab2/conf/sitemaps. There are also 'sister" folders …/conf/items , …/conf//things , …/conf/rules which should be fairly self explanatory?

With all this text file editing going on, I would recommend using VSCode editor with the openHAB extension - it will do syntax checking etc.
I’m afraid that would be something else new to learn, but will probably save time in the long run over using a simple text editor.

I am using paperUI.
here are screenshoots, how I receive address 16.

I create a pool object from modbus ID#1


and then I use data object and get address 16

and then I link number to value.

so I can see value ‘1’ in control menu in paperUI…

what to do next? I see some transformation fields, which are set to default… how to use them. because temperature i need to divide by 10.

Ed

Please read and understand the post I linked to about using Modbus for bitwise.
It does not involve any transformations, you cannot force a transformation to do what you want.
It uses the Modbus binding’s bitwise addressing feature to “split out” bits from a register into separate channels that can be linked to separate Items.
Please ask about anything that is not clear.

Okay, a non-bitwise question :smiley:
This is explained in the binding docs, which you have obviously read to get this far, but there is a lot in there.


There is an example there for a divide by 10 transform.

You would need to use your text editor to create a file xxx.js in the /transform folder to contain the javascript, then add a readTransform= parameter to your data Thing, which points to the JS transform filename.

getting error:
Could not transform state ‘275 °C’ with function ‘JS(divide10.js)’ and format ‘%s’

You could help by showing us the complete error , showing us what you have done , like the setup of your Thing and the content of your JS file , and explaining what you are trying to do,
I know that the Modbus binding will not produce a value like ‘275 °C’ because it does not understand units at all, so i know there is something going on that you are not telling us about.

I understand there may be language difficulties here, but you are making it really difficult.

Hello,

I read temperature, and divide it by 10. but when I see variable in control it’s Rounded.
so I set temperature to 25.5, but I see it as 26.

this is how I see variables:

if I click set, then I see 25.5

Data: Current Temperature is read/olny, how to protect it from changin?

I want to see, as a temperature 25.5 °C

Where I need to setup a format? can’t find.

Ed