Multi Button Relay Sketch



  • Has anyone made a multi (at least 4) relay version of the relay with button sketch? the basic relay example sketch allows for multiple relays but the relay with button sketch only allows for 1. I am sure it would not be difficult for an experienced Arduino/MySensors programmer to modify the example sketch for me? Any takers?


  • Hero Member

    @SGi I have used two buttons in my Mains controller project. I have posted just the relay code below to show you what you need to do. I have not used the eeprom to store the state but you could soon add that back in. The main thing you need to do is check to see which sensor the incoming message is for.

    /**
       
       DESCRIPTION
       Based on the RelayWithButtonActuator sketch
      
    */
    
    // Enable debug prints to serial monitor
    #define MY_DEBUG
    
    // Enable and select radio type attached
    #define MY_RADIO_NRF24
    //#define MY_RADIO_RFM69
    
    // Enabled repeater feature for this node
    //#define MY_REPEATER_FEATURE
    
    #include <SPI.h>
    #include <MySensors.h>
    #include <Bounce2.h>
    
    #define RELAY_ON 1
    #define RELAY_OFF 0
    
    #define SSR_A_ID 1   // Id of the sensor child
    #define SSR_B_ID 2   // Id of the sensor child
    
    const int buttonPinA = 3;
    const int buttonPinB = 4;
    const int relayPinA = 5;
    const int relayPinB = 6;
    int oldValueA = 0;
    int oldValueB = 0;
    bool stateA = false;
    bool stateB = false;
    
    
    
    Bounce debouncerA = Bounce();
    Bounce debouncerB = Bounce();
    
    MyMessage msgA(SSR_A_ID, V_STATUS);
    MyMessage msgB(SSR_B_ID, V_STATUS);
    
    void setup()
    {
    
      pinMode(buttonPinA, INPUT_PULLUP); // Setup the button Activate internal pull-up
      pinMode(buttonPinB, INPUT_PULLUP); // Setup the button Activate internal pull-up
    // Then set relay pins in output mode
      pinMode(relayPinA, OUTPUT);
      pinMode(relayPinB, OUTPUT);
    
      // After setting up the buttons, setup debouncer
      debouncerA.attach(buttonPinA);
      debouncerA.interval(5);
      debouncerB.attach(buttonPinB);
      debouncerB.interval(5);
    
      // Make sure relays are off when starting up
      digitalWrite(relayPinA, RELAY_OFF);
      digitalWrite(relayPinB, RELAY_OFF);
      
      
    }
    
    void presentation()  {
      // Send the sketch version information to the gateway and Controller
      sendSketchInfo("Mains Controller", "1.0");
    
      // Register all sensors to gw (they will be created as child devices)
      present(SSR_A_ID, S_LIGHT);
      present(SSR_B_ID, S_LIGHT);
    
    }
    
    /*
       Example on how to asynchronously check for new messages from gw
    */
    void loop()
    {
      debouncerA.update();
      // Get the update value
      int valueA = debouncerA.read();
      if (valueA != oldValueA && valueA == 0) {
        send(msgA.set(stateA ? false : true), true); // Send new state and request ack back
    
      }
      oldValueA = valueA;
     
    
      debouncerB.update();
      // Get the update value
      int valueB = debouncerB.read();
      if (valueB != oldValueB && valueB == 0) {
        send(msgB.set(stateB ? false : true), true); // Send new state and request ack back
    
      }
      oldValueB = valueB;
    }
    
    void receive(const MyMessage &message) {
      // We only expect one type of message from controller. But we better check anyway.
     
    
    
      
    
      if (message.type == V_STATUS) {
          
        switch (message.sensor) {
          case 1:
            stateA = message.getBool();
            digitalWrite(message.sensor + 4, stateA ? RELAY_ON : RELAY_OFF);
            
            break;
          case 2:
            stateB = message.getBool();
            digitalWrite(message.sensor + 4, stateB ? RELAY_ON : RELAY_OFF);
            
            break;
          
        }
       
          // Write some debug info
        Serial.print("Incoming change for sensor:");
        Serial.println(message.sensor);
        Serial.print("from node:");
        Serial.println(message.sender);
        Serial.print(", New status: ");
        Serial.println(message.getBool());
      }
    }
    
    


  • @Boots33
    if i want use an up/down switch (no push switch) that with each change (up or down) , relay state change . for example if relay is "on" and switch is "down" , with change switch to "up" relay to be "off" OR if relay is "off" and switch is "down" , with change switch to "up" relay to be "on"
    in sketch , what am i do ?


  • Hero Member

    Haven't tried it but this might work

    move the line _____ oldValueA = valueA; ____up into the if statement

    and remove ______ && valueA == 0 ____ from the if conditional

     debouncerA.update();
      // Get the update value
      int valueA = debouncerA.read();
      if (valueA != oldValueA ) {
        send(msgA.set(stateA ? false : true), true); // Send new state and request ack back
       oldValueA = valueA;
      }
      
    


  • @Boots33
    this is great
    but have a tiny problem
    with power off/on , relay state is unstable every time . i could not fix this . can you fix ? with power off/on relay to be high every time . different state of relay and button have influence on relay state after power off/on . often with power off/on , there are a change state low to high or high to low quickly.
    in other means , in startup if switch be down or up , dont Make sure relays are off when starting up

    also state in web is not correct


  • Hero Member

    @rayan It might be easier if you post your code so we can see where the changes need to be made.



  • @Boots33
    this is your code :)

    #define MY_DEBUG
    #define MY_RADIO_NRF24
    #define MY_REPEATER_FEATURE
    
    #include <SPI.h>
    #include <MySensors.h>
    #include <Bounce2.h>
    
    #define RELAY_ON 1
    #define RELAY_OFF 0
    
    #define SSR_A_ID 1   // Id of the sensor child
    #define SSR_B_ID 2   // Id of the sensor child
    
    const int buttonPinA = 18;
    const int buttonPinB = 19;
    const int relayPinA = 5;
    const int relayPinB = 6;
    int oldValueA = 0;
    int oldValueB = 0;
    bool stateA = false;
    bool stateB = false;
    
    
    
    Bounce debouncerA = Bounce();
    Bounce debouncerB = Bounce();
    
    MyMessage msgA(SSR_A_ID, V_STATUS);
    MyMessage msgB(SSR_B_ID, V_STATUS);
    
    void setup()
    {
    
      pinMode(buttonPinA, INPUT_PULLUP); // Setup the button Activate internal pull-up
      pinMode(buttonPinB, INPUT_PULLUP); // Setup the button Activate internal pull-up
    
    
      // After setting up the buttons, setup debouncer
      debouncerA.attach(buttonPinA);
      debouncerA.interval(5);
      debouncerB.attach(buttonPinB);
      debouncerB.interval(5);
    
      // Make sure relays are off when starting up
      digitalWrite(relayPinA, RELAY_OFF);
      digitalWrite(relayPinB, RELAY_OFF);
      // Then set relay pins in output mode
      pinMode(relayPinA, OUTPUT);
      pinMode(relayPinB, OUTPUT);
      
    }
    
    void presentation()  {
      // Send the sketch version information to the gateway and Controller
      sendSketchInfo("Mains Controller", "1.0");
    
      // Register all sensors to gw (they will be created as child devices)
      present(SSR_A_ID, S_LIGHT);
      present(SSR_B_ID, S_LIGHT);
    
    }
    
    /*
       Example on how to asynchronously check for new messages from gw
    */
    void loop()
    {
      debouncerA.update();
      // Get the update value
      int valueA = debouncerA.read();
      if (valueA != oldValueA) {
        send(msgA.set(stateA ? false : true), true); // Send new state and request ack back
      oldValueA = valueA;
      }
     
    
      debouncerB.update();
      // Get the update value
      int valueB = debouncerB.read();
      if (valueB != oldValueB) {
        send(msgB.set(stateB ? false : true), true); // Send new state and request ack back
      oldValueB = valueB;
      }
    }
    
    void receive(const MyMessage &message) {
      // We only expect one type of message from controller. But we better check anyway.
      if (message.type == V_STATUS) {
          
        switch (message.sensor) {
          case 1:
            stateA = message.getBool();
            digitalWrite(message.sensor + 4, stateA ? RELAY_ON : RELAY_OFF);
            
            break;
          case 2:
            stateB = message.getBool();
            digitalWrite(message.sensor + 4, stateB ? RELAY_ON : RELAY_OFF);
            
            break;
          
        }
       
          // Write some debug info
        Serial.print("Incoming change for sensor:");
        Serial.println(message.sensor);
        Serial.print("from node:");
        Serial.println(message.sender);
        Serial.print(", New status: ");
        Serial.println(message.getBool());
      }
    }
    


  • you are set value for relay in code

      digitalWrite(relayPinA, RELAY_OFF);
      digitalWrite(relayPinB, RELAY_OFF);
    

    but i dont know why after start up . . .


  • Hero Member

    @rayan so are you saying that when the node is first booted up you want the relay to always to be turned on?



  • @Boots33
    i want if power of home be off and after time on again , so all of relay ( with switch up/down with each state) to be off. now in this code after startup relay is unstable for 1s and my light is on and aff quickly :)
    also if lights are off , if power off/on , so some of relay go to ON in startup !


  • Hero Member

    @rayan So if the house looses power you want the relays to be turned off when power is restored?



  • @Boots33
    yes, all of lights are on or off (some on some off) so when looses power and power is restored , i want all of lights be off also in web and app light = off , so with key in app or change state of switch turn on again ...



  • but this app , every time after the restored power and startup, relay ( related to state of up/down switch) have different state


  • Hero Member

    @rayan yes it was meant to be used with push buttons not toggle switches. It will need a few tweaks to make it work. I am at work now so will take a look when I get home.



  • @Boots33 said:

    @rayan yes it was meant to be used with push buttons not toggle switches. It will need a few tweaks to make it work. I am at work now so will take a look when I get home.

    ok thank you


  • Hero Member

    @rayan Ok had a quick look and I don't think we need to do a lot for this to work.
    The only extra change I have made is to add four new lines at the end of the setup function

       /*--------------------- Added these lines for toggle switch-------------------------*/
      oldValueA = digitalRead(buttonPinA);  // set oldValueA to the current status of the toggle switch
      oldValueB = digitalRead(buttonPinB);  // set oldValueB to the current status of the toggle switch
      send(msgA.set(false)); // Send off state for relayA to ensure controller knows the switch is off
      send(msgB.set(false)); // Send off state for relayB to ensure controller knows the switch is off
    

    As you can see the oldValue variables are now set to represent the current state of the toggle switches when the node boots up. this should stop any changes in state being made in the main loop until a switch is toggled.
    The other two lines just send a message to the controller to tell it the switches are off. this should make the controller icons show the correct state

    Below is the full sketch, I have nothing to test it on so give it a try and see how it goes

    #define MY_DEBUG
    #define MY_RADIO_NRF24
    #define MY_REPEATER_FEATURE
    
    #include <SPI.h>
    #include <MySensors.h>
    #include <Bounce2.h>
    
    #define RELAY_ON 1
    #define RELAY_OFF 0
    
    #define SSR_A_ID 1   // Id of the sensor child
    #define SSR_B_ID 2   // Id of the sensor child
    
    const int buttonPinA = 18;
    const int buttonPinB = 19;
    const int relayPinA = 5;
    const int relayPinB = 6;
    int oldValueA = 0;
    int oldValueB = 0;
    bool stateA = false;
    bool stateB = false;
    
    
    
    Bounce debouncerA = Bounce();
    Bounce debouncerB = Bounce();
    
    MyMessage msgA(SSR_A_ID, V_STATUS);
    MyMessage msgB(SSR_B_ID, V_STATUS);
    
    void setup()
    {
    
      pinMode(buttonPinA, INPUT_PULLUP); // Setup the button Activate internal pull-up
      pinMode(buttonPinB, INPUT_PULLUP); // Setup the button Activate internal pull-up
    // Then set relay pins in output mode
      pinMode(relayPinA, OUTPUT);
      pinMode(relayPinB, OUTPUT);
    
      // After setting up the buttons, setup debouncer
      debouncerA.attach(buttonPinA);
      debouncerA.interval(5);
      debouncerB.attach(buttonPinB);
      debouncerB.interval(5);
    
      // Make sure relays are off when starting up
      digitalWrite(relayPinA, RELAY_OFF);
      digitalWrite(relayPinB, RELAY_OFF);
      
    
        /*--------------------- Added these lines for toggle switch-------------------------*/
      oldValueA = digitalRead(buttonPinA);  // set oldValueA to the current status of the toggle switch
      oldValueB = digitalRead(buttonPinB);  // set oldValueB to the current status of the toggle switch
      send(msgA.set(false)); // Send off state for relayA to ensure controller knows the switch is off
      send(msgB.set(false)); // Send off state for relayB to ensure controller knows the switch is off
      
    }
    
    void presentation()  {
      // Send the sketch version information to the gateway and Controller
      sendSketchInfo("Mains Controller", "1.0");
    
      // Register all sensors to gw (they will be created as child devices)
      present(SSR_A_ID, S_LIGHT);
      present(SSR_B_ID, S_LIGHT);
    
    }
    
    /*
       Example on how to asynchronously check for new messages from gw
    */
    void loop()
    {
      debouncerA.update();
      // Get the update value
      int valueA = debouncerA.read();
      if (valueA != oldValueA) {
        send(msgA.set(stateA ? false : true), true); // Send new state and request ack back
      oldValueA = valueA;
      }
     
    
      debouncerB.update();
      // Get the update value
      int valueB = debouncerB.read();
      if (valueB != oldValueB) {
        send(msgB.set(stateB ? false : true), true); // Send new state and request ack back
      oldValueB = valueB;
      }
    }
    
    void receive(const MyMessage &message) {
      // We only expect one type of message from controller. But we better check anyway.
      if (message.type == V_STATUS) {
          
        switch (message.sensor) {
          case 1:
            stateA = message.getBool();
            digitalWrite(message.sensor + 4, stateA ? RELAY_ON : RELAY_OFF);
            
            break;
          case 2:
            stateB = message.getBool();
            digitalWrite(message.sensor + 4, stateB ? RELAY_ON : RELAY_OFF);
            
            break;
          
        }
       
          // Write some debug info
        Serial.print("Incoming change for sensor:");
        Serial.println(message.sensor);
        Serial.print("from node:");
        Serial.println(message.sender);
        Serial.print(", New status: ");
        Serial.println(message.getBool());
      }
    }
    


  • @Boots33 said:

    i test your code and this is excellent . but there is another tiny problem :)
    when relay is ON then loses power so in app relay is ON (icon) , when power is restored and relay go to OFF in app icon is ON and dont Ack for go to show Off .
    you are best in programming :)


  • Hero Member

    @rayan maybe trying to send the off message before the presentation stops it from sending

    try this , have moved the messages to the main loop where they will only be sent once in the first loop

    #define MY_DEBUG
    #define MY_RADIO_NRF24
    #define MY_REPEATER_FEATURE
    
    #include <SPI.h>
    #include <MySensors.h>
    #include <Bounce2.h>
    
    #define RELAY_ON 1
    #define RELAY_OFF 0
    
    #define SSR_A_ID 1   // Id of the sensor child
    #define SSR_B_ID 2   // Id of the sensor child
    
    const int buttonPinA = 18;
    const int buttonPinB = 19;
    const int relayPinA = 5;
    const int relayPinB = 6;
    int oldValueA = 0;
    int oldValueB = 0;
    bool stateA = false;
    bool stateB = false;
    int trigger = 0;
    
    
    Bounce debouncerA = Bounce();
    Bounce debouncerB = Bounce();
    
    MyMessage msgA(SSR_A_ID, V_STATUS);
    MyMessage msgB(SSR_B_ID, V_STATUS);
    
    void setup()
    {
    
      pinMode(buttonPinA, INPUT_PULLUP); // Setup the button Activate internal pull-up
      pinMode(buttonPinB, INPUT_PULLUP); // Setup the button Activate internal pull-up
    // Then set relay pins in output mode
      pinMode(relayPinA, OUTPUT);
      pinMode(relayPinB, OUTPUT);
    
      // After setting up the buttons, setup debouncer
      debouncerA.attach(buttonPinA);
      debouncerA.interval(5);
      debouncerB.attach(buttonPinB);
      debouncerB.interval(5);
    
      // Make sure relays are off when starting up
      digitalWrite(relayPinA, RELAY_OFF);
      digitalWrite(relayPinB, RELAY_OFF);
      
    
        /*--------------------- Added these lines for toggle switch-------------------------*/
      oldValueA = digitalRead(buttonPinA);  // set oldValueA to the current status of the toggle switch
      oldValueB = digitalRead(buttonPinB);  // set oldValueB to the current status of the toggle switch
     // send(msgA.set(false)); // Send off state for relayA to ensure controller knows the switch is off
     // send(msgB.set(false)); // Send off state for relayB to ensure controller knows the switch is off
      
    }
    
    void presentation()  {
      // Send the sketch version information to the gateway and Controller
      sendSketchInfo("Mains Controller", "1.0");
    
      // Register all sensors to gw (they will be created as child devices)
      present(SSR_A_ID, S_LIGHT);
      present(SSR_B_ID, S_LIGHT);
    
    }
    
    /*
       Example on how to asynchronously check for new messages from gw
    */
    void loop()
    {
    if (trigger == 0){
      send(msgA.set(false)); // Send off state for relayA to ensure controller knows the switch is off
      send(msgB.set(false)); // Send off state for relayB to ensure controller knows the switch is off
      trigger = 1;
    }
    
    
      debouncerA.update();
      // Get the update value
      int valueA = debouncerA.read();
      if (valueA != oldValueA) {
        send(msgA.set(stateA ? false : true), true); // Send new state and request ack back
      oldValueA = valueA;
      }
     
    
      debouncerB.update();
      // Get the update value
      int valueB = debouncerB.read();
      if (valueB != oldValueB) {
        send(msgB.set(stateB ? false : true), true); // Send new state and request ack back
      oldValueB = valueB;
      }
    }
    
    void receive(const MyMessage &message) {
      // We only expect one type of message from controller. But we better check anyway.
      if (message.type == V_STATUS) {
          
        switch (message.sensor) {
          case 1:
            stateA = message.getBool();
            digitalWrite(message.sensor + 4, stateA ? RELAY_ON : RELAY_OFF);
            
            break;
          case 2:
            stateB = message.getBool();
            digitalWrite(message.sensor + 4, stateB ? RELAY_ON : RELAY_OFF);
            
            break;
          
        }
       
          // Write some debug info
        Serial.print("Incoming change for sensor:");
        Serial.println(message.sensor);
        Serial.print("from node:");
        Serial.println(message.sender);
        Serial.print(", New status: ");
        Serial.println(message.getBool());
      }
    }
    


  • @Boots33
    great.
    so this is best sketch :)
    thank you



  • @Boots33
    oh , after added this device , happen a Event ! node id of motion sensor and this device is 1 ! and after sense of motion light on in dashborad ! why both Catch node id 1 .
    i dont add #define node id for motion and for this. but both take id 1 and Interference

    0_1475589467935_mdmddmdmd.jpg


Log in to reply
 

Looks like your connection to MySensors Forum was lost, please wait while we try to reconnect.