Toggling GPIO's correctly in demo.items

Hello all,

I am trying to control a 16:1 multiplexer and I am using the GPIO binding for the Openhabianpi. The thing is that I know how to toggle the gpio pins on and off and I am currently able to select a single input which I have given. But as soon as I want to select another input channel, then it doesn’t work.

Lets start with the code, it is in demo.items.

Group:Switch:OR(ON,OFF) ch0 “Channel0”

Switch select0 “SELECT0” (ch0) { gpio= “pin:19 activelow:yes initialValue:low” }

Switch select1 “SELECT1” (ch0) { gpio= “pin:5 activelow:yes initialValue:low” }

Switch select2 “SELECT2” (ch0) { gpio= “pin:6 activelow:yes initialValue:low” }

Switch select3 “SELECT3” (ch0) { gpio= “pin:13 activelow:yes initialValue:low” }

Switch enable “Enable” (ch0) { gpio= “pin:18 activelow:yes initialValue:low” }

Group:Switch:OR(ON,OFF) ch1 “Channel1”

Switch select4 “SELECT4” (ch1) { gpio= “pin:19 activelow:yes initialValue:high” }

Switch select5 “SELECT5” (ch1) { gpio= “pin:5 activelow:yes initialValue:low” }

Switch select6 “SELECT6” (ch1) { gpio= “pin:6 activelow:yes initialValue:low” }

Switch select7 “SELECT7” (ch1) { gpio= “pin:13 activelow:yes initialValue:low” }

Switch enable1 “Enable1” (ch1) { gpio= “pin:18 activelow:yes initialValue:low” }

The gpio pins are controlling the 4 select pins. So in the UI if I toggle the channel 1, then the MUX is selecting my first input, however, as soon as I toggle the channel 2, the MUX doesn’t select the input at the second channel.

I am thinking that I will have to make some kind of rule or add a method in the demo.items. Can someone suggest a possible solution?

Thank you!

You can issue commands via multiple Items to the same channel, but that doesn’t mean it is a good plan.

Wouldn’t you want a Number Item you can set to 0-15, and when it changes it triggers a rule that commands four pins to the appropriate pattern?

I don’t know, I think using Groups for this has a certain elegance to it.

First of all, what I would do is only create one Switch Item for the GPIO pins. There is no reason to define select4 through select7 or enable1. For one thing, you have contradictory configurations on those Items. select0 is setting the initial value of pin 19 to low but select4 is setting the initial value of pin 19 to high. Which is it? Do you want the pin to be high or low when OH first starts/loads the .items file? You can’t have it both ways.

So to avoid this sort of contradictory config, just define one item for each of the pins.

Wait, I think I now understand what you are trying to do. When you select ch1, you want pin 19 to go high and the rest to go low.

Yes, I think rossko57 is right, you need a Rule for this. Groups will not work. A Group can only set all it’s members to ON or all it’s members to OFF. With the GPIO binding, ON means high and OFF means low. You can set some to high and sum to low like this.

OK, let’s see if we can be clever. I’m assuming you have 5! (120) different combinations. Yikes. We don’t want to have to manually define each and every combination by hand.

Let’s see if we can do some binary magic so that we can just use a number like rossko57 suggests but without needing to have some sort of mapping or switch statement where we manually define each of the 120 possible combinations.

In most programming languages I’d immediately jump on using a short, XOR and the binary shift operator. But Xtend doesn’t have an xor operator. Each bit of the short would represent one of the pins and we would do some binary manipulation to translate the the second bit to pin 19 high and all the rest low.

This is going to be really ugly. If you want to go down this path, I highly recommend implementing it in Jython instead of Rules DSL Rules. Python will give you the operators you need. It can be done in Rules DSL as one can implement XOR with only bitwise OR and AND operators, but it’s going to be a pain, probably more of a pain than just manually encoding them all by hand.

Since you have to create a Switch for each combination anyway, what if you encode the on/off states of the switches in the Item name?

Group Channels

Switch Select0_00000 "Channel0" (Channels)
Switch Select1_10000 "Channel0" (Channels)
...

Switch GPIO19 { gpio= “pin:19 activelow:yes initialValue:low” }
Switch GPIO5  { gpio= “pin:5  activelow:yes initialValue:low” }
...

Then your Rule can be:

rule "Channel triggered"
when
    Member of Channels received command ON
then
    val gpioMap = triggeringItem.name.split("_")
    
    GPIO19.sendCommand(if(gpioMap.charAt(0) == '1') ON else OFF)
    GPIO5.sendCommand(if(gpioMap.charAt(1) == '1') ON else OFF)
    GPIO6.sendCommand(if(gpioMap.charAt(2) == '1') ON else OFF)
    GPIO13.sendCommand(if(gpioMap.charAt(3) == '1') ON else OFF)
    GPIO18.sendCommand(if(gpioMap.charAt(4) == '1') ON else OFF)
end
1 Like

If it’s a 16:1 mux, there should be only 4 address pins. The fifth pin mentioned is a mystery, maybe it’s a strobe/enable and should always be set on albeit slightly delayed after setting up addressing. Easily done in a rule.
Perhaps it also needs setting off again, after a while or before changing address, again easily done.

Hello again,

Thank you everybody for taking out time and giving me ideas. So I have found the solution and it works :smile:

I had thought that it would have been cool if I used the groups because that is really very elegant but I don’t think I can and also,

This was very wrong. I just cannot configure the same pins again and again.

So what I did is to simply, make items for my GPIO’s in the items file and then make a rule for each channel for turning it on and off.

rule "channel0_ON"

when 

Item chan0 changed to ON 

then 

select0.sendCommand(ON)
select1.sendCommand(ON)
select2.sendCommand(ON)
select3.sendCommand(ON)
enable.sendCommand(ON)

end

rule "channel0_OFF"

when 

Item chan0 changed to OFF

then 
enable.sendCommand(OFF)
end

I know this is not an elegant solution but it still works and seems pretty simple. So for the 16 input channels, I will have to create such rules. Any alternate solutions or any elegant modifications to the code are welcome.

Thank you so much! :slight_smile:

Oh, just an afterthought, right now, I can turn on as many channels as I want. But I would like to make a logic which will allow me to trigger only one channel at a single time. Just like, right now I have 2 switches on my UI, for channel 0 and 1. So if I trigger on channel0 then channel1 should turn off. What can be an approach to do this?

Thank you for all the help I am getting. This community rocks!

???

I presented an approach above where you encode the on/off states of the gpio pins in the name of your Channel Item. That means you only need one Rule to handle all 16 cases.

For example, chan0 would become chan0_11111 and you can use the Rule above.

Presumably you would want OFF to set enable to OFF in all cases so

rule "OFF received on a channel"
when
    Member of Channels received command OFF
then
    enable.sendCommand(OFF)
end

If you have one Rule it’s easy to do what ever you need to do before you activate the pins for the new channel.

For example, using the Rule I posted above, just add to the top:

Channels.members.filter[ c | c.state == ON ].forEach[ c | c.postUpdate(OFF) ] 
triggeringItem.postUpdate(ON) // set the triggeringItem back to ON

Note the very deliberate use of received command in the triggers instead of changed. Also not the deliberate use of postUpdate in the two lines above.