Caching issue with relay component?

47 views
Skip to first unread message

GeertVc

unread,
Apr 12, 2015, 11:28:53 AM4/12/15
to pi...@googlegroups.com
Hi,

I want to connect a button push, which has a built-in LED, to a relay activation as follows:

  • When the button is pushed, the relay is switched on: the LED must start blinking with a time interval of 500ms
  • When the button is pushed again, the relays is switched off: the LED must stop blinking

To accomplish this, I have the following code (I'm using an MCP23017 to do the job):

        private static final GpioController gpio = GpioFactory.getInstance();

        final MCP23017GpioProvider mcp23017GpioProvider = new MCP23017GpioProvider(I2CBus.BUS_1, 0x20);
       
        Button switch_01_BtnA = new GpioButtonComponent(
              gpio.provisionDigitalInputPin(mcp23017GpioProvider, MCP23017Pin.GPIO_B0
                  , "MyInput-B0", PinPullResistance.OFF
              )
            , PinState.HIGH
            , PinState.LOW
        );

        Relay relay_V01 = new GpioRelayComponent(
              gpio.provisionDigitalOutputPin(mcp23017GpioProvider, MCP23017Pin.GPIO_B1
                  , "MyOutput-B1", PinState.LOW
              )
        );

        LED switch_01_Led1 = new GpioLEDComponent(
              gpio.provisionDigitalOutputPin(mcp23017GpioProvider, MCP23017Pin.GPIO_A7
                  , "MyOutput-A7", PinState.LOW
              )
        );

        // create switch listener
        switch_01_BtnA.addListener(new ButtonPressedListener() {
            public void onButtonPressed(ButtonEvent event) {
                // display console message
                AnsiConsole.out().println(Ansi.ansi()
                    .fgBright(Ansi.Color.CYAN)
                    .a("Switch_01_BtnA pressed").reset()
                );

                relay_V01.toggle();
               
                if (relay_V01.getState() == RelayState.OPEN) {
                    switch_01_Led1.blink(0);
                    switch_01_Led1.off();
                } else {
                    switch_01_Led1.blink(500);
                }
               
                relayOn = !relayOn;
            }
        });
       
        switch_01_BtnA.addListener(new ButtonReleasedListener() {
            public void onButtonReleased(ButtonEvent event) {
                // display console message
                AnsiConsole.out().println(Ansi.ansi()
                    .fgBright(Ansi.Color.CYAN)
                    .a("Switch_01_BtnA released").reset()
                );
            }
        });
       
Although I'm having both ButtonPressedListener as well as ButtonReleasedListener, I'm only interested in the ButtonPressedListener.  Hence, the "logic" is within the onButtonPressed() method.

To know if I have to switch on or off the blinking, I'm checking the state of the relay after I've toggled the relay.  And here's where the problem lies:

  • The function relay_V01.toggle() works perfect.  Each and every time I press the button of the switch, the relays toggles to the opposite state (if on, switch off / if off, switch on).  It never skips a state.
  • However, the function relay_V01.getState() returns me sometimes the wrong state and when this happens, the state returned remains wrong.
    If the relays is open (that is, switched off), I want to stop the LED blinking.  Otherwise, I want to start the blinking.
    Only the very first button press, the synchronisation between the relay toggling and the relay state is OK.  From the second button press onwards, things get out of sync (that is, when the relay is switched off through the toggle function, the getState returns me that the relay is on and vice versa.

So far, I was not able to debug this decently, but I'm afraid it has something to do with the cached state of the relay...

Unless someone finds something wrong in the above code?

PS: I've also tried to switch the initial state of switch_01_BtnA while creating the instance, but that doesn't solve the issue...

PPS: It would be really nice if the ToggleSwitch component would indeed implement the real toggle function.  Maybe I wouldn't have to rely on the getState() of the relay component then...



Robert Savage

unread,
Apr 13, 2015, 9:37:44 AM4/13/15
to pi...@googlegroups.com
I am guessing the issue lies with the MCP23017GpioProvider impl.  Getting the relay's state ultimately calls into the MCP23017GpioProvider's getState(pin) method.  For the MCP23017GpioProvider implementation, it uses a timer thread (GpioStateMonitor) to watch for pin state changes.  
I suspect that there is some race condition with GpioStateMonitor where the state is not yet *settled*.  I have not yet see an obvious bug that stands out, but I could see this race condition causing some erroneous results.

Try basing your logic on the last state of the relay prior to invoking a state change on it.  Let's just see if that helps at all.

...

if (relay_V01.getState() == RelayState.CLOSED) {
  switch_01_Led1.blink(0);
  switch_01_Led1.off();
  relay_V01.open();
} else {
  switch_01_Led1.blink(500);
  relay_V01.close();
}


..


GeertVc

unread,
Jun 26, 2015, 6:17:28 AM6/26/15
to pi...@googlegroups.com
First off... Sorry for the very late reply.

I've tried the following code (equivalent to the original code I posted before) and all works like a charm now:

switchAanrechtRechtsKnopA.addListener(new SwitchListener() {
    @Override
    public void onStateChange(SwitchStateChangeEvent event) {
        if (event.getNewState() == SwitchState.ON) {
            relayOnderlichtKeuken.toggle();
            if (relayOnderlichtKeuken.isClosed()) {
                switchAanrechtRechtsLedA.on();
            } else {
                switchAanrechtRechtsLedA.off();
            }
        }
        System.out.println("[ SWITCH S2_A PRESSED ]: " + event.getNewState());
    }
});


Where:
  • switchAanrechtRechtsKnopA is a MomentarySwitch
  • relayOnderlichtKeuken is a Relay
  • switchAanrechtRechtsLedA is a LED

Any idea if the issues were maybe solved with the official Pi4J release (I was using the SNAPSHOT version initially, now I moved to the official Pi4J release...)?

Reply all
Reply to author
Forward
0 new messages