[SOLVED] MCP23017 - Contact (Input) and Switch (Output)

Good evening,

I installed wiringPi mentioned in the docs. I will check the debugging mode in the next days. Thanks for the Tip!

I posted the error I had with the binding 2.5 here. I did not find any solution but would be happy, if you have a hint.

Best regards
BrainPain

Hello everybody,

I now tried to use “org.openhab.binding.mcp23017-2.5.3-SNAPSHOT.jar”. The good thing is that I do not have the same problem like I had with the version installed via Paper UI. The bad thing is, that I have the same problem like written above:

  • Inputs worked perfectly
  • Outputs don’t work

Now I set debugging on the binding like rossko57 said and get the following feedback when switching it on via Basic UI:

2020-03-16 11:22:56.837 [DEBUG] [017.internal.handler.Mcp23017Handler] - Received command: ON on channelGroup output on channel A0

2020-03-16 11:22:56.838 [DEBUG] [017.internal.handler.Mcp23017Handler] - Defined channel in group: output. Valid: true

==> /var/log/openhab2/events.log <==

2020-03-16 11:22:56.842 [ome.event.ItemCommandEvent] - Item 'living_room_led_switch' received command ON

==> /var/log/openhab2/openhab.log <==

2020-03-16 11:22:56.842 [DEBUG] [017.internal.handler.Mcp23017Handler] - Is channel A0 in supported channels: true

2020-03-16 11:22:56.847 [DEBUG] [ernal.handler.Mcp23017PinStateHolder] - Getting output pin for channel mcp23017:mcp23017:output1:output#A0

2020-03-16 11:22:56.850 [DEBUG] [017.internal.handler.Mcp23017Handler] - got output pin "A0" <GPIO A0> for channel mcp23017:mcp23017:output1:output#A0 and command ON [active_low=false, new_state=HIGH]

2020-03-16 11:22:56.867 [DEBUG] [017.internal.handler.Mcp23017Handler] - Received command: ON on channelGroup output on channel A0

2020-03-16 11:22:56.869 [DEBUG] [017.internal.handler.Mcp23017Handler] - Defined channel in group: output. Valid: true

2020-03-16 11:22:56.872 [DEBUG] [017.internal.handler.Mcp23017Handler] - Is channel A0 in supported channels: true

2020-03-16 11:22:56.874 [DEBUG] [ernal.handler.Mcp23017PinStateHolder] - Getting output pin for channel mcp23017:mcp23017:input1:output#A0

2020-03-16 11:22:56.879 [DEBUG] [017.internal.handler.Mcp23017Handler] - got output pin "A0" <GPIO A0> for channel mcp23017:mcp23017:input1:output#A0 and command ON [active_low=false, new_state=HIGH]

==> /var/log/openhab2/events.log <==

2020-03-16 11:22:56.884 [nt.ItemStatePredictedEvent] - living_room_led_switch predicted to become ON

And when I switch it off:

2020-03-16 11:27:32.300 [ome.event.ItemCommandEvent] - Item 'living_room_led_switch' received command OFF

==> /var/log/openhab2/openhab.log <==

2020-03-16 11:27:32.312 [DEBUG] [017.internal.handler.Mcp23017Handler] - Received command: OFF on channelGroup output on channel A0

2020-03-16 11:27:32.319 [DEBUG] [017.internal.handler.Mcp23017Handler] - Received command: OFF on channelGroup output on channel A0

2020-03-16 11:27:32.322 [DEBUG] [017.internal.handler.Mcp23017Handler] - Defined channel in group: output. Valid: true

==> /var/log/openhab2/events.log <==

2020-03-16 11:27:32.321 [nt.ItemStatePredictedEvent] - living_room_led_switch predicted to become OFF

==> /var/log/openhab2/openhab.log <==

2020-03-16 11:27:32.324 [DEBUG] [017.internal.handler.Mcp23017Handler] - Is channel A0 in supported channels: true

2020-03-16 11:27:32.327 [DEBUG] [ernal.handler.Mcp23017PinStateHolder] - Getting output pin for channel mcp23017:mcp23017:input1:output#A0

2020-03-16 11:27:32.330 [DEBUG] [017.internal.handler.Mcp23017Handler] - got output pin "A0" <GPIO A0> for channel mcp23017:mcp23017:input1:output#A0 and command OFF [active_low=false, new_state=LOW]

2020-03-16 11:27:32.320 [DEBUG] [017.internal.handler.Mcp23017Handler] - Defined channel in group: output. Valid: true

2020-03-16 11:27:32.340 [DEBUG] [017.internal.handler.Mcp23017Handler] - Is channel A0 in supported channels: true

2020-03-16 11:27:32.342 [DEBUG] [ernal.handler.Mcp23017PinStateHolder] - Getting output pin for channel mcp23017:mcp23017:output1:output#A0

2020-03-16 11:27:32.343 [DEBUG] [017.internal.handler.Mcp23017Handler] - got output pin "A0" <GPIO A0> for channel mcp23017:mcp23017:output1:output#A0 and command OFF [active_low=false, new_state=LOW]

==> /var/log/openhab2/events.log <==

2020-03-16 11:27:32.345 [vent.ItemStateChangedEvent] - living_room_led_switch changed from ON to OFF

I am a very beginner running out of ideas how to fix it and looking forward for you help!

Best regards
BrainPain

Have you some other utility running, that has reserved this pin or set it into read mode? You would expect a complaint about permissions or such if you had, though.

Thanks for the fast reply. No, this is the only binding I installed and I have no other programms etc. installed.

You’re supposed to have this wiring-Pi thing installed.

Have tried it’s command line gpio tool?

Yes, I tested if I can use it with the following command:

man gpio

I received a feedback. Do you need a specific output?

Does it work, can you control the pin with gpio that you cannot control from openAB?
I don’t need any output, I’ve no idea what to expect or how this binding works.

Do you know how to use gpio command tool and how to command a mcp23017-pin? I will try to do so this evening or tomorrow.

No idea

http://wiringpi.com/the-gpio-utility/

Another thought - confident you are looking at the correct pin? Your [default_state=“HIGH”] experiment should have confirmed that.

You are the best! I have checked the wireing a thousand times but you let me have a look at it again. I connected A7 instead of A0. Now it workes and I just have loop which is a problem of the rule. This should be a problem which I can solve by myself.

Sorry for bothering you the last days with such a stupid mistake. I will write a summary this evening.

Thanks again an best regards
BrainPain

How did that default high/low appear to work, then? You configured more pins than you showed us, or all outputs adopt the same, or?

I use two MCP23017 and created the following thing:

Thing mcp23017:mcp23017:input1 "MCP23017 Input 1" [address=20,bus=1] {
    //input-Pins
    Type input_pin : input#A0
    Type input_pin : input#A1
    Type input_pin : input#A2
    Type input_pin : input#A3
    Type input_pin : input#A4
    Type input_pin : input#A5
    Type input_pin : input#A6
    Type input_pin : input#A7

    Type input_pin : input#B0
    Type input_pin : input#B1
    Type input_pin : input#B2
    Type input_pin : input#B3
    Type input_pin : input#B4
    Type input_pin : input#B5
    Type input_pin : input#B6
    Type input_pin : input#B7
}

Thing mcp23017:mcp23017:output1 "MCP23017 Output 1" [address=24,bus=1] {
    //output-Pins
    Type output_pin : output#A0 [default_state="HIGH"]
    Type output_pin : output#A1 [default_state="HIGH"]
    Type output_pin : output#A2 [default_state="HIGH"]
    Type output_pin : output#A3 [default_state="HIGH"]
    Type output_pin : output#A4 [default_state="HIGH"]
    Type output_pin : output#A5 [default_state="HIGH"]
    Type output_pin : output#A6 [default_state="HIGH"]
    Type output_pin : output#A7 [default_state="HIGH"]

    Type output_pin : output#B0 [default_state="HIGH"]
    Type output_pin : output#B1 [default_state="HIGH"]
    Type output_pin : output#B2 [default_state="HIGH"]
    Type output_pin : output#B3 [default_state="HIGH"]
    Type output_pin : output#B4 [default_state="HIGH"]
    Type output_pin : output#B5 [default_state="HIGH"]
    Type output_pin : output#B6 [default_state="HIGH"]
    Type output_pin : output#B7 [default_state="HIGH"]
}

But I just use B0 of the input-chip as an input and A0 of the output-chip as an output:

Switch
    living_room_led_switch
    "Living room LED switch"
    {channel="mcp23017:mcp23017:output1:output#A0"}

Contact
    living_room_led_contact
    "Living room LED contact"
    {channel="mcp23017:mcp23017:input1:input#B0"}

The Input-Pin is connected to a button which switches a relay. This ensures, that the switch works without openhab or anything else. The following rule should change the lable of the switch in Basic UI from on to off and from off to on every time the hardware switch is used.

rule "living_room_led contact"
when
    Item living_room_led_contact changed to CLOSED
then
    if (living_room_led_switch.state == OFF) {
        living_room_led_switch.sendCommand(ON)
    }
    else {
        living_room_led_switch.sendCommand(OFF)
    }
end

At this point a new problem is begins :frowning: The reason for it is, that everytime I push the button the rule said to the switch to send a command which is not needed as I just want to change the “picture” of the switch in Basic UI. On the other side, when I use the switch of Basic UI to turn the LED on, the contact switches it off again. I hope I was able to describe it well. My question is:

How can I isolate the contact from the switch? At the end nothing should happen to the conntact when the switch in Basic UI is used but on the other hand I would like to see a change when the button is used.

Thank you!!!
BrainPain

Maybe try this thread.

If I’ve understood you correctly, you’re using the input pin to tell openHAB the state of a pushbutton. Whether openHAB knows about it or not, the button switches a relay? A pulse (latching) relay?

If that’s the case you are not really interested in the button. You want to know the relay state.

Good evening,

thanks for the reply. Meanwhile I found a solution and I want to summarize what I did. But first of all I want to thank the community for the support!!

1. Set-up

We installed for everything which can be switched in our house relay from Eltako (eS12-200-Uc) which are placed in a central controll box. Every switch in our house is wired with 24V and when pressed they give a short 24V-signal to the relay which switches the 220V for light etc… This works without any Raspberry Pi or something else. (This is very important as I still want to have light in case the Raspberry Pi is down). The aim was to use the 24V-cycle with the Raspberry Pi. The following wirering scheme shows what I did in my Test-set-up (Instead of 220V I used 24V and a LED this is much saver!!!).
Please find the corrected version below.
What happens at wicht event?

a) button is pressed

  1. A signal is send to the relay which switches the relay and the light glows

  2. A signal switches the optocoupler which isolates the Raspberry Pi from the 24V and a 3.3V Signal can pass the optocoupler and give a signal to the input pin B0 (It is important to set a pull-down resistor to this pin to prevent floating currents - thanks to the community for this hint!)

  3. The 3.3V signal is used by openhab to change the symbol on the sitemap

b) Switching the switch on sitemap

  1. A short 3.3V signal (100 milliseconds) is send from output pin A0 to the optocoupler

  2. The signal let the 24V pass which switches the relay and the light is on or off

  3. The switch shows the actual state of the light (on or off)

2. Installing the MCP23017-binding

This is the part which cost me a lot of energy. Unfortunately the version which can be installed via Paper UI leads to an error thus I put the “org.openhab.binding.mcp23017-2.5.3-SNAPSHOT.jar”-file into the addon-folder after uninstalling the binding in Paper UI. That’s it :slight_smile: Furthermore wiringPi and so on needs to be installed and the user “openhab” needs to be added to group “gpio” and “i2c”. (To be honest, I don’t know, if the last two steps are really necessary)

3. The code in openhab

I use two MCP23017 one only for inputs (address 20) and one only for outputs (address 24). I use this set-up, because in future I will use several MCP23017 and I wanted to check, if everything works. This is why I created two things:

Thing mcp23017:mcp23017:input1 "MCP23017 Input 1" [address=20,bus=1] {
    //input-Pins
    Type input_pin : input#A0
    Type input_pin : input#A1
    Type input_pin : input#A2
    Type input_pin : input#A3
    Type input_pin : input#A4
    Type input_pin : input#A5
    Type input_pin : input#A6
    Type input_pin : input#A7

    Type input_pin : input#B0
    Type input_pin : input#B1
    Type input_pin : input#B2
    Type input_pin : input#B3
    Type input_pin : input#B4
    Type input_pin : input#B5
    Type input_pin : input#B6
    Type input_pin : input#B7
}

Thing mcp23017:mcp23017:output1 "MCP23017 Output 1" [address=24,bus=1] {
    //output-Pins
    Type output_pin : output#A0 [default_state="HIGH"]
    Type output_pin : output#A1 [default_state="HIGH"]
    Type output_pin : output#A2 [default_state="HIGH"]
    Type output_pin : output#A3 [default_state="HIGH"]
    Type output_pin : output#A4 [default_state="HIGH"]
    Type output_pin : output#A5 [default_state="HIGH"]
    Type output_pin : output#A6 [default_state="HIGH"]
    Type output_pin : output#A7 [default_state="HIGH"]

    Type output_pin : output#B0 [default_state="HIGH"]
    Type output_pin : output#B1 [default_state="HIGH"]
    Type output_pin : output#B2 [default_state="HIGH"]
    Type output_pin : output#B3 [default_state="HIGH"]
    Type output_pin : output#B4 [default_state="HIGH"]
    Type output_pin : output#B5 [default_state="HIGH"]
    Type output_pin : output#B6 [default_state="HIGH"]
    Type output_pin : output#B7 [default_state="HIGH"]
}

The first one for inputs and the second for outputs. It is important to set default_state=”HIGH” After that the following items were created:

Switch
    living_room_led_switch
    "Living room LED switch"

Switch
    living_room_led_state
    "Living room LED switch contact"

Switch
    living_room_led_command
    "Living room LED command"
    {channel="mcp23017:mcp23017:output1:output#A0"}

Contact
    living_room_led_contact
    "Living room LED contact"
    {channel="mcp23017:mcp23017:input1:input#B0"}

But why three switches for on light? The reason is, that otherwise a click on “living_room_led_switch” would lead to a second triggering of the “living_room_led_switch” via contact, as the input gets an impulse, too. The task of the four items are the following:
living_room_led_switch: is shown on the sitemap and will trigger the rule “living_room_led switch” (see below) if used via Basic UI or whatever.
living_room_led_state: saves the state of the light (ON or OFF) and is used on the sitemap (e.g. visibility=[living_room_led_state==ON])
living_room_led_command: This switch is triggerd over a rule by the “living_room_led_switch” and is the only one which is connected to the thing (adress=24 => Output)
living_room_led_contact: This is the conntact wich is conected to the input (adress=20 => Input) and will trigger the second rule, if a button is pressed

Let’s have a look at the rules:

rule "living_room_led switch"
when
    Item living_room_led_switch received update
then
    living_room_led_command.sendCommand(ON)
    Thread::sleep(100)
    living_room_led_command.sendCommand(OFF)
end

rule "living_room_led contact"
when
    Item living_room_led_contact changed to CLOSED
then
    if (living_room_led_state.state == ON) {
        living_room_led_state.sendCommand(OFF)
    }   
    else
        living_room_led_state.sendCommand(ON)
end

The rule “living_room_led switch” reacts on a press of “living_room_led_switch” and set “living_room_led_command” to state “ON” for 100 milliseconds. This is because the Eltako is a latching relay which reacts on short impulses. The second rule reacts on an input and changes, depending on the state of “living_room_led_state”, the state of “living_room_led_state” which is important for the switch which is shown on the sitemap:

sitemap Test label="Test" {
    Frame label="Test" {
        //Shows the switch depending on its state
        Switch item=living_room_led_switch label="Licht ON" icon="switch-off" mappings=[ON="ON"] visibility=[living_room_led_state==OFF]
        Switch item=living_room_led_switch label="Licht OFF" icon="switch-on" mappings=[ON="OFF"] visibility=[living_room_led_state==ON]
    }
}

Both switches are the same with an different label and mapping via its parameter visibility. On is shown if "living_room_led_state is “ON” and one if it is “OFF”.

3. And now?
I have to create a circuit board, solder it and bring it to from “dev” to “prod”. After everything is done (which can take a while) I will open a new thread in which I explain everything in detail :slight_smile:

Once again thanks!

Best regards
BrainPain

Just for comparison, I’ll outline the rules I use with pulse relays.
I use modbus control, which means I can link my “monitor” input to a Switch type Item, and so I can get away with two Items per relay.

But the MCP23017 binding requires you to link inputs to a Contact type, not a Switch, so you do have to go with three Items as you have done.
There is careful use of command and postUpdate, and != ON rather than == OFF to avoid problems with NULL or UNDEF Items.

   // this one goes on sitemap, gets commanded by motion rules, etc.
Switch Light_Master "master" {autoupdate="false"}
   // this one is the simulated push button
Switch Light_Pulse "button" {channel="your:output:device"}
   // this one is the feedback from the device
Contact Light_Monitor "sensing" {channel="your:input:device"}
// this rule avoids the need for any button pulse timer
rule "monitor light"
when
   Item Light_Monitor changed
then
   if (Light_Pulse.state == ON) {
      // then it was an openHAB initiated switching
      Light_Pulse.sendCommand(OFF) // stop pressing simulated button
   } else {
      // then it was a manual external change
      trigger presence detection, cancel timers, etc. due manual activity
   }
   // now update the master 
   if (triggeringItem.state == CLOSED && Light_Master.state == ON) {
      Light_Master.postUpdate(OFF)
   } else if (triggeringItem.state == OPEN && Light_Master.state != ON) {
      Light_Master.postUpdate(ON)
   }
end

// this rule actions commands from UI or other rules
rule "do light command"
when
   Item Light_Master received command
then
   //only do it if state not already as commanded
   if (receivedCommand.toString != Light_Master.state.toString) {
      Light_Pulse.sendCommand(ON)  // simulate button press
   }
end

Suggested improvements -

It’s easy to apply the “Associated Items” Design Pattern here - that means just one set of rules can serve many sets of Items.

I actually put a failsafe expire on the pulse Item - if anything goes wrong, it turns off eventually
Switch Light_Pulse "button" {channel="your:output:device" , expire="1m,command=OFF}

Using this schematic diagram and selecting an adress other than 20 will shorten the 3.3v power supply from the PI; d’not know what the output will be;

The pull-down 1 resistor is no help; the way this diagram is designed, it will blow the collector-emittor junction of the optocoupler “input”

https://www.electronics-tutorials.ws/logic/pull-up-resistor.html

Hey rossko57, Hey Rik,

Thanks alot for your feedback.

At rossko57: I will have closer look at it later. I would Love to habe it easier.

At Rik:

What do you mean with shorten? I made the diagramm After I build and test the set-up. As the set-up workes with two mcp23017 I propably made a mistake with the schedul.

Thanks a lot!

Had a closer look at it. The schedul is completly wrong :neutral_face: I am sorry for it and will upload a new one during the next days.

Oké
Most of the elctronic I/O ports have these days internal weak pull-up resistors, they are only used for input biasing. So does the mcp23017; an exception are the address pins, which need to be externaly biased according following schematic:afbeelding
This means that switching is always referenced to ground. Using this technique gives a better noise immunity but…
More importent are the programming faults making an input involuntarily as an output and set the output to 0Volt; this will destroy the circuit internaly. :unamused: Direct switching from the PS can bring you in compromising situation. One can use the same technique to connect the optocoupler directly to the I/O pin with the emittor to ground.

Hello,
please find enclosed the corrected wirering scheme, as promised above. (I deleted the wrong one in my first post)
Testschaltung.pdf (19.9 KB)

Once again sorry for the wrong upload!

Best regards
BrainPain