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. Development
  3. Multi Button Relay Sketch

Multi Button Relay Sketch

Scheduled Pinned Locked Moved Development
69 Posts 12 Posters 25.4k Views 18 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.
  • Boots33B Offline
    Boots33B Offline
    Boots33
    Hero Member
    wrote on last edited by Boots33
    #49

    Guys I feel this thread has wandered a long way from the original topic and has taken up a lot of time. i really don't think there is a lot to be gained by turning the fairly simple relay sketch into what you now desire.

    Even with the changes it still will not work if it boots up and can't find the gateway.

    I am posting a final sketch which you may like to try, again it is untested so you may still need to work on it. I hope you understand I have a few of my own uncompleted projects that I want to get back to with the limited free time I have. Good luck with your MySensors journey.

    #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;
    }
    
    
    if (isTransportOK()){
       // put code to execute when connection is available here
        connectionPresent();
    
      } 
      else {
       // put code to execute when no connection is available here
       connectionLost();
      }
    
      
    }
    
    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());
      }
    }
    
    
    
    void connectionPresent() {
    // put code to execute when connection is available here
         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 connectionLost() {
    
       // put code to execute when no connection is available here
        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
        send(msgA.set(stateA ? false : true), false); // Send new state with no request for ack
        stateA = stateA ? false : true;               // invert the state
         digitalWrite(relayPinA, stateA ? RELAY_ON : RELAY_OFF);  // toggle the relay
      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
        send(msgB.set(stateB ? false : true), false); // Send new state with no request for ack
        stateB = stateB ? false : true;                // invert the state
         digitalWrite(relayPinB, stateB ? RELAY_ON : RELAY_OFF);  // toggle the relay
        
      oldValueB = valueB;
      }
    }
    
    
    rayanR 2 Replies Last reply
    0
    • pepsonP Offline
      pepsonP Offline
      pepson
      wrote on last edited by
      #50

      Still not working correct. After lost connection with gateway and then change status , after connection restore , but status is still not update in Domoticz. Still show before lost connection.

      1 Reply Last reply
      0
      • Boots33B Boots33

        Guys I feel this thread has wandered a long way from the original topic and has taken up a lot of time. i really don't think there is a lot to be gained by turning the fairly simple relay sketch into what you now desire.

        Even with the changes it still will not work if it boots up and can't find the gateway.

        I am posting a final sketch which you may like to try, again it is untested so you may still need to work on it. I hope you understand I have a few of my own uncompleted projects that I want to get back to with the limited free time I have. Good luck with your MySensors journey.

        #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;
        }
        
        
        if (isTransportOK()){
           // put code to execute when connection is available here
            connectionPresent();
        
          } 
          else {
           // put code to execute when no connection is available here
           connectionLost();
          }
        
          
        }
        
        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());
          }
        }
        
        
        
        void connectionPresent() {
        // put code to execute when connection is available here
             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 connectionLost() {
        
           // put code to execute when no connection is available here
            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
            send(msgA.set(stateA ? false : true), false); // Send new state with no request for ack
            stateA = stateA ? false : true;               // invert the state
             digitalWrite(relayPinA, stateA ? RELAY_ON : RELAY_OFF);  // toggle the relay
          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
            send(msgB.set(stateB ? false : true), false); // Send new state with no request for ack
            stateB = stateB ? false : true;                // invert the state
             digitalWrite(relayPinB, stateB ? RELAY_ON : RELAY_OFF);  // toggle the relay
            
          oldValueB = valueB;
          }
        }
        
        
        rayanR Offline
        rayanR Offline
        rayan
        wrote on last edited by rayan
        #51
        This post is deleted!
        1 Reply Last reply
        0
        • Boots33B Boots33

          Guys I feel this thread has wandered a long way from the original topic and has taken up a lot of time. i really don't think there is a lot to be gained by turning the fairly simple relay sketch into what you now desire.

          Even with the changes it still will not work if it boots up and can't find the gateway.

          I am posting a final sketch which you may like to try, again it is untested so you may still need to work on it. I hope you understand I have a few of my own uncompleted projects that I want to get back to with the limited free time I have. Good luck with your MySensors journey.

          #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;
          }
          
          
          if (isTransportOK()){
             // put code to execute when connection is available here
              connectionPresent();
          
            } 
            else {
             // put code to execute when no connection is available here
             connectionLost();
            }
          
            
          }
          
          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());
            }
          }
          
          
          
          void connectionPresent() {
          // put code to execute when connection is available here
               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 connectionLost() {
          
             // put code to execute when no connection is available here
              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
              send(msgA.set(stateA ? false : true), false); // Send new state with no request for ack
              stateA = stateA ? false : true;               // invert the state
               digitalWrite(relayPinA, stateA ? RELAY_ON : RELAY_OFF);  // toggle the relay
            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
              send(msgB.set(stateB ? false : true), false); // Send new state with no request for ack
              stateB = stateB ? false : true;                // invert the state
               digitalWrite(relayPinB, stateB ? RELAY_ON : RELAY_OFF);  // toggle the relay
              
            oldValueB = valueB;
            }
          }
          
          
          rayanR Offline
          rayanR Offline
          rayan
          wrote on last edited by
          #52

          @Boots33
          hi my friend.
          i use your sketch and thank you.but there is a problem.
          sketchs in site , when relay is fail , when i send command , so show to me "Error sending switch command, check device/hardware !" but your sketch dont show this error. so i dont understand relay is fail or no , when we are out home. can you fix this ?

          1 Reply Last reply
          0
          • korttomaK korttoma

            Here is an example that I'm using with 4 relays and 4 monostable buttons:

            // Enable debug prints to serial monitor
            #define MY_DEBUG
            
            // Enable and select radio type attached
            #define MY_RADIO_NRF24
            
            #define SN "RelayButtonArray"
            #define SV "1.0"
            
            #include <MySensors.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 4                     //2-4
            const int relayPin[] = {14, 15, 16, 17};       //  switch around pins to your desire
            const int buttonPin[] = {6, 7, 4, 5};   //  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 before() {
              for (int sensor=1, pin=RELAY_1; sensor<=NUMBER_OF_RELAYS;sensor++, pin++) {
                // Then set relay pins in output mode
                pinMode(pin, OUTPUT);
                // Set relay to last known state (using eeprom storage)
                digitalWrite(pin, loadState(sensor)?RELAY_ON:RELAY_OFF);
              }
              }*/
            
            void setup() {
              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(30);
                wait(50);
              }
            }
            
            void presentation()
            {
              // Send the sketch version information to the gateway and Controller
              sendSketchInfo(SN, SV);
            
              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()) {
                  
                  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);
            }
            
            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);
            }
            
            breimannB Offline
            breimannB Offline
            breimann
            wrote on last edited by
            #53

            @korttoma love this sketch. Used it for a dual LED strip light controller for our loft where our kids sleep - daughter on one side and boys on the other, both with LED strips (RGB) i installed. This way we can turn them on or off remotely without having to climb up there!!

            Worked great. Thankyou for sharing.

            1 Reply Last reply
            1
            • M Offline
              M Offline
              moskovskiy82
              wrote on last edited by
              #54

              Anybody has a sketch where multiple buttons are put up on single wire and voltage drop is used to distinguish between them?

              1 Reply Last reply
              0
              • nieatyN Offline
                nieatyN Offline
                nieaty
                wrote on last edited by
                #55
                This post is deleted!
                1 Reply Last reply
                1
                • pepsonP Offline
                  pepsonP Offline
                  pepson
                  wrote on last edited by
                  #56

                  Hi
                  Has anybody solution how resolved problem update status when connection with gateway is not available and then come back connection with gateway?

                  1 Reply Last reply
                  0
                  • pepsonP Offline
                    pepsonP Offline
                    pepson
                    wrote on last edited by
                    #57

                    Hi
                    Has anybody solution how resolved problem update status when connection with gateway is not available and then come back connection with gateway?

                    Boots33B 1 Reply Last reply
                    0
                    • pepsonP pepson

                      Hi
                      Has anybody solution how resolved problem update status when connection with gateway is not available and then come back connection with gateway?

                      Boots33B Offline
                      Boots33B Offline
                      Boots33
                      Hero Member
                      wrote on last edited by
                      #58

                      @pepson have a look at this Synchronising Light switch

                      1 Reply Last reply
                      0
                      • pepsonP Offline
                        pepsonP Offline
                        pepson
                        wrote on last edited by
                        #59

                        I try sketch from your link but i test and the same issu.
                        I enable relay, then disable GATEWAY MySensors on DOmoticz and then change status relay to DISABLE by button. Then enable Gateway on Domoticz and still in domoticz show that relay is ENABLED. Not update status that i manual DISABLE relay by button.

                        Boots33B 1 Reply Last reply
                        0
                        • pepsonP Offline
                          pepsonP Offline
                          pepson
                          wrote on last edited by
                          #60

                          This is my sketch with my radio and this not working... no sync status after lost connection with gateway and after come back gateway...

                          /*
                             Relay with button sketch
                             modified to work with no uplink
                             to gateway and try to maintain sync to controller
                          */
                          
                          
                          #define MY_DEBUG                               // Enable debug prints to serial monitor
                          
                          #define MY_RADIO_RFM69
                          #define MY_RFM69_FREQUENCY RF69_868MHZ
                          #define MY_IS_RFM69HW                         // Enable and select radio type attached
                          
                          #define MY_TRANSPORT_WAIT_READY_MS 5000        //set how long to wait for transport ready in milliseconds
                          
                          // Enabled repeater feature for this node
                          #define MY_REPEATER_FEATURE
                          
                          // Node id defaults to AUTO (tries to fetch id from controller)
                          #define MY_NODE_ID 10
                          
                          #include <MySensors.h>
                          #include <Bounce2.h>
                          
                          #define RELAY_PIN  5      // Arduino Digital I/O pin number for relay 
                          #define BUTTON_PIN  3     // Arduino Digital I/O pin number for button 
                          #define CHILD_ID 1        // Id of the sensor child
                          #define RELAY_ON 0
                          #define RELAY_OFF 1
                          
                          Bounce debouncer = Bounce();
                          int oldValue = 0;
                          bool uplinkAvailable = true;
                          bool state = false;
                          bool requestState;
                          bool firstStart = true;
                          unsigned long uplinkCheckTime ;                // holder for uplink checks
                          unsigned long uplinkCheckPeriod = 30*1000;     // time between checks for uplink in milliseconds
                          unsigned long returnWait = 1500;               // how long to wait for return from controller in milliseconds
                          MyMessage msg(CHILD_ID, V_STATUS);
                          
                          void setup(){
                            pinMode(BUTTON_PIN, INPUT_PULLUP);           // Setup the button pin, Activate internal pull-up
                            
                            debouncer.attach(BUTTON_PIN);                // After setting up the button, setup debouncer
                            debouncer.interval(5);
                          
                            pinMode(RELAY_PIN, OUTPUT);                 // set relay pin in output mode
                            digitalWrite(RELAY_PIN, RELAY_OFF);         // Make sure relay is off when starting up
                          }
                          
                          void presentation()  {
                            // Send the sketch version information to the gateway and Controller
                            sendSketchInfo("Relay & Button", "1.0");
                          
                            // Register all sensors to gw (they will be created as child devices)
                            present(CHILD_ID, S_BINARY);
                          }
                          
                          
                          void loop(){
                            if (firstStart) {                            // this code is only run once at startup
                              Serial.println("First run started");
                              if (request( CHILD_ID, V_STATUS)) {       // request the current state of the switch on the controller and check that an ack was received
                                Serial.println("uplink available");
                                wait (returnWait);                      //wait needed to allow request to return from controller
                                Serial.print("controller state --- ");
                                Serial.println(requestState);
                                if (requestState != state) {           // check that controller is corectly showing the current relay state
                                  send(msg.set(state), false);         // notify controller of current state
                                }
                              }
                              else {
                                Serial.println("uplink not available");
                                uplinkAvailable = false;               // no uplink established
                                uplinkCheckTime = millis();
                              }
                              firstStart = false;                     // set firstStart flag false to prevent code from running again
                            }
                          
                            debouncer.update();
                            int value = debouncer.read();                               // Get the update value
                            if (value != oldValue && value == 0) {                      // check for new button push
                              state =  !state;                                          // Toggle the state
                              digitalWrite(RELAY_PIN, state ? RELAY_ON : RELAY_OFF);    // switch the relay to the new state
                              if (!send(msg.set(state), true)) {                        //Attempt to notify controller of changed state
                                Serial.println("uplink not available");
                                uplinkAvailable = false;                                // no uplink available
                                uplinkCheckTime = millis();                             
                              }
                            }
                           oldValue = value;
                          
                            if (!uplinkAvailable && (millis() - uplinkCheckTime > uplinkCheckPeriod) ) {       // test to see if function should be called
                              uplinkCheck();                                                                  // call uplink checking function
                            }
                          
                          }
                          
                          /*-------------------start of functions--------------------------*/
                          
                          void receive(const MyMessage &message) {
                            if (message.type == V_STATUS) {                                   // check to see if incoming message is for a switch
                              switch (message.getCommand()) {                                 // message.getCommand will give us the command type of the incomming message
                                case C_SET:                                                   //message is a set command  from controller to update relay state
                                  state = message.getBool();                                  // get the new state
                                  digitalWrite(RELAY_PIN, state ? RELAY_ON : RELAY_OFF);      // switch relay to new state
                                  uplinkAvailable = true;                                     //  uplink established
                                  /*---- Write some debug info----*/
                                  Serial.print("Incoming change for sensor:");
                                  Serial.print(message.sensor);
                                  Serial.print(", New status: ");
                                  Serial.println(message.getBool());
                                  break;
                                case C_REQ:                                               // message is a returning request from controller
                                  requestState = message.getBool();                       // update requestState with returning state
                                  break;
                              }
                            }
                          }
                          
                          void uplinkCheck() {
                            if (request( CHILD_ID, V_STATUS)) {         // request the current state of the switch on the controller and check that the request was succsessful
                              Serial.println("uplink re-established");
                              wait (returnWait);                        //wait needed to allow request to return from controller
                              if (requestState != state) {              // check that controller is corectly showing the current relay state
                                send(msg.set(state), false);            // notify controller of current state no ack
                                uplinkAvailable = true;                 //  uplink established
                              }
                            }
                            uplinkCheckTime = millis();                // reset the checktime
                            Serial.println("uplinkchecktime reset");
                          }```
                          1 Reply Last reply
                          0
                          • pepsonP pepson

                            I try sketch from your link but i test and the same issu.
                            I enable relay, then disable GATEWAY MySensors on DOmoticz and then change status relay to DISABLE by button. Then enable Gateway on Domoticz and still in domoticz show that relay is ENABLED. Not update status that i manual DISABLE relay by button.

                            Boots33B Offline
                            Boots33B Offline
                            Boots33
                            Hero Member
                            wrote on last edited by
                            #61

                            @pepson said in Multi Button Relay Sketch:

                            I try sketch from your link but i test and the same issu.
                            I enable relay, then disable GATEWAY MySensors on DOmoticz and then change status relay to DISABLE by button. Then enable Gateway on Domoticz and still in domoticz show that relay is ENABLED. Not update status that i manual DISABLE relay by button.

                            As far as I know there is no direct way to test for a connection all the way to the controller in MySensors 2.1.

                            My sketch for the synchronising switch uses the presence of the gateway as the test, this has been adequate for my needs. My controller and gateway are both powered from the same place so they both go down if power is lost.

                            I have found Domoticz very stable and have not had any issues with it at all so am wondering why Dometicz seems to be giving you problems. is it powered from a different supply to your gateway?

                            I do have another sketch that uses requestTime as a way of checking for the controller that may be of use to you. it needs a little cleaning up first, so will have a look at it when i get a chance and post it for you to try.

                            pepsonP 1 Reply Last reply
                            0
                            • Boots33B Boots33

                              @pepson said in Multi Button Relay Sketch:

                              I try sketch from your link but i test and the same issu.
                              I enable relay, then disable GATEWAY MySensors on DOmoticz and then change status relay to DISABLE by button. Then enable Gateway on Domoticz and still in domoticz show that relay is ENABLED. Not update status that i manual DISABLE relay by button.

                              As far as I know there is no direct way to test for a connection all the way to the controller in MySensors 2.1.

                              My sketch for the synchronising switch uses the presence of the gateway as the test, this has been adequate for my needs. My controller and gateway are both powered from the same place so they both go down if power is lost.

                              I have found Domoticz very stable and have not had any issues with it at all so am wondering why Dometicz seems to be giving you problems. is it powered from a different supply to your gateway?

                              I do have another sketch that uses requestTime as a way of checking for the controller that may be of use to you. it needs a little cleaning up first, so will have a look at it when i get a chance and post it for you to try.

                              pepsonP Offline
                              pepsonP Offline
                              pepson
                              wrote on last edited by pepson
                              #62

                              @boots33
                              Gateway and Node has the same POWER. But Node start faster than Domoticz with Gateway.

                              But in my gateway is not tested when i use radio RFM69HW ?
                              Problem is when Domoticz with gateway down power, (also NODE down power). When power come back and under start Domoticz i change status on relay it is not show in domoticz because NODE with relay start faster than DOmoticz with Gateway.
                              Also when i disable power from Domoticz with ENABLE RELAY . but NODe has still power and change relay to DISABLE and then again POWER ON Domoticz. After run Domoticz not show actual status my Relay because GATWAY was disable when i change status relay.

                              Explaine me more please for what is in your sketch SYNCHRONISING ? What does it give us?

                              Boots33B 1 Reply Last reply
                              0
                              • pepsonP pepson

                                @boots33
                                Gateway and Node has the same POWER. But Node start faster than Domoticz with Gateway.

                                But in my gateway is not tested when i use radio RFM69HW ?
                                Problem is when Domoticz with gateway down power, (also NODE down power). When power come back and under start Domoticz i change status on relay it is not show in domoticz because NODE with relay start faster than DOmoticz with Gateway.
                                Also when i disable power from Domoticz with ENABLE RELAY . but NODe has still power and change relay to DISABLE and then again POWER ON Domoticz. After run Domoticz not show actual status my Relay because GATWAY was disable when i change status relay.

                                Explaine me more please for what is in your sketch SYNCHRONISING ? What does it give us?

                                Boots33B Offline
                                Boots33B Offline
                                Boots33
                                Hero Member
                                wrote on last edited by
                                #63

                                @pepson said in Multi Button Relay Sketch:

                                because NODE with relay start faster than DOmoticz with Gateway.

                                One solution could be to add a delay to your node and gateway sketches. This could just be run once as the node/gateway boots up thus giving Domoticz time to boot.

                                Also when i disable power from Domoticz with ENABLE RELAY . but NODe has still power and change relay to DISABLE and then again POWER ON Domoticz. After run Domoticz not show actual status my Relay because GATWAY was disable >when i change status relay.

                                As I have said earlier all MySensors 2.1 checks for uplink available are only checking for a connection to the gateway not all the way to the controller. So you can turn the controller on and off as often as you like and the node will not know it is not there. As long as the gateway is present the node will show the uplink as available.

                                Explaine me more please for what is in your sketch SYNCHRONISING ? What does it give us?

                                My original syncing switch sketch that i pointed you to above will work for most normal situations where the controller and gateway are on the same power supply. If you add the delay I have mentioned to your Gateway/node then that will allow the controller to boot first when returning from a power outage.

                                When you are turning off the controller by itself I do not think that is a true real world test, if the gateway and controller share the same power supply then this is not likely to happen.

                                In any case you may need to implement some form of code on Dometicz to push the occurrence of a controller reboot to your nodes. The nodes will not detect a missing controller unless your nodes are constantly pinging the controller to see if it is there.

                                I do have the other sketch using a time request to check for the presence of the controller, I will post that code in my Synchronising Light switch thread for you to try.

                                1 Reply Last reply
                                0
                                • pepsonP Offline
                                  pepsonP Offline
                                  pepson
                                  wrote on last edited by
                                  #64

                                  @boots33 said in Multi Button Relay Sketch:

                                  When you are turning off the controller by itself I do not think that is a true real world test, if the gateway and controller share the same power supply then this is not likely to happen.
                                  In any case you may need to implement some form of code on Dometicz to push the occurrence of a controller reboot to your nodes. The nodes will not detect a missing controller unless your nodes are constantly pinging the controller to see if it is there.
                                  I do have the other sketch using a time request to check for the presence of the controller, I will post that code in my Synchronising Light switch thread for you to try.

                                  Ok i wait for your sketch using a time request...

                                  I have Domoticz on Raspberry Pi3 and to this Raspberry i have connected Gateway MySensors on Arduino Nano by USB from Rasspberry.

                                  Can you ready code for delay start gateway and node ?

                                  And tell me when i restart Gateway , it ceck status NODE ? How i can restart gateway on my raspberry without disable raspberry and domoticz ?

                                  1 Reply Last reply
                                  0
                                  • Pictor LallemandP Offline
                                    Pictor LallemandP Offline
                                    Pictor Lallemand
                                    wrote on last edited by
                                    #65

                                    hello,

                                    I made this code it save state in EEPROM after reboot it load previous state saved .
                                    I share you my sketch is made for 4 relays an 4 momentary button.

                                    // 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_PIN0  5  // Arduino Digital I/O pin number for relay 
                                    #define RELAY_PIN1  6
                                    #define RELAY_PIN2  7
                                    #define RELAY_PIN3  8
                                    #define BUTTON_PIN0  A0  // Arduino Digital I/O pin number for button 
                                    #define BUTTON_PIN1  A1  // Arduino Digital I/O pin number for button 
                                    #define BUTTON_PIN2  A2  // Arduino Digital I/O pin number for button 
                                    #define BUTTON_PIN3  A3  // Arduino Digital I/O pin number for button 
                                    
                                    #define CHILD0_ID 50   // Id of the sensor child
                                    #define CHILD1_ID 51   // Id of the sensor child
                                    #define CHILD2_ID 52   // Id of the sensor child
                                    #define CHILD3_ID 53   // Id of the sensor child
                                    
                                    #define RELAY_ON 1
                                    #define RELAY_OFF 0
                                    
                                    Bounce debouncerA = Bounce();
                                    Bounce debouncerB = Bounce();
                                    Bounce debouncerC = Bounce();
                                    Bounce debouncerD = Bounce();
                                    
                                    int oldValueA = 0;
                                    int oldValueB = 0;
                                    int oldValueC = 0;
                                    int oldValueD = 0;
                                    
                                    bool stateA;
                                    bool stateB;
                                    bool stateC;
                                    bool stateD;
                                    
                                    MyMessage msgA(CHILD0_ID, V_LIGHT);
                                    MyMessage msgB(CHILD1_ID, V_LIGHT);
                                    MyMessage msgC(CHILD2_ID, V_LIGHT);
                                    MyMessage msgD(CHILD3_ID, V_LIGHT);
                                    
                                    void setup()
                                    {
                                      // Setup the button
                                      pinMode(BUTTON_PIN0, INPUT_PULLUP);
                                      pinMode(BUTTON_PIN1, INPUT_PULLUP);
                                      pinMode(BUTTON_PIN2, INPUT_PULLUP);
                                      pinMode(BUTTON_PIN3, INPUT_PULLUP);
                                    
                                      // After setting up the button, setup debouncer
                                      debouncerA.attach(BUTTON_PIN0);
                                      debouncerA.interval(5);
                                      debouncerB.attach(BUTTON_PIN1);
                                      debouncerB.interval(5);
                                      debouncerC.attach(BUTTON_PIN2);
                                      debouncerC.interval(5);
                                      debouncerD.attach(BUTTON_PIN3);
                                      debouncerD.interval(5);
                                    
                                      // Make sure relays are off when starting up
                                      digitalWrite(RELAY_PIN0, RELAY_OFF);
                                      digitalWrite(RELAY_PIN1, RELAY_OFF);
                                      digitalWrite(RELAY_PIN2, RELAY_OFF);
                                      digitalWrite(RELAY_PIN3, RELAY_OFF);
                                      // Then set relay pins in output mode
                                      pinMode(RELAY_PIN0, OUTPUT);
                                      pinMode(RELAY_PIN1, OUTPUT);
                                      pinMode(RELAY_PIN2, OUTPUT);
                                      pinMode(RELAY_PIN3, OUTPUT);
                                    
                                    
                                    
                                      // Set relay to last known state (using eeprom storage)
                                      stateA = loadState(CHILD0_ID);
                                      digitalWrite(RELAY_PIN0, stateA ? RELAY_ON : RELAY_OFF);
                                    
                                      stateB = loadState(CHILD1_ID);
                                      digitalWrite(RELAY_PIN1, stateB ? RELAY_ON : RELAY_OFF);
                                    
                                      stateC = loadState(CHILD2_ID);
                                      digitalWrite(RELAY_PIN2, stateC ? RELAY_ON : RELAY_OFF);
                                    
                                      stateD = loadState(CHILD3_ID);
                                      digitalWrite(RELAY_PIN3, stateD ? RELAY_ON : RELAY_OFF);
                                    }
                                    
                                    void presentation()  {
                                      // Send the sketch version information to the gateway and Controller
                                      sendSketchInfo("4 Relay & button", "1.0");
                                    
                                      // Register all sensors to gw (they will be created as child devices)
                                      present(CHILD0_ID, S_LIGHT);
                                      present(CHILD1_ID, S_LIGHT);
                                      present(CHILD2_ID, S_LIGHT);
                                      present(CHILD3_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;
                                    
                                      debouncerC.update();
                                      // Get the update value
                                      int valueC = debouncerC.read();
                                      if (valueC != oldValueC && valueC == 0) {
                                        send(msgC.set(stateC ? false : true), true); // Send new state and request ack back
                                      }
                                      oldValueC = valueC;
                                    
                                      debouncerD.update();
                                      // Get the update value
                                      int valueD = debouncerD.read();
                                      if (valueD != oldValueD && valueD == 0) {
                                        send(msgD.set(stateD ? false : true), true); // Send new state and request ack back
                                      }
                                      oldValueD = valueD;
                                    }
                                    
                                    void receive(const MyMessage &message) {
                                      // We only expect one type of message from controller. But we better check anyway.
                                      if (message.type == V_LIGHT) {
                                        
                                        switch (message.sensor) {
                                          case CHILD0_ID:
                                            stateA = message.getBool();
                                            digitalWrite(RELAY_PIN0, stateA ? RELAY_ON : RELAY_OFF);
                                            saveState(CHILD0_ID, stateA);
                                            break;
                                            
                                          case CHILD1_ID:
                                            stateB = message.getBool();
                                            digitalWrite(RELAY_PIN1, stateB ? RELAY_ON : RELAY_OFF);
                                            saveState(CHILD1_ID, stateB);
                                            break;
                                    
                                          case CHILD2_ID:
                                            stateC = message.getBool();
                                            digitalWrite(RELAY_PIN2, stateC ? RELAY_ON : RELAY_OFF);
                                            saveState(CHILD2_ID, stateC);
                                            break;
                                            
                                          case CHILD3_ID:
                                            stateD = message.getBool();
                                            digitalWrite(RELAY_PIN3, stateD ? RELAY_ON : RELAY_OFF);
                                            saveState(CHILD3_ID, stateD);
                                            break;
                                        }
                                        // Write some debug info
                                        Serial.print("Incoming change for sensor:");
                                        Serial.print(message.sensor);
                                        Serial.print(", New status: ");
                                        Serial.println(message.getBool());
                                      }
                                    }
                                    
                                    rejoe2R pepsonP 2 Replies Last reply
                                    0
                                    • Pictor LallemandP Pictor Lallemand

                                      hello,

                                      I made this code it save state in EEPROM after reboot it load previous state saved .
                                      I share you my sketch is made for 4 relays an 4 momentary button.

                                      // 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_PIN0  5  // Arduino Digital I/O pin number for relay 
                                      #define RELAY_PIN1  6
                                      #define RELAY_PIN2  7
                                      #define RELAY_PIN3  8
                                      #define BUTTON_PIN0  A0  // Arduino Digital I/O pin number for button 
                                      #define BUTTON_PIN1  A1  // Arduino Digital I/O pin number for button 
                                      #define BUTTON_PIN2  A2  // Arduino Digital I/O pin number for button 
                                      #define BUTTON_PIN3  A3  // Arduino Digital I/O pin number for button 
                                      
                                      #define CHILD0_ID 50   // Id of the sensor child
                                      #define CHILD1_ID 51   // Id of the sensor child
                                      #define CHILD2_ID 52   // Id of the sensor child
                                      #define CHILD3_ID 53   // Id of the sensor child
                                      
                                      #define RELAY_ON 1
                                      #define RELAY_OFF 0
                                      
                                      Bounce debouncerA = Bounce();
                                      Bounce debouncerB = Bounce();
                                      Bounce debouncerC = Bounce();
                                      Bounce debouncerD = Bounce();
                                      
                                      int oldValueA = 0;
                                      int oldValueB = 0;
                                      int oldValueC = 0;
                                      int oldValueD = 0;
                                      
                                      bool stateA;
                                      bool stateB;
                                      bool stateC;
                                      bool stateD;
                                      
                                      MyMessage msgA(CHILD0_ID, V_LIGHT);
                                      MyMessage msgB(CHILD1_ID, V_LIGHT);
                                      MyMessage msgC(CHILD2_ID, V_LIGHT);
                                      MyMessage msgD(CHILD3_ID, V_LIGHT);
                                      
                                      void setup()
                                      {
                                        // Setup the button
                                        pinMode(BUTTON_PIN0, INPUT_PULLUP);
                                        pinMode(BUTTON_PIN1, INPUT_PULLUP);
                                        pinMode(BUTTON_PIN2, INPUT_PULLUP);
                                        pinMode(BUTTON_PIN3, INPUT_PULLUP);
                                      
                                        // After setting up the button, setup debouncer
                                        debouncerA.attach(BUTTON_PIN0);
                                        debouncerA.interval(5);
                                        debouncerB.attach(BUTTON_PIN1);
                                        debouncerB.interval(5);
                                        debouncerC.attach(BUTTON_PIN2);
                                        debouncerC.interval(5);
                                        debouncerD.attach(BUTTON_PIN3);
                                        debouncerD.interval(5);
                                      
                                        // Make sure relays are off when starting up
                                        digitalWrite(RELAY_PIN0, RELAY_OFF);
                                        digitalWrite(RELAY_PIN1, RELAY_OFF);
                                        digitalWrite(RELAY_PIN2, RELAY_OFF);
                                        digitalWrite(RELAY_PIN3, RELAY_OFF);
                                        // Then set relay pins in output mode
                                        pinMode(RELAY_PIN0, OUTPUT);
                                        pinMode(RELAY_PIN1, OUTPUT);
                                        pinMode(RELAY_PIN2, OUTPUT);
                                        pinMode(RELAY_PIN3, OUTPUT);
                                      
                                      
                                      
                                        // Set relay to last known state (using eeprom storage)
                                        stateA = loadState(CHILD0_ID);
                                        digitalWrite(RELAY_PIN0, stateA ? RELAY_ON : RELAY_OFF);
                                      
                                        stateB = loadState(CHILD1_ID);
                                        digitalWrite(RELAY_PIN1, stateB ? RELAY_ON : RELAY_OFF);
                                      
                                        stateC = loadState(CHILD2_ID);
                                        digitalWrite(RELAY_PIN2, stateC ? RELAY_ON : RELAY_OFF);
                                      
                                        stateD = loadState(CHILD3_ID);
                                        digitalWrite(RELAY_PIN3, stateD ? RELAY_ON : RELAY_OFF);
                                      }
                                      
                                      void presentation()  {
                                        // Send the sketch version information to the gateway and Controller
                                        sendSketchInfo("4 Relay & button", "1.0");
                                      
                                        // Register all sensors to gw (they will be created as child devices)
                                        present(CHILD0_ID, S_LIGHT);
                                        present(CHILD1_ID, S_LIGHT);
                                        present(CHILD2_ID, S_LIGHT);
                                        present(CHILD3_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;
                                      
                                        debouncerC.update();
                                        // Get the update value
                                        int valueC = debouncerC.read();
                                        if (valueC != oldValueC && valueC == 0) {
                                          send(msgC.set(stateC ? false : true), true); // Send new state and request ack back
                                        }
                                        oldValueC = valueC;
                                      
                                        debouncerD.update();
                                        // Get the update value
                                        int valueD = debouncerD.read();
                                        if (valueD != oldValueD && valueD == 0) {
                                          send(msgD.set(stateD ? false : true), true); // Send new state and request ack back
                                        }
                                        oldValueD = valueD;
                                      }
                                      
                                      void receive(const MyMessage &message) {
                                        // We only expect one type of message from controller. But we better check anyway.
                                        if (message.type == V_LIGHT) {
                                          
                                          switch (message.sensor) {
                                            case CHILD0_ID:
                                              stateA = message.getBool();
                                              digitalWrite(RELAY_PIN0, stateA ? RELAY_ON : RELAY_OFF);
                                              saveState(CHILD0_ID, stateA);
                                              break;
                                              
                                            case CHILD1_ID:
                                              stateB = message.getBool();
                                              digitalWrite(RELAY_PIN1, stateB ? RELAY_ON : RELAY_OFF);
                                              saveState(CHILD1_ID, stateB);
                                              break;
                                      
                                            case CHILD2_ID:
                                              stateC = message.getBool();
                                              digitalWrite(RELAY_PIN2, stateC ? RELAY_ON : RELAY_OFF);
                                              saveState(CHILD2_ID, stateC);
                                              break;
                                              
                                            case CHILD3_ID:
                                              stateD = message.getBool();
                                              digitalWrite(RELAY_PIN3, stateD ? RELAY_ON : RELAY_OFF);
                                              saveState(CHILD3_ID, stateD);
                                              break;
                                          }
                                          // Write some debug info
                                          Serial.print("Incoming change for sensor:");
                                          Serial.print(message.sensor);
                                          Serial.print(", New status: ");
                                          Serial.println(message.getBool());
                                        }
                                      }
                                      
                                      rejoe2R Offline
                                      rejoe2R Offline
                                      rejoe2
                                      wrote on last edited by
                                      #66

                                      @pictor-lallemand You may also have a look at the sketch @korttoma published in post #33. It does exactly the same than yours, but in case one needs more or less relays, it's much easier to adopt :grinning: .

                                      Controller: FHEM; MySensors: 2.3.1, RS485,nRF24,RFM69, serial Gateways

                                      1 Reply Last reply
                                      0
                                      • korttomaK korttoma

                                        Here is an example that I'm using with 4 relays and 4 monostable buttons:

                                        // Enable debug prints to serial monitor
                                        #define MY_DEBUG
                                        
                                        // Enable and select radio type attached
                                        #define MY_RADIO_NRF24
                                        
                                        #define SN "RelayButtonArray"
                                        #define SV "1.0"
                                        
                                        #include <MySensors.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 4                     //2-4
                                        const int relayPin[] = {14, 15, 16, 17};       //  switch around pins to your desire
                                        const int buttonPin[] = {6, 7, 4, 5};   //  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 before() {
                                          for (int sensor=1, pin=RELAY_1; sensor<=NUMBER_OF_RELAYS;sensor++, pin++) {
                                            // Then set relay pins in output mode
                                            pinMode(pin, OUTPUT);
                                            // Set relay to last known state (using eeprom storage)
                                            digitalWrite(pin, loadState(sensor)?RELAY_ON:RELAY_OFF);
                                          }
                                          }*/
                                        
                                        void setup() {
                                          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(30);
                                            wait(50);
                                          }
                                        }
                                        
                                        void presentation()
                                        {
                                          // Send the sketch version information to the gateway and Controller
                                          sendSketchInfo(SN, SV);
                                        
                                          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()) {
                                              
                                              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);
                                        }
                                        
                                        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);
                                        }
                                        
                                        N Offline
                                        N Offline
                                        nelsonov
                                        wrote on last edited by
                                        #67

                                        @korttoma Two years later.... I just wanted to say that your sketch is elegant and beautiful. Using arrays is an idea I had as well, but I was just starting to write something when I thought about looking to see if someone had already done it. You saved me days of yelling at the monitor trying work it out for myself. You should consider making a topic out of this script.

                                        https://keybase.io/nelsonov

                                        1 Reply Last reply
                                        0
                                        • Pictor LallemandP Pictor Lallemand

                                          hello,

                                          I made this code it save state in EEPROM after reboot it load previous state saved .
                                          I share you my sketch is made for 4 relays an 4 momentary button.

                                          // 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_PIN0  5  // Arduino Digital I/O pin number for relay 
                                          #define RELAY_PIN1  6
                                          #define RELAY_PIN2  7
                                          #define RELAY_PIN3  8
                                          #define BUTTON_PIN0  A0  // Arduino Digital I/O pin number for button 
                                          #define BUTTON_PIN1  A1  // Arduino Digital I/O pin number for button 
                                          #define BUTTON_PIN2  A2  // Arduino Digital I/O pin number for button 
                                          #define BUTTON_PIN3  A3  // Arduino Digital I/O pin number for button 
                                          
                                          #define CHILD0_ID 50   // Id of the sensor child
                                          #define CHILD1_ID 51   // Id of the sensor child
                                          #define CHILD2_ID 52   // Id of the sensor child
                                          #define CHILD3_ID 53   // Id of the sensor child
                                          
                                          #define RELAY_ON 1
                                          #define RELAY_OFF 0
                                          
                                          Bounce debouncerA = Bounce();
                                          Bounce debouncerB = Bounce();
                                          Bounce debouncerC = Bounce();
                                          Bounce debouncerD = Bounce();
                                          
                                          int oldValueA = 0;
                                          int oldValueB = 0;
                                          int oldValueC = 0;
                                          int oldValueD = 0;
                                          
                                          bool stateA;
                                          bool stateB;
                                          bool stateC;
                                          bool stateD;
                                          
                                          MyMessage msgA(CHILD0_ID, V_LIGHT);
                                          MyMessage msgB(CHILD1_ID, V_LIGHT);
                                          MyMessage msgC(CHILD2_ID, V_LIGHT);
                                          MyMessage msgD(CHILD3_ID, V_LIGHT);
                                          
                                          void setup()
                                          {
                                            // Setup the button
                                            pinMode(BUTTON_PIN0, INPUT_PULLUP);
                                            pinMode(BUTTON_PIN1, INPUT_PULLUP);
                                            pinMode(BUTTON_PIN2, INPUT_PULLUP);
                                            pinMode(BUTTON_PIN3, INPUT_PULLUP);
                                          
                                            // After setting up the button, setup debouncer
                                            debouncerA.attach(BUTTON_PIN0);
                                            debouncerA.interval(5);
                                            debouncerB.attach(BUTTON_PIN1);
                                            debouncerB.interval(5);
                                            debouncerC.attach(BUTTON_PIN2);
                                            debouncerC.interval(5);
                                            debouncerD.attach(BUTTON_PIN3);
                                            debouncerD.interval(5);
                                          
                                            // Make sure relays are off when starting up
                                            digitalWrite(RELAY_PIN0, RELAY_OFF);
                                            digitalWrite(RELAY_PIN1, RELAY_OFF);
                                            digitalWrite(RELAY_PIN2, RELAY_OFF);
                                            digitalWrite(RELAY_PIN3, RELAY_OFF);
                                            // Then set relay pins in output mode
                                            pinMode(RELAY_PIN0, OUTPUT);
                                            pinMode(RELAY_PIN1, OUTPUT);
                                            pinMode(RELAY_PIN2, OUTPUT);
                                            pinMode(RELAY_PIN3, OUTPUT);
                                          
                                          
                                          
                                            // Set relay to last known state (using eeprom storage)
                                            stateA = loadState(CHILD0_ID);
                                            digitalWrite(RELAY_PIN0, stateA ? RELAY_ON : RELAY_OFF);
                                          
                                            stateB = loadState(CHILD1_ID);
                                            digitalWrite(RELAY_PIN1, stateB ? RELAY_ON : RELAY_OFF);
                                          
                                            stateC = loadState(CHILD2_ID);
                                            digitalWrite(RELAY_PIN2, stateC ? RELAY_ON : RELAY_OFF);
                                          
                                            stateD = loadState(CHILD3_ID);
                                            digitalWrite(RELAY_PIN3, stateD ? RELAY_ON : RELAY_OFF);
                                          }
                                          
                                          void presentation()  {
                                            // Send the sketch version information to the gateway and Controller
                                            sendSketchInfo("4 Relay & button", "1.0");
                                          
                                            // Register all sensors to gw (they will be created as child devices)
                                            present(CHILD0_ID, S_LIGHT);
                                            present(CHILD1_ID, S_LIGHT);
                                            present(CHILD2_ID, S_LIGHT);
                                            present(CHILD3_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;
                                          
                                            debouncerC.update();
                                            // Get the update value
                                            int valueC = debouncerC.read();
                                            if (valueC != oldValueC && valueC == 0) {
                                              send(msgC.set(stateC ? false : true), true); // Send new state and request ack back
                                            }
                                            oldValueC = valueC;
                                          
                                            debouncerD.update();
                                            // Get the update value
                                            int valueD = debouncerD.read();
                                            if (valueD != oldValueD && valueD == 0) {
                                              send(msgD.set(stateD ? false : true), true); // Send new state and request ack back
                                            }
                                            oldValueD = valueD;
                                          }
                                          
                                          void receive(const MyMessage &message) {
                                            // We only expect one type of message from controller. But we better check anyway.
                                            if (message.type == V_LIGHT) {
                                              
                                              switch (message.sensor) {
                                                case CHILD0_ID:
                                                  stateA = message.getBool();
                                                  digitalWrite(RELAY_PIN0, stateA ? RELAY_ON : RELAY_OFF);
                                                  saveState(CHILD0_ID, stateA);
                                                  break;
                                                  
                                                case CHILD1_ID:
                                                  stateB = message.getBool();
                                                  digitalWrite(RELAY_PIN1, stateB ? RELAY_ON : RELAY_OFF);
                                                  saveState(CHILD1_ID, stateB);
                                                  break;
                                          
                                                case CHILD2_ID:
                                                  stateC = message.getBool();
                                                  digitalWrite(RELAY_PIN2, stateC ? RELAY_ON : RELAY_OFF);
                                                  saveState(CHILD2_ID, stateC);
                                                  break;
                                                  
                                                case CHILD3_ID:
                                                  stateD = message.getBool();
                                                  digitalWrite(RELAY_PIN3, stateD ? RELAY_ON : RELAY_OFF);
                                                  saveState(CHILD3_ID, stateD);
                                                  break;
                                              }
                                              // Write some debug info
                                              Serial.print("Incoming change for sensor:");
                                              Serial.print(message.sensor);
                                              Serial.print(", New status: ");
                                              Serial.println(message.getBool());
                                            }
                                          }
                                          
                                          pepsonP Offline
                                          pepsonP Offline
                                          pepson
                                          wrote on last edited by
                                          #68

                                          @pictor-lallemand

                                          Hi
                                          I change your sketch to working wirg serial wire gateway on my Arduino Mega 2560 but not working.
                                          Why...
                                          In home assistant found 4 childs number:50, 51, 52, 53 but when try change state relay by button or by Home Assistant , state relay not change. Please look.

                                          
                                          // Enable debug prints to serial monitor
                                          #define MY_DEBUG 
                                          
                                          // Enable serial gateway
                                          #define MY_GATEWAY_SERIAL
                                          
                                          // Define a lower baud rate for Arduino's running on 8 MHz (Arduino Pro Mini 3.3V & SenseBender)
                                          #if F_CPU == 8000000L
                                          #define MY_BAUD_RATE 38400
                                          #endif
                                          
                                          // Enable debug prints to serial monitor
                                          #define MY_DEBUG
                                          
                                          #include <SPI.h>
                                          #include <MySensors.h>
                                          #include <Bounce2.h>
                                          
                                          #define RELAY_PIN0  5  // Arduino Digital I/O pin number for relay 
                                          #define RELAY_PIN1  6
                                          #define RELAY_PIN2  7
                                          #define RELAY_PIN3  8
                                          #define BUTTON_PIN0  A0  // Arduino Digital I/O pin number for button 
                                          #define BUTTON_PIN1  A1  // Arduino Digital I/O pin number for button 
                                          #define BUTTON_PIN2  A2  // Arduino Digital I/O pin number for button 
                                          #define BUTTON_PIN3  A3  // Arduino Digital I/O pin number for button 
                                          
                                          #define CHILD0_ID 50   // Id of the sensor child
                                          #define CHILD1_ID 51   // Id of the sensor child
                                          #define CHILD2_ID 52   // Id of the sensor child
                                          #define CHILD3_ID 53   // Id of the sensor child
                                          
                                          #define RELAY_ON 1
                                          #define RELAY_OFF 0
                                          
                                          Bounce debouncerA = Bounce();
                                          Bounce debouncerB = Bounce();
                                          Bounce debouncerC = Bounce();
                                          Bounce debouncerD = Bounce();
                                          
                                          int oldValueA = 0;
                                          int oldValueB = 0;
                                          int oldValueC = 0;
                                          int oldValueD = 0;
                                          
                                          bool stateA;
                                          bool stateB;
                                          bool stateC;
                                          bool stateD;
                                          
                                          MyMessage msgA(CHILD0_ID, V_LIGHT);
                                          MyMessage msgB(CHILD1_ID, V_LIGHT);
                                          MyMessage msgC(CHILD2_ID, V_LIGHT);
                                          MyMessage msgD(CHILD3_ID, V_LIGHT);
                                          
                                          void setup()
                                          {
                                            // Setup the button
                                            pinMode(BUTTON_PIN0, INPUT_PULLUP);
                                            pinMode(BUTTON_PIN1, INPUT_PULLUP);
                                            pinMode(BUTTON_PIN2, INPUT_PULLUP);
                                            pinMode(BUTTON_PIN3, INPUT_PULLUP);
                                          
                                            // After setting up the button, setup debouncer
                                            debouncerA.attach(BUTTON_PIN0);
                                            debouncerA.interval(5);
                                            debouncerB.attach(BUTTON_PIN1);
                                            debouncerB.interval(5);
                                            debouncerC.attach(BUTTON_PIN2);
                                            debouncerC.interval(5);
                                            debouncerD.attach(BUTTON_PIN3);
                                            debouncerD.interval(5);
                                          
                                            // Make sure relays are off when starting up
                                            digitalWrite(RELAY_PIN0, RELAY_OFF);
                                            digitalWrite(RELAY_PIN1, RELAY_OFF);
                                            digitalWrite(RELAY_PIN2, RELAY_OFF);
                                            digitalWrite(RELAY_PIN3, RELAY_OFF);
                                            // Then set relay pins in output mode
                                            pinMode(RELAY_PIN0, OUTPUT);
                                            pinMode(RELAY_PIN1, OUTPUT);
                                            pinMode(RELAY_PIN2, OUTPUT);
                                            pinMode(RELAY_PIN3, OUTPUT);
                                          
                                          
                                          
                                            // Set relay to last known state (using eeprom storage)
                                            stateA = loadState(CHILD0_ID);
                                            digitalWrite(RELAY_PIN0, stateA ? RELAY_ON : RELAY_OFF);
                                          
                                            stateB = loadState(CHILD1_ID);
                                            digitalWrite(RELAY_PIN1, stateB ? RELAY_ON : RELAY_OFF);
                                          
                                            stateC = loadState(CHILD2_ID);
                                            digitalWrite(RELAY_PIN2, stateC ? RELAY_ON : RELAY_OFF);
                                          
                                            stateD = loadState(CHILD3_ID);
                                            digitalWrite(RELAY_PIN3, stateD ? RELAY_ON : RELAY_OFF);
                                          }
                                          
                                          void presentation()  {
                                            // Send the sketch version information to the gateway and Controller
                                            sendSketchInfo("4 Relay & button", "1.0");
                                          
                                            // Register all sensors to gw (they will be created as child devices)
                                            present(CHILD0_ID, S_LIGHT);
                                            present(CHILD1_ID, S_LIGHT);
                                            present(CHILD2_ID, S_LIGHT);
                                            present(CHILD3_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;
                                          
                                            debouncerC.update();
                                            // Get the update value
                                            int valueC = debouncerC.read();
                                            if (valueC != oldValueC && valueC == 0) {
                                              send(msgC.set(stateC ? false : true), true); // Send new state and request ack back
                                            }
                                            oldValueC = valueC;
                                          
                                            debouncerD.update();
                                            // Get the update value
                                            int valueD = debouncerD.read();
                                            if (valueD != oldValueD && valueD == 0) {
                                              send(msgD.set(stateD ? false : true), true); // Send new state and request ack back
                                            }
                                            oldValueD = valueD;
                                          }
                                          
                                          void receive(const MyMessage &message) {
                                            // We only expect one type of message from controller. But we better check anyway.
                                            if (message.type == V_LIGHT) {
                                              
                                              switch (message.sensor) {
                                                case CHILD0_ID:
                                                  stateA = message.getBool();
                                                  digitalWrite(RELAY_PIN0, stateA ? RELAY_ON : RELAY_OFF);
                                                  saveState(CHILD0_ID, stateA);
                                                  break;
                                                  
                                                case CHILD1_ID:
                                                  stateB = message.getBool();
                                                  digitalWrite(RELAY_PIN1, stateB ? RELAY_ON : RELAY_OFF);
                                                  saveState(CHILD1_ID, stateB);
                                                  break;
                                          
                                                case CHILD2_ID:
                                                  stateC = message.getBool();
                                                  digitalWrite(RELAY_PIN2, stateC ? RELAY_ON : RELAY_OFF);
                                                  saveState(CHILD2_ID, stateC);
                                                  break;
                                                  
                                                case CHILD3_ID:
                                                  stateD = message.getBool();
                                                  digitalWrite(RELAY_PIN3, stateD ? RELAY_ON : RELAY_OFF);
                                                  saveState(CHILD3_ID, stateD);
                                                  break;
                                              }
                                              // Write some debug info
                                              Serial.print("Incoming change for sensor:");
                                              Serial.print(message.sensor);
                                              Serial.print(", New status: ");
                                              Serial.println(message.getBool());
                                            }
                                          }```
                                          1 Reply Last reply
                                          0
                                          Reply
                                          • Reply as topic
                                          Log in to reply
                                          • Oldest to Newest
                                          • Newest to Oldest
                                          • Most Votes


                                          24

                                          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