Lights Control Hardware (PLC)

Bear in mind I know nothing about GLC or VLAGs, but I don’t need to.
What do you want openHAB to do?
So far as I can see, you need to write individual bits in a holding register to control lighting devices.

More than one way to do that - but a crucial question is, do you need to read back the contents of that register?
If these bits represent push-on, push-off buttons, you might not care and will read the status of the lighting channels from somewhere else?
If these bits represent on-off switches, we have to more careful.

Hi,

the GLC configs are fine and run in this configuration stable.
My wish is like you said that openHab can work as a button by using the internal Vlag…

I think it is not necessary to read back Status of the Vlag and my Plan was to look at the Output of the boxes if Light is on or of.

My plan has been to buid in a switch which has an auto restet like the push buttons which were discribt in several thread´s:

push button once -> high bit is sent -> reset after 50msec. -> Light is swiched on

push button twice-> high bit is sent -> reset after 50msec. -> Light is swiched off

and Light Status can be read by the digital output 1.

My .thing config writes the high bit by switching on but it doesn´t write the low bit when i swich off

Sounds good to me.
openHAB does need to know current light state or you won’t be able to exercise proper control, when other people may be switching on/off.

A side benefit is that is possible to get openHAB to detect lighting changes that it did not ask for i.e. it can know when somebody is manually switching - presence detection.

Alright, so here we only need to make write-only single bit channels. That’s really easy compared to read/write.
IMPORTANT - This is based on a big assumption about your Adam setup. Writing bit X will clear/zero every other bit in the register, even if it was only set 10mS ago. If you are automating lighting from openHAB you may well send commands to several zones in quick succession. Will Adam care if they trample on each other?
If that’s a problem, we will have to go the more complicated way.

Bridge modbus:tcp:Wohnhaus01 [ host="192.168.0.152", port=502, id=1 ] {

    // no poller needed for write-only data Thing
    // many data Things write to same register
        // command anything to this to write "1" i.e. 00000000 00000001
    Thing data vlag01 [  writeStart="305", writeValueType="uint16", writeType="holding", writeTransform="1" ]
        // command anything to this to write "2" i.e. 00000000 00000010
    Thing data vlag02 [  writeStart="305", writeValueType="uint16", writeType="holding", writeTransform="2" ]
        // command anything to this to write "4" i.e. 00000000 00000100
    Thing data vlag03 [  writeStart="305", writeValueType="uint16", writeType="holding", writeTransform="4" ]
...
    Thing data vlag15 [  writeStart="305", writeValueType="uint16", writeType="holding", writeTransform="32768" ]

    // poller for any other stuff you want on this modbus slave
    Bridge poller thing [ ...

Do you need to reset these bits after a time,or is that automatic at the Adam? Is that 50mS programmed into the Adam,or done by openHAB? Would it matter if it were a couple of seconds instead?

Just for reference, why bitwise read/write is difficult -

From OH3.1 the binding will have a new profile making that easier.

Hi rossko57,

thank you so much for helping me!!!

rossko57
Sounds good to me.
openHAB does need to know current light state or you won’t be able to exercise proper control, when other people may be switching on/off.

Yes, i configured the adam´s that Di0 & Vlag0 swiching the Do0.
Do0 is the feedback that light is swiched on.

rossko57
IMPORTANT - This is based on a big assumption about your Adam setup. Writing bit X will clear/zero every other bit in the register, even if it was only set 10mS ago.

I think this won´t be a problem because all the Bit´s have to go back to 0 like a virtuel Button.
Okay if two Users swiching a Button at the same time the Light won´t turn on/off by one of them and the result is that the user use Button again and than it works

rossko57
If you are automating lighting from openHAB you may well send commands to several zones in quick succession. Will Adam care if they trample on each other?
If that’s a problem, we will have to go the more complicated way.

The Vlags do the same like the Di´s in the Adam boxes… If i push more than 1 Button at the same time the box swiches al buttons i´ve pushed.
I think if i have to build a szenario including Vlag0, Vlag1 and Vlag 4 i have to build a Button which send´s a 1011 par example?! In theorie that would work?

rossko57
Do you need to reset these bits after a time,or is that automatic at the Adam? Is that 50mS programmed into the Adam,or done by openHAB? Would it matter if it were a couple of seconds instead?

Unfortunately i´m not able to give a Vlag a setting with an auto switch of and it has to be done in openHab. In the GLC logic the adam box looking for the falling edge of the Vlag or the Di.
That means if i hold the Button no other falling edge can be detected at this time and the light can´t be swiched on or off till i release the button, the same handling by the Vlag.
That might be a problem ?!

Alright. We can construct an Item in openHAB to represent each lighting zone, that gets its state from the polled DoX, and when issued a command from UI or rule, goes through a little dance to simulate a pushbutton press then release to VlagY - but only if a change of state is needed. Do and Vlag need not be on same Adam box.
When doing this with pulse-relay controlled stuff, I’ve found the most reliable and flexible way to do this to have a second Item represent the pushbutton, and link them with a little rule.

From the viewpoint of openHAB user, it’s just another on/off light Item. (and the pushbutton Item is hidden from users)

That’s fine, we can manage “push button, wait, release” from openHAB.
OH has an ‘expire’ feature that would make this easy to implement - but it works in seconds.

Ah, so the actual switching action takes place upon button release, not button push?
Then we’ll have to use rules in openHAB to give a quick press-release, not a slow expire.
But -
That does mean we do not have to worry much about sending e.g 0010 and cutting short a 0001 that we just sent before. The simple way will work.

I would try to avoid programming this in at a low level.
If we can make all this so it reliably switches individual zones, even many in quick succession, this kind of group/scene is best done at the high level. That’s a lot easier to work with.

Before we go writing any config or rules … what version openHAB do you run?
The Modbus binding is right now getting new features that make writing to register bits easier. Info for @ssalonen who is creating this!

We can do it in OH 3.0 with rules as in that “bitwise” post that I linked to (and that would continue to work if you upgrade later), but if you can run a snapshot version OH with latest binding we could exploit new bit features that should formally arrive in OH3.1.

Hi,

we have a Synology-Nas with an virtual machine windows 10 on it and i´ve installed openHab 3.0 on it.
Yes i think it won´t be a problem to use a snapshot… I had just began to explore openhab and don´t have many bindings.

I will be home in about two ours and than i could install it

Okay, it took a little more time but now i´ve switched to openHab 3.1, i installed the service for auto start and added the modBus binding

Alright, let’s have a go. One step at a time -get the reading working first.

If I understand right, you need to read the DO register 40303 for light circuit states, and we’ll eventually want to write Vlag at 40305, but we’ll need to read too for binding bitwise operations.
The 40xxx is an odd Modbus convention that tells us its holding register type.
Looking at your screenshots of your QMod utility, the Adam names register 40305 at protocol address 304 (hex 0130) so we need to be aware of the “-1 address” issue.

I advise naming Things and channels relating to the Modbus slave device e.g. DO01 and leaving Items to have the meaningful names like CowshedLights.

So, based on your original things and assuming you want to use a xxx.things file (as I would myself)

   // ADAM device 1
Bridge modbus:tcp:wohnhaus01 [ host="192.168.0.152", port=502, id=1 ] {
    
         // poll regs DI,DO,GCL
    Bridge poller wh01 [ start=300, length=6, refresh=500, type="holding" ]
    {
            // read DO as bits
        Thing data do01 [  readStart="302.0", readValueType="uint16" ]
        Thing data do02 [  readStart="302.1", readValueType="uint16" ]
        ... etc
        Thing data do16 [  readStart="302.15", readValueType="uint16" ]

            // read Vlag as register, we will write bits using profiles
        Thing data vlags [  readStart="304", readValueType="uint16", writeStart="304", writeValueType="uint16", writeType="holding" ]
    } // end of poller
} // end of device

Will you be defining Items using files, or with the UI? UI probably advisable for OH3, but I will give example in old xxx.items file mode and you should be able to see how to create it in UI
Names of your choice.

   // Item representing a lighting zone
Switch Cowshed "Cowshed lights" {channel="modbus:data:wohnhaus01:wh01:do01:switch"}
   // each zone partnered with a simulated pushbutton
Switch Cowshed_pulse "Cowshed push" { channel="modbus:data:wohnhaus01:wh01:vlags:switch" [ profile="modbus:bit", bit-index="0" ], autoupdate="false", expire="1s,command=OFF" }
   // Item representing next lighting zone
Switch Yard "Yard lights" {channel="modbus:data:wohnhaus01:wh01:do02:switch"}
   // partner pushbutton
Switch Yard_pulse "Yard push" { channel="modbus:data:wohnhaus01:wh01:vlags:switch" [ profile="modbus:bit", bit-index="1" ], autoupdate="false", expire="1s,command=OFF" }
... etc

Note that all the pulse Items are linked to the same data Thing, but using the brand new bit profile feature to select write bit. I hope the binding version enabling this feature is in the OH snapshot!

The Item names are deliberately related in zone-pulse pairs, because we’ll make use of that in rules later.

I’ve suggested disabling autoupdate on the pulse Items, so that we manage the Item state separately from any commands in rules.
Autoupdate can stay by default on the light zone Items for a quickUI response.

The 1-second expire will “un-push” the simulated pushbutton when we begin to use it. I’m pretty confident this will work satisfactorily without the short mS pulse, but we can revise later if needed (without using expire)

Try all this, see if it configures error-free, and see if you can monitor the actual lights. (there shouldn’t be much to see in pulse yet).
We’ll add rules for control when confident that we can read.

Thank you so much rossko57!

I´ll try it later (i can´t reach openHab at work) and give you a detailed feedback :slight_smile :slight_smile:

Hi rossko57,

ok here the result of testing…

I´ve modified the xxx.thing to the register of the digital outputs

   // ADAM 6052 Wohnhaus01
Bridge modbus:tcp:wohnhaus01 [ host="192.168.0.152", port=502, id=1 ] {
    
         // poll reg Do
   Bridge poller Thing_Do [ start=0016, length=8, refresh=1000, type="coil" ] {
       //Flutlicht Innenhof
       Thing data Thing_Do00 [ readStart="0016", readValueType="bit", writeStart="0016", writeValueType="bit", writeType="coil"]
       //Flutlicht Pferde
       Thing data Thing_Do01 [ readStart="0017", readValueType="bit", writeStart="0017", writeValueType="bit", writeType="coil"]
       //Ambientebeleuchtung
       Thing data Thing_Do02 [ readStart="0018", readValueType="bit", writeStart="0018", writeValueType="bit", writeType="coil"]
       //Nicht in Gebrauch
       //Thing data Thing_Do03 [ readStart="0019", readValueType="bit", writeStart="0019", writeValueType="bit", writeType="coil"]
       //Nicht in Gebrauch
       //Thing data Thing_Do04 [ readStart="0020", readValueType="bit", writeStart="0020", writeValueType="bit", writeType="coil"]
       //Nicht in Gebrauch
       //Thing data Thing_Do05 [ readStart="0021", readValueType="bit", writeStart="0021", writeValueType="bit", writeType="coil"]
       //Nicht in Gebrauch
       //Thing data Thing_Do06 [ readStart="0022", readValueType="bit", writeStart="0022", writeValueType="bit", writeType="coil"]
       //Nicht in Gebrauch
       //Thing data Thing_Do07 [ readStart="0023", readValueType="bit", writeStart="0023", writeValueType="bit", writeType="coil"]
    } // end of poller Do

         // poll reg Vlag
   Bridge poller wh01 [ start=300, length=6, refresh=500, type="holding" ] {
       // read Vlag as register, we will write bits using profiles
       Thing data vlags [  readStart="304", readValueType="uint16", writeStart="304", writeValueType="uint16", writeType="holding" ]
    } // end of poller Vlag

} // end of device

I named the swiches in items by correct names in xxx.items:

   // Item representing a lighting zone
Switch FlutInnenh "Flutlicht Innenhof" {channel="modbus:data:wohnhaus01:Thing_Do:Thing_Do00:switch"}
   // each zone partnered with a simulated pushbutton
Switch FlutInnenh_pulse "FlutInnenh push" { channel="modbus:data:wohnhaus01:wh01:vlags:switch" [ profile="modbus:bit", bit-index="0" ], autoupdate="false", expire="1s,command=OFF" }
   // Item representing next lighting zone
Switch FlutPferd "Flutlicht Pferde" {channel="modbus:data:wohnhaus01:Thing_Do:Thing_Do01:switch"}
   // partner pushbutton
Switch FlutPferd_pulse "FlutPferd push" { channel="modbus:data:wohnhaus01:wh01:vlags:switch" [ profile="modbus:bit", bit-index="1" ], autoupdate="false", expire="1s,command=OFF" }
   // Item representing next lighting zone
Switch Ambiente "Ambiente Beleuchtung" {channel="modbus:data:wohnhaus01:Thing_Do:Thing_Do02:switch"}
   // partner pushbutton
Switch Ambiente_pulse "Ambiente push" { channel="modbus:data:wohnhaus01:wh01:vlags:switch" [ profile="modbus:bit", bit-index="2" ], autoupdate="false", expire="1s,command=OFF" }

After data migration i added a “value as a Number” item to check if the read poll of register 305 is working.

The result is:
normel switches are showing the live status of light on/off
the pulse switches just showing the value null
the value as a number shows the correct value in dezimal ( i used the polling tool to figure it out

Okay, that’s what we hoped for, good start. :smiley:

Upon discussing with Sami how the new bit-write mechanism in the binding works, I don’t think it’s going to work well here. It seems it is not going to work well where you might write 2 or 3 “at the same time” (very quickly consecutively really) as you might well do with lighting zones. The safer course is to manage our own register cache and bit-write via rules.

It’s a different approach, requires different settings,but the same Item light-pulse paired structure. I’ll have a think and come back on this.

EDIT -

Aha, I did not realise your DO outputs were available as coil-type registers. Doesn’t matter here, so long as you know what is going on. These are just “mirrors” of outputs on other devices, right? So we cannot use for control, only monitoring.

I assume that the Vlag bits we want to write are only available packed into a holding register, though?

Hi rossko57,

Yes that was pretty simple with your help :wink: but i if i had to to do that for my own i´m not able to.

Uhh that sounds strange and i hope you will continue to support me please.

That´s correct you can just see the status…
You can see in the picture that the Do0 from the adam box is just a part from the construction…
…in this case 3 x Do for the lights
AdamBox2Rule2

Yes, those Vlag´s are only available in the holding register… :frowning:

thank you very much rossko57 that you invest your time to helping me !!!

Alright, had a think and a play.

Change of method means change of infrastructure.

Revised Things

         // poll reg Do
   Bridge poller Thing_Do [ start=0016, length=8, refresh=500, type="coil" ] {
       //Flutlicht Innenhof
       Thing data Thing_Do00 [ readStart="0016", readValueType="bit"]
etc.

Mostly okay as it was, I think you can afford to poll more often.
but
Do change these DO to read-only, we want to ignore commands here.

         // poll reg Vlag
   Bridge poller wh01 [ start=300, length=6, refresh=0, type="holding" ] {
       // read/write Vlag as whole register, we will write bits from rule
       Thing data vlags [  writeStart="304", writeValueType="uint16", writeType="holding" ]
    } // end of poller Vlag

In contrast, we need not poll at all here - unless you want to look at any of the other holding registers.
Nothing else is changing vlag but us, so we need never read it back.
Change the data Thing to write-only.

Revised Items

We need to introduce Group Items, which allows us to easily use one rule to deal with a group of similar Items. All light zones in one group, all pulse-pushbuttons in another

We’re going to use one Item to keep an image of the 16-bit Vlag register. This gets updated by a rule as bits are written.

A big change in the naming pattern. The methods used here are the same as the “Modbus bitwise” posting linked to earlier. But the rule there is just a demo, not really suitable for expanding to 16 Items with the switch/case, and it would require hardcoding Item names into the rule.
We can avoid that by hardcoding the bit number used by this button into the name of the pulse-pushbutton Item. Much easier to add/amend Items.

   // modbus lighting items
Group gAdamLights "for light zones"
Group gVlags "for pulses"
Number VlagReg "for vlag register image" {channel="modbus:data:wohnhaus01:wh01:vlags:number"}

   // Item representing a lighting zone
Switch FlutInnenh "Flutlicht Innenhof" (gAdamLights) {channel="modbus:data:wohnhaus01:Thing_Do:Thing_Do00:switch", autoupdate="false"}
   // each zone partnered with a simulated pushbutton
Switch FlutInnenh_pulse_00 "FlutInnenh push" (gVlags) {autoupdate="false", expire="1s,command=OFF"}
Switch FlutPferd "Flutlicht Pferde" (gAdamLights) {channel="modbus:data:wohnhaus01:Thing_Do:Thing_Do01:switch", autoupdate="false"}
Switch FlutPferd_pulse_01 "FlutPferd push" (gVlags) {autoupdate="false", expire="1s,command=OFF"}
etc.

So, Light Items are linked to read-only modbus channels to monitor light states…
Note that autoupdate is disabled - we don’t want commands interfering with Item state, because our rule needs accurate state.
These are the Items to put on your UI with on/off switches, and to command from other rules like motion activated lighting.

Simulated pushbutton Items are not linked to anything, all managed by rule.
We don’t care about Item state here, it is all about commands. So we can disable autoupdate to reduce workload.
Expire is used to automatically “un-push” a button after 1 second. I think that will be fast enough for you (it’s as fast as expire goes). If it isn’t, we can change something else later.

Rules

Everything is done by two rules.
I’ve written in file-based DSL, it should be possible to convert to other languages and/or UI.

One rule manages the pushing of the buttons, writing bits to vlag register while preserving state of all other bits.

The other rule manages if and when to push a button at all, to toggle a light on or off.

import java.math.BigInteger // we need this for set/clearBit()

rule "simulate vlag pushbutton"
    // this rule pushes and releases buttons
when
    Member of gVlags received command
then
    var register = BigInteger.valueOf(0)  // we need BigInteger type to use setBit
    if ( VlagReg.state != NULL && VlagReg.state != UNDEF) { // avoid using invalid register image
        register = (VlagReg.state as DecimalType).toBigDecimal.toBigInteger // use existing image
    }
        // relies on Item name like FlutPferd_pulse_01
    val bitnum = Integer.parseInt(triggeringItem.name.split("_").get(2))  // get the 01 part
    if (receivedCommand == ON) {
        register = register.setBit(bitnum)
    } else if (receivedCommand == OFF) { // by testing both, we will ignore REFRESH commands etc.
        register = register.clearBit(bitnum)
    }
        // at last, write image to Modbus
    VlagReg.sendCommand(register)
end

rule "control pushbutton Items"
    // this rule converts on/off commands to buttons
when
    Member of gAdamLights received command
then
        // check if action needed first
    if ((receivedCommand ==ON && triggeringItem.state != ON) ||
        (receivedCommand == OFF && triggeringItem.state != OFF)) {
        val template = triggeringItem.name + "_pulse_"
            // find partner pushbutton in group, but we don't know suffix like _01
        val button = gVlags.members.findFirst[i | i.name.contains(template)]
        if (button === null) {
            logWarn("ERROR", "config missing " + template)
        } else {
            button.sendCommand(ON) // push the button for change
            // relying on expire to un-push later, but we could use timer here
        }
    } // else no change needed
end
1 Like

Hey rossko57,

this is amazing!!!

your config works perfect, oh thank you so much i never were able to do this for my own.

i have changed the length from 6 to 1

thank you so much

OOPS - just noticed an error. The image register Item VlagReg should not have autoupdate disabled. This error would not impact most usage,but I’ve amended the previous post.

Doesn’t matter much with zero polling :wink:

We can enhance this set up to detect when someone manually operates the lights i.e.lights change but openHAB didn’t request that.

I use this for presence detection, alongside PIRs, door openings etc. - “Someone is there at the wall switch”.
I also use it to modify automated lighting behaviour e.g.if someone chooses to manually turn the lights off, we don’t want to immediately turn them back on from a motion detection…

Any interest in detection? (What you do with it is up to you!)

Oh yes that sounds very intresting!
I have doorcontact´s at the most front doors so I would be able to switch the Outdoor Light automatically :slight_smile:

Alright, this is a mash together of the Adam code and something I use myself with pulse relays.

The problem is that a transient openHAB command causes a state change - with a delay. Monitoring a state change does not tell us who did it, unless we “remember” that OH recently sent a command.

In the Adam setup, the write-only simulated pushbutton Items are working just by commands. The Item state is unused, so we are going to hijack that to use as our “command rememberer”.

So a small change to all pushbutton Items -

Switch FlutInnenh_pulse_00 "FlutInnenh push" (gVlags) {autoupdate="false"}

Stopping using expire here at all. (In theory we could use it to cancel the remember with state=OFF, but that doesn’t work properly in OH2 with preceding command OFF. Maybe it would in OH3,but timers work)

The rule that handles light Items changes, timers added -
One to un-push the button.
A longer one to allow for a response from commanded light.

rule "control pushbutton Items"
    // this rule converts on/off commands to buttons
when
    Member of gAdamLights received command
then
        // check if action needed first
    if((receivedCommand ==ON && triggeringItem.state != ON) ||
        (receivedCommand == OFF && triggeringItem.state != OFF)) {
        val template = triggeringItem.name + "_pulse_"
            // find partner pushbutton in group, but we don't know suffix like _01
        val button = gVlags.members.findFirst[i | i.name.contains(template)]
        if (button === null) {
            logWarn("ERROR", "config missing " + template)
        } else {
            button.sendCommand(ON) // push the button for change
            button.postUpdate(ON) // remember command
                // set up to un-push after 300mS
            createTimer(now.plusNanos(300000)) [ |
                button.sendCommand(OFF) // un-push button
                   // leave state ON and spawn new timer
                createTimer(now.plusSeconds(2)) [ |
                    button.postUpdate(OFF) // forget the command
               ]
            ]
        }
    } // else no change needed
end

The button bits-to-register rule stays unchanged.

Add a new rule to detect light changes

rule "detect light switching"
when
    Member of gAdamLights changed from ON to OFF or
    Member of gAdamLights changed from OFF to ON
        // ignore NULL or UNDEF changes
then
    val template = triggeringItem.name + "_pulse_"
    val button = gVlags.members.findFirst[i | i.name.contains(template)]
    if (button.state != ON) {  // it was not openHAB
        // then it was a manual change
        // someone is stood at the wallswitch!
        logInfo("test", "Who is there?")
        // code whatever you want, like updating a presence Item
    }
end

Hi rossko57,

thank you again for those nice settings!

I added both of your rules to the rules folder and changed the xxx.items with the push switches…

Unfortunately i´m not able to switch the light´s by openHab anymore but the status of the lights is shown correctly when i use the hardware buttons…

Maybe i did a mistake and i will check all configs again!

There is a timing error, I got micros for nanos. (I tested in OH2 where this is different)

Fixed for 300mS -

                // set up to un-push after 300mS
          createTimer(now.plusNanos(300000000)) [ |
                button.sendCommand(OFF) // un-push button

Okay, i have changed it to 300000000 nanoseconds but it still doesn´t work.

I noticed that you have done an import in the first rule that you created…

Do i need that again in my “new” first rule, maybe?