Skip to content
  • MySensors
  • OpenHardware.io
  • Categories
  • Recent
  • Tags
  • Popular
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Brand Logo
  1. Home
  2. General Discussion
  3. Array Relay Button Actuator

Array Relay Button Actuator

Scheduled Pinned Locked Moved General Discussion
45 Posts 16 Posters 24.8k Views 16 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • BartEB BartE

    @niccodemi You can forget using the oldValue, because the debounce takes track of it's last status. When update() is called and a debounced pin-change is detect this function will return true otherwise it will send false.
    Having a short delay each loop will stabilize the debouncers so your loop() can look like this:

    void loop()
    {
        for (byte i = 0; i < noRelays; i++) {
            if (debouncer[i].update()) {
                Relays[i].relayState = !Relays[i].relayState;
                digitalWrite(Relays[i].relayPin, Relays[i].relayState?RELAY_ON:RELAY_OFF);
                send(msg[i].set(Relays[i].relayState? true : false));
                // save sensor state in EEPROM (location == sensor number)
                saveState( i, Relays[i].relayState );
            }                 
        }
        wait(10);
    }
    
    martinhjelmareM Offline
    martinhjelmareM Offline
    martinhjelmare
    Plugin Developer
    wrote on last edited by martinhjelmare
    #36

    @BartE

    Why do you think it's better to add the wait than to increase debounce interval? Didn't know update returns a boolean, cool.

    BartEB 1 Reply Last reply
    0
    • martinhjelmareM martinhjelmare

      @BartE

      Why do you think it's better to add the wait than to increase debounce interval? Didn't know update returns a boolean, cool.

      BartEB Offline
      BartEB Offline
      BartE
      Contest Winner
      wrote on last edited by BartE
      #37

      @martinhjelmare there is no reason to have that many button checks per millisecond, if you "wait" each while loop the MySensors core has more time to process messages i.s.o. of reading I/O pins especially when your node acts as a repeater. (During a wait the process function is called)
      A person will not notices a button to take 50 i.s.o 10 milliseconds to respond.

      martinhjelmareM 1 Reply Last reply
      1
      • BartEB BartE

        @martinhjelmare there is no reason to have that many button checks per millisecond, if you "wait" each while loop the MySensors core has more time to process messages i.s.o. of reading I/O pins especially when your node acts as a repeater. (During a wait the process function is called)
        A person will not notices a button to take 50 i.s.o 10 milliseconds to respond.

        martinhjelmareM Offline
        martinhjelmareM Offline
        martinhjelmare
        Plugin Developer
        wrote on last edited by
        #38

        @BartE

        Yes, very good point.

        1 Reply Last reply
        0
        • N Offline
          N Offline
          niccodemi
          wrote on last edited by
          #39

          @martinhjelmare @BartE thank you both for trying to solve this issue but the problem is still there. On reboot relay (usually just 1 never both) gets set randomly in loop function (setup function always restores correct state). I also tried increasing debouncer up to 500 without success. And I am also sure this is not hardware related because if I load sketch which is meant for momentary switch relays work as expected (tested with 10 consecutive reboots). Just to be on the same page this is latest sketch:

          //MultiRelayButton Sketch, MySensors 1.6
          
          #define MY_RADIO_NRF24
          
          #define MY_REPEATER_FEATURE
          
          #include <MySensor.h>
          #include <SPI.h>
          #include <Bounce2.h>
          #define RELAY_ON 0                      // switch around for realy HIGH/LOW state
          #define RELAY_OFF 1
          //
          
          #define noRelays 2                     //2-4
          const int relayPin[] = {14,15};          //  switch around pins to your desire
          const int buttonPin[] = {3,4};      //  switch around pins to your desire
          
          class Relay             // relay class, store all relevant data (equivalent to struct)
          {
          public:                                      
            int buttonPin;                   // physical pin number of button
            int relayPin;             // physical pin number of relay
            //byte oldValue;                    // last Values for key (debounce)
            boolean relayState;               // relay status (also stored in EEPROM)
          };
          
          Relay Relays[noRelays]; 
          Bounce debouncer[noRelays];
          MyMessage msg[noRelays];
          
          void setup(){
              sendHeartbeat();
              wait(250);
              // Initialize Relays with corresponding buttons
              for (int i = 0; i < noRelays; i++){
              Relays[i].buttonPin = buttonPin[i];              // assign physical pins
              Relays[i].relayPin = relayPin[i];
              msg[i].sensor = i;                                   // initialize messages
              msg[i].type = V_LIGHT;
              debouncer[i] = Bounce();                        // initialize debouncer
              debouncer[i].attach(buttonPin[i]);
              debouncer[i].interval(100);
              pinMode(Relays[i].buttonPin, INPUT_PULLUP);
              wait(250);
              pinMode(Relays[i].relayPin, OUTPUT);
              //Relays[i].oldValue = digitalRead(Relays[i].buttonPin);
              Relays[i].relayState = loadState(i);                               // retrieve last values from EEPROM
              digitalWrite(Relays[i].relayPin, Relays[i].relayState? RELAY_ON:RELAY_OFF);   // and set relays accordingly
              send(msg[i].set(Relays[i].relayState? true : false));                  // make controller aware of last status  
              wait(250);
              }
          }
          void presentation()  {
                sendSketchInfo("MultiRelayButton", "0.9k");
                wait(250);
                for (int i = 0; i < noRelays; i++)
                present(i, S_LIGHT);                               // present sensor to gateway
                wait(250);
          }
          void loop()
          {
              for (byte i = 0; i < noRelays; i++) {
                  if (debouncer[i].update()) {
                      Relays[i].relayState = !Relays[i].relayState;
                      digitalWrite(Relays[i].relayPin, Relays[i].relayState?RELAY_ON:RELAY_OFF);
                      send(msg[i].set(Relays[i].relayState? true : false));
                      // save sensor state in EEPROM (location == sensor number)
                      saveState( i, Relays[i].relayState );
                  }                 
              }
              wait(50);
          }
          // process incoming message 
          void receive(const MyMessage &message){        
             if (message.type == V_LIGHT){ 
             if (message.sensor <noRelays){            // check if message is valid for relays..... previous line  [[[ if (message.sensor <=noRelays){ ]]]
             Relays[message.sensor].relayState = message.getBool(); 
             digitalWrite(Relays[message.sensor].relayPin, Relays[message.sensor].relayState? RELAY_ON:RELAY_OFF); // and set relays accordingly
             saveState( message.sensor, Relays[message.sensor].relayState ); // save sensor state in EEPROM (location == sensor number)
             }
            }
            wait(50);
          }
          
          martinhjelmareM 1 Reply Last reply
          0
          • N niccodemi

            @martinhjelmare @BartE thank you both for trying to solve this issue but the problem is still there. On reboot relay (usually just 1 never both) gets set randomly in loop function (setup function always restores correct state). I also tried increasing debouncer up to 500 without success. And I am also sure this is not hardware related because if I load sketch which is meant for momentary switch relays work as expected (tested with 10 consecutive reboots). Just to be on the same page this is latest sketch:

            //MultiRelayButton Sketch, MySensors 1.6
            
            #define MY_RADIO_NRF24
            
            #define MY_REPEATER_FEATURE
            
            #include <MySensor.h>
            #include <SPI.h>
            #include <Bounce2.h>
            #define RELAY_ON 0                      // switch around for realy HIGH/LOW state
            #define RELAY_OFF 1
            //
            
            #define noRelays 2                     //2-4
            const int relayPin[] = {14,15};          //  switch around pins to your desire
            const int buttonPin[] = {3,4};      //  switch around pins to your desire
            
            class Relay             // relay class, store all relevant data (equivalent to struct)
            {
            public:                                      
              int buttonPin;                   // physical pin number of button
              int relayPin;             // physical pin number of relay
              //byte oldValue;                    // last Values for key (debounce)
              boolean relayState;               // relay status (also stored in EEPROM)
            };
            
            Relay Relays[noRelays]; 
            Bounce debouncer[noRelays];
            MyMessage msg[noRelays];
            
            void setup(){
                sendHeartbeat();
                wait(250);
                // Initialize Relays with corresponding buttons
                for (int i = 0; i < noRelays; i++){
                Relays[i].buttonPin = buttonPin[i];              // assign physical pins
                Relays[i].relayPin = relayPin[i];
                msg[i].sensor = i;                                   // initialize messages
                msg[i].type = V_LIGHT;
                debouncer[i] = Bounce();                        // initialize debouncer
                debouncer[i].attach(buttonPin[i]);
                debouncer[i].interval(100);
                pinMode(Relays[i].buttonPin, INPUT_PULLUP);
                wait(250);
                pinMode(Relays[i].relayPin, OUTPUT);
                //Relays[i].oldValue = digitalRead(Relays[i].buttonPin);
                Relays[i].relayState = loadState(i);                               // retrieve last values from EEPROM
                digitalWrite(Relays[i].relayPin, Relays[i].relayState? RELAY_ON:RELAY_OFF);   // and set relays accordingly
                send(msg[i].set(Relays[i].relayState? true : false));                  // make controller aware of last status  
                wait(250);
                }
            }
            void presentation()  {
                  sendSketchInfo("MultiRelayButton", "0.9k");
                  wait(250);
                  for (int i = 0; i < noRelays; i++)
                  present(i, S_LIGHT);                               // present sensor to gateway
                  wait(250);
            }
            void loop()
            {
                for (byte i = 0; i < noRelays; i++) {
                    if (debouncer[i].update()) {
                        Relays[i].relayState = !Relays[i].relayState;
                        digitalWrite(Relays[i].relayPin, Relays[i].relayState?RELAY_ON:RELAY_OFF);
                        send(msg[i].set(Relays[i].relayState? true : false));
                        // save sensor state in EEPROM (location == sensor number)
                        saveState( i, Relays[i].relayState );
                    }                 
                }
                wait(50);
            }
            // process incoming message 
            void receive(const MyMessage &message){        
               if (message.type == V_LIGHT){ 
               if (message.sensor <noRelays){            // check if message is valid for relays..... previous line  [[[ if (message.sensor <=noRelays){ ]]]
               Relays[message.sensor].relayState = message.getBool(); 
               digitalWrite(Relays[message.sensor].relayPin, Relays[message.sensor].relayState? RELAY_ON:RELAY_OFF); // and set relays accordingly
               saveState( message.sensor, Relays[message.sensor].relayState ); // save sensor state in EEPROM (location == sensor number)
               }
              }
              wait(50);
            }
            
            martinhjelmareM Offline
            martinhjelmareM Offline
            martinhjelmare
            Plugin Developer
            wrote on last edited by martinhjelmare
            #40

            @niccodemi

            I think you should setup the button first, pinMode etc, and then setup the debouncer and attach it to the button.

            https://github.com/thomasfredericks/Bounce2/wiki

            If you attach the debouncer while the pin is floating, the debouncer will probably have a hard time figuring out correct new state.

            1 Reply Last reply
            0
            • N Offline
              N Offline
              niccodemi
              wrote on last edited by
              #41

              @martinhjelmare

              That was it. After I amended sketch according to your advise all the random state changes disappeared. I rebooted node over 20 times in various button / relay states and it always started with relays in correct position. For anyone else interested below is amended sketch.

              //MultiRelayButton Sketch, MySensors 1.6, toggle switch
              
              #define MY_RADIO_NRF24
              
              #define MY_REPEATER_FEATURE
              
              #include <MySensor.h>
              #include <SPI.h>
              #include <Bounce2.h>
              #define RELAY_ON 0                      // switch around for ACTIVE LOW / ACTIVE HIGH relay
              #define RELAY_OFF 1
              //
              
              #define noRelays 2                     //2-4
              const int relayPin[] = {14,15};          //  switch around pins to your desire
              const int buttonPin[] = {3,4};      //  switch around pins to your desire
              
              class Relay             // relay class, store all relevant data (equivalent to struct)
              {
              public:                                      
                int buttonPin;                   // physical pin number of button
                int relayPin;             // physical pin number of relay
                boolean relayState;               // relay status (also stored in EEPROM)
              };
              
              Relay Relays[noRelays]; 
              Bounce debouncer[noRelays];
              MyMessage msg[noRelays];
              
              void setup(){
                  sendHeartbeat();
                  wait(100);
                  // Initialize Relays with corresponding buttons
                  for (int i = 0; i < noRelays; i++){
                  Relays[i].buttonPin = buttonPin[i];              // assign physical pins
                  Relays[i].relayPin = relayPin[i];
                  msg[i].sensor = i;                                   // initialize messages
                  msg[i].type = V_LIGHT;   
                  pinMode(Relays[i].buttonPin, INPUT_PULLUP);
                  wait(100);
                  pinMode(Relays[i].relayPin, OUTPUT);
                  Relays[i].relayState = loadState(i);                               // retrieve last values from EEPROM
                  digitalWrite(Relays[i].relayPin, Relays[i].relayState? RELAY_ON:RELAY_OFF);   // and set relays accordingly
                  send(msg[i].set(Relays[i].relayState? true : false));                  // make controller aware of last status  
                  wait(50);
                  debouncer[i] = Bounce();                        // initialize debouncer
                  debouncer[i].attach(buttonPin[i]);
                  debouncer[i].interval(20);
                  wait(50);
                  }
              }
              void presentation()  {
                    sendSketchInfo("MultiRelayButton", "0.9t");
                    wait(100);
                    for (int i = 0; i < noRelays; i++)
                    present(i, S_LIGHT);                               // present sensor to gateway
                    wait(100);
              }
              void loop()
              {
                  for (byte i = 0; i < noRelays; i++) {
                      if (debouncer[i].update()) {
                          Relays[i].relayState = !Relays[i].relayState;
                          digitalWrite(Relays[i].relayPin, Relays[i].relayState?RELAY_ON:RELAY_OFF);
                          send(msg[i].set(Relays[i].relayState? true : false));
                          // save sensor state in EEPROM (location == sensor number)
                          saveState( i, Relays[i].relayState );
                      }                 
                  }
                  wait(20);
              }
              // process incoming message 
              void receive(const MyMessage &message){        
                 if (message.type == V_LIGHT){ 
                 if (message.sensor <noRelays){            // check if message is valid for relays..... previous line  [[[ if (message.sensor <=noRelays){ ]]]
                 Relays[message.sensor].relayState = message.getBool(); 
                 digitalWrite(Relays[message.sensor].relayPin, Relays[message.sensor].relayState? RELAY_ON:RELAY_OFF); // and set relays accordingly
                 saveState( message.sensor, Relays[message.sensor].relayState ); // save sensor state in EEPROM (location == sensor number)
                 }
                }
                wait(20);
              }
              
              1 Reply Last reply
              0
              • M Offline
                M Offline
                moskovskiy82
                wrote on last edited by
                #42

                What is the simplest method to add two extra butons to this sketch not tied to the relay?
                I have a four button device. Two will work with relays and two extra utilised in openhab rules

                1 Reply Last reply
                0
                • korttomaK Offline
                  korttomaK Offline
                  korttoma
                  Hero Member
                  wrote on last edited by
                  #43

                  Just in case someone else finds this thread and decides to use the sketch and runs in to the same issue I did.

                  I was using push buttons and the sketch above, when I pushed the button the relay turned on but as soon as I let go of the button the relay turned back off. I changed the sketch like this:

                  void loop()
                  {
                    for (byte i = 0; i < noRelays; i++) {
                      if (debouncer[i].update()) {
                        
                        int value = debouncer[i].read();
                        
                        if ( value == LOW) {
                          Relays[i].relayState = !Relays[i].relayState;
                          digitalWrite(Relays[i].relayPin, Relays[i].relayState ? RELAY_ON : RELAY_OFF);
                          send(msg[i].set(Relays[i].relayState ? true : false));
                          // save sensor state in EEPROM (location == sensor number)
                          saveState( i, Relays[i].relayState );
                        }
                      }
                    }
                    //wait(20);
                  }
                  

                  Now the relay changes state as soon as I push the button and keeps the state until I push the button again.

                  Because my inputs for the push buttons are ground when pushed I used

                  if ( value == LOW) 
                  

                  This way the relay would turn on immediately when I push the button and not wait until I let go of the button.

                  • Tomas
                  Стоян ГеоргиевС 1 Reply Last reply
                  0
                  • korttomaK korttoma

                    Just in case someone else finds this thread and decides to use the sketch and runs in to the same issue I did.

                    I was using push buttons and the sketch above, when I pushed the button the relay turned on but as soon as I let go of the button the relay turned back off. I changed the sketch like this:

                    void loop()
                    {
                      for (byte i = 0; i < noRelays; i++) {
                        if (debouncer[i].update()) {
                          
                          int value = debouncer[i].read();
                          
                          if ( value == LOW) {
                            Relays[i].relayState = !Relays[i].relayState;
                            digitalWrite(Relays[i].relayPin, Relays[i].relayState ? RELAY_ON : RELAY_OFF);
                            send(msg[i].set(Relays[i].relayState ? true : false));
                            // save sensor state in EEPROM (location == sensor number)
                            saveState( i, Relays[i].relayState );
                          }
                        }
                      }
                      //wait(20);
                    }
                    

                    Now the relay changes state as soon as I push the button and keeps the state until I push the button again.

                    Because my inputs for the push buttons are ground when pushed I used

                    if ( value == LOW) 
                    

                    This way the relay would turn on immediately when I push the button and not wait until I let go of the button.

                    Стоян ГеоргиевС Offline
                    Стоян ГеоргиевС Offline
                    Стоян Георгиев
                    wrote on last edited by
                    #44

                    @korttoma I used this sketch but my vera founds only 1 device and i have no idea why.

                    korttomaK 1 Reply Last reply
                    0
                    • Стоян ГеоргиевС Стоян Георгиев

                      @korttoma I used this sketch but my vera founds only 1 device and i have no idea why.

                      korttomaK Offline
                      korttomaK Offline
                      korttoma
                      Hero Member
                      wrote on last edited by
                      #45

                      @Стоян-Георгиев please post the complete sketch along with info about MySensors library version you are using.

                      • Tomas
                      1 Reply Last reply
                      0
                      Reply
                      • Reply as topic
                      Log in to reply
                      • Oldest to Newest
                      • Newest to Oldest
                      • Most Votes


                      21

                      Online

                      11.7k

                      Users

                      11.2k

                      Topics

                      113.1k

                      Posts


                      Copyright 2025 TBD   |   Forum Guidelines   |   Privacy Policy   |   Terms of Service
                      • Login

                      • Don't have an account? Register

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • MySensors
                      • OpenHardware.io
                      • Categories
                      • Recent
                      • Tags
                      • Popular