Synchronising Light switch


  • Hero Member

    I have a 12v system in my house that is used for some of the lighting so wanted to let Mysensors take control of the nightlights that until now i have had to switch on manually. There were a few things that needed to be achieved with these nodes to make them acceptable for use.

    1. I had to retain hardware switch so the lights could still be switched from the local wall plate.

    2. The hardware switch had to remain functional even if the gateway or controller were not available. we live in a semi rural area where there are few street lights so the 12v lighting has to remain operational during power outages etc.

    3. The node should make an effort to keep the controller in sync with its current state. During first boot up and when a broken up-link has been re-established.

    The code is working with Domoticz and so far has responded well to all conditions stated above.
    it uses request to check with the controllers state and sends a message if needed to sync.
    A momentary push button is used for the switch.

    /*
       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_NRF24                         // Enable and select radio type attached
    
    #define MY_TRANSPORT_WAIT_READY_MS 5000        //set how long to wait for transport ready in milliseconds
    
    #include <MySensors.h>
    #include <Bounce2.h>
    
    #define RELAY_PIN  4      // 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 1
    #define RELAY_OFF 0
    
    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");
    }
    
    
    

    The wiring
    0_1496469040524_relay circuit.jpg



  • cool.
    nothing too much in code, nor in wiring.
    👍


  • Hero Member

    @core_c Yes I did not want it to be overly complicated or to be constantly pinging the network either.
    It is a fairly good compromise the node only starts to ping once it has determined the uplink is broken and you can decide the interval by changing uplinkCheckPeriod. At the moment it is set to 30 seconds.

    In testing the return from request usually arrived within 800 milliseconds so returnWait could also be reduced from 1500ms if it was a concern. It is only used when the node is first reconnected so felt I would rather make sure I got the correct data by adding an extra delay.


  • Hero Member

    Just a couple of other ideas on this subject to share 🙂

    This sketch is a small modification on the original to allow for the use of a toggle type switch instead of the push button

    /*
       Relay with toggle switch sketch
       modified to work with no uplink
       to gateway and try to maintain sync to controller
       Toggle switch connected between pin3 and ground.
    */
    
    
    #define MY_DEBUG                               // Enable debug prints to serial monitor
    
    #define MY_RADIO_NRF24                         // Enable and select radio type attached
    
    #define MY_TRANSPORT_WAIT_READY_MS 5000        //set how long to wait for transport ready in milliseconds
    
    #include <MySensors.h>
    #include <Bounce2.h>
    
    #define RELAY_PIN  4      // Arduino Digital I/O pin number for relay 
    #define SWITCH_PIN  3     // Arduino Digital I/O pin number for switch 
    #define CHILD_ID 1        // Id of the sensor child
    #define RELAY_ON 1
    #define RELAY_OFF 0
    
    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(SWITCH_PIN, INPUT_PULLUP);           // Setup the button pin, Activate internal pull-up
      
      debouncer.attach(SWITCH_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 & Toggle", "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) {                      // check for new throw of toggle switch
        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");
    }
    
    

    This next sketch is for a push button once again but this time it is using requestTime() to try and determine if the controller is available. While all uplink checks are only made to the gateway, by checking for the time returned from the controller it is possible to use this to test for the controllers presence. I have not tested this code extensively but it does appear to work ok within the original design goals.

    /*
       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_NRF24                         // Enable and select radio type attached
    //#define MY_RF24_CHANNEL 84
    //#define MY_NODE_ID 203
    #define MY_TRANSPORT_WAIT_READY_MS 5000        //set how long to wait for transport ready in milliseconds
    
    #include <MySensors.h>
    #include <Bounce2.h>
    
    #define RELAY_PIN  4      // 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 1
    #define RELAY_OFF 0
    
    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.. adjust as needed
    unsigned long oldTime = 0;
    unsigned long newTime = 0;
    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 test", "1.1");
    
      // 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");
        requestTime();                             // get time from controller
        wait (returnWait);                         // delay to allow time to return
        if (oldTime == 0){                         // check to see if there was a return from the time request
          Serial.println("uplink not available");
          uplinkAvailable = false;                 // no uplink established
          uplinkCheckTime = millis();
        }
         else{
          Serial.println("uplink available");
          request( CHILD_ID, V_STATUS);            // get status of switch on controller
          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
          } 
         }   
      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
        requestTime();
        wait (returnWait);                                               // delay to allow time to return
        if (oldTime != newTime){                                  // if times are different then uplink is available
          send(msg.set(state), false);
          oldTime = newTime;
        }
        else{                                                    // if times are the same no uplink is available
         Serial.println("uplink not available");
          uplinkAvailable = false;                                // no uplink available, set flag false
          uplinkCheckTime = millis();                             // start the timer from now
        }
    
      }
      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() {
        requestTime();
        wait (returnWait);                       // wait for time return.. this may need to be varied for your system
       if (oldTime != newTime){
         Serial.println("uplink re-established");
         request( CHILD_ID, V_STATUS);
         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
          oldTime = newTime;
        }
      }
      uplinkCheckTime = millis();                // reset the checktime
      Serial.println("uplinkchecktime reset");
    }
    
    
    void receiveTime(unsigned long time)
    {
      if (firstStart){
        oldTime = time;
        newTime = time;
      }
      else{
      newTime = time;
    }
      Serial.print("time received---- " );
      Serial.println(time);
    }
    
    
    


  • @boots33

    Can you also share version for 2 relays and also 1relays with temperature sensors DS18B20 Dallas and 2relays also with DS18B20 ?

    And how your sketch check that controller is available ? And if controlller is not available what is do ?



  • Ok i test your sketch with custom my radio. It look as this below.
    This look that works ok. When controller is ENABLE and i only disable on controller GATEWAY, then change status NODE and again ENABLE gateway status node on controller is refresh after some time. Also when POWER OFF controller and gateway and then change status NODE , also status is correct refresh on controller after bootup controller with gateway.

    Status is not refreshed only in one situation. When i only reboote controller with gateway and under reboote i change status NODE. After run controller and gateway status is not refresh and show not correct.

    Please share me this sketch if you can for 2xrelays ? And also option with send temperature from Dallas DS18b20 ?

    One question... How change time betwen change relay on and off. Now i must wait about 2-4 secund before try change status on off by button. Can i change this time ?

    /*
       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
    
    //#define MY_NODE_ID 203                       // Node id defaults to AUTO (tries to fetch id from controller) 
    
    #define MY_TRANSPORT_WAIT_READY_MS 5000        //set how long to wait for transport ready in milliseconds
    
    #define MY_REPEATER_FEATURE                    // Enabled repeater feature for this node
    
    #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 1
    #define RELAY_OFF 0
    
    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.. adjust as needed
    unsigned long oldTime = 0;
    unsigned long newTime = 0;
    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 test", "1.1");
    
      // 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");
        requestTime();                             // get time from controller
        wait (returnWait);                         // delay to allow time to return
        if (oldTime == 0){                         // check to see if there was a return from the time request
          Serial.println("uplink not available");
          uplinkAvailable = false;                 // no uplink established
          uplinkCheckTime = millis();
        }
         else{
          Serial.println("uplink available");
          request( CHILD_ID, V_STATUS);            // get status of switch on controller
          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
          } 
         }   
      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
        requestTime();
        wait (returnWait);                                               // delay to allow time to return
        if (oldTime != newTime){                                  // if times are different then uplink is available
          send(msg.set(state), false);
          oldTime = newTime;
        }
        else{                                                    // if times are the same no uplink is available
         Serial.println("uplink not available");
          uplinkAvailable = false;                                // no uplink available, set flag false
          uplinkCheckTime = millis();                             // start the timer from now
        }
    
      }
      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() {
        requestTime();
        wait (returnWait);                       // wait for time return.. this may need to be varied for your system
       if (oldTime != newTime){
         Serial.println("uplink re-established");
         request( CHILD_ID, V_STATUS);
         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
          oldTime = newTime;
        }
      }
      uplinkCheckTime = millis();                // reset the checktime
      Serial.println("uplinkchecktime reset");
    }
    
    
    void receiveTime(unsigned long time)
    {
      if (firstStart){
        oldTime = time;
        newTime = time;
      }
      else{
      newTime = time;
    }
      Serial.print("time received---- " );
      Serial.println(time);
    }```

  • Hero Member

    @pepson said in Synchronising Light switch:

    Status is not refreshed only in one situation. When i only reboote controller with gateway and under reboote i change status NODE. After run controller and gateway status is not refresh and show not correct.

    Sorry I do not understand what start up scenario you are describing here. Can you post details of the exact steps needed to replicate this problem.

    Please share me this sketch if you can for 2xrelays ? And also option with send temperature from Dallas DS18b20 ?

    I do not have any sketches that include switches & temperature sensors, there are however some posts already on combining relays and temp senders. You should do a search to locate them or perhaps start a new thread about that.

    One question... How change time betwen change relay on and off. Now i must wait about 2-4 secund before try change status on off by button. Can i change this time ?

    The relay should change from on/off instantly from the local switch or from the controller.
    The delay in being able to continuously flick the switch between on and off will most likely be caused by the delay required to receive the time return.
    As I said in an earlier post : In testing the return from request usually arrived within 800 milliseconds so returnWait could also be reduced from 1500ms if it was a concern.

    If you reduce it too far the switch sync will once again become unreliable. This is the trade off for a sync switch

    Why do you need to switch your lights every 2 seconds?



  • If i need fast on and then off light.
    But ok i test with change returnWait about 1000.

    But can you also share me only sketch for 2 or more relay ? This will be good sketch also for other user... Thanks for your help.
    You are the best 🙂



  • Please help me modification this script to support 2x relays with button. I start modification but i dont know how finished it...

    /*
       2xRelay 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
    
    //#define MY_NODE_ID 203                       // Node id defaults to AUTO (tries to fetch id from controller) 
    
    #define MY_TRANSPORT_WAIT_READY_MS 5000        //set how long to wait for transport ready in milliseconds
    
    #define MY_REPEATER_FEATURE                    // Enabled repeater feature for this node
    
    #include <MySensors.h>
    #include <Bounce2.h>
    
    #define RELAY_PIN_A  5      // Arduino Digital I/O pin number for relay A
    #define BUTTON_PIN_A  3     // Arduino Digital I/O pin number for button A
    #define RELAY_PIN_B  6      // Arduino Digital I/O pin number for relay B
    #define BUTTON_PIN_B  4     // Arduino Digital I/O pin number for button B
    #define CHILD_ID_A 1        // Id of the sensor child A
    #define CHILD_ID_B 2        // Id of the sensor child B
    #define RELAY_ON 1
    #define RELAY_OFF 0
    
    Bounce debouncer = Bounce();
    int oldValue = 0;
    bool uplinkAvailable = true;
    bool stateA = false;
    bool stateB = 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 = 1000;               // how long to wait for return from controller in milliseconds.. adjust as needed
    unsigned long oldTime = 0;
    unsigned long newTime = 0;
    MyMessage msg(CHILD_ID_A, V_STATUS);
    MyMessage msg(CHILD_ID_B, V_STATUS);
    
    void setup(){
      pinMode(BUTTON_PIN, INPUT_PULLUP);           // Setup the button pin, Activate internal pull-up
      
      debouncer.attach(BUTTON_PIN_A);                // After setting up the button A, setup debouncer
      debouncer.interval(5);
      debouncer.attach(BUTTON_PIN_B);                // After setting up the button B, setup debouncer
      debouncer.interval(5);
    
      pinMode(RELAY_PIN_A, OUTPUT);                 // set relay A pin in output mode
      digitalWrite(RELAY_PIN_A, RELAY_OFF);         // Make sure relay B is off when starting up
      pinMode(RELAY_PIN_B, OUTPUT);                 // set relay B pin in output mode
      digitalWrite(RELAY_PIN_B, RELAY_OFF);         // Make sure relay B is off when starting up
    }
    
    void presentation()  {
      // Send the sketch version information to the gateway and Controller
      sendSketchInfo("2xRelay & Button", "2.1.1");
    
      // Register all sensors to gw (they will be created as child devices)
      present(CHILD_ID_A, S_BINARY);
      present(CHILD_ID_B, S_BINARY);
    }
    
    
    void loop(){
      if (firstStart) {                            // this code is only run once at startup
        Serial.println("First run started");
        requestTime();                             // get time from controller
        wait (returnWait);                         // delay to allow time to return
        if (oldTime == 0){                         // check to see if there was a return from the time request
          Serial.println("uplink not available");
          uplinkAvailable = false;                 // no uplink established
          uplinkCheckTime = millis();
        }
         else{
          Serial.println("uplink available");
          request( CHILD_ID_A, V_STATUS);            // get status of switch on controller
          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
          } 
         }   
      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_A, state ? RELAY_ON : RELAY_OFF);    // switch the relay to the new state
        requestTime();
        wait (returnWait);                                               // delay to allow time to return
        if (oldTime != newTime){                                  // if times are different then uplink is available
          send(msg.set(state), false);
          oldTime = newTime;
        }
        else{                                                    // if times are the same no uplink is available
         Serial.println("uplink not available");
          uplinkAvailable = false;                                // no uplink available, set flag false
          uplinkCheckTime = millis();                             // start the timer from now
        }
    
      }
    
      if (firstStart) {                            // this code is only run once at startup
        Serial.println("First run started");
        requestTime();                             // get time from controller
        wait (returnWait);                         // delay to allow time to return
        if (oldTime == 0){                         // check to see if there was a return from the time request
          Serial.println("uplink not available");
          uplinkAvailable = false;                 // no uplink established
          uplinkCheckTime = millis();
        }
         else{
          Serial.println("uplink available");
          request( CHILD_ID_B, V_STATUS);            // get status of switch on controller
          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
          } 
         }   
      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_B, stateB ? RELAY_ON : RELAY_OFF);    // switch the relay to the new state
        requestTime();
        wait (returnWait);                                               // delay to allow time to return
        if (oldTime != newTime){                                  // if times are different then uplink is available
          send(msg.set(stateB), false);
          oldTime = newTime;
        }
        else{                                                    // if times are the same no uplink is available
         Serial.println("uplink not available");
          uplinkAvailable = false;                                // no uplink available, set flag false
          uplinkCheckTime = millis();                             // start the timer from now
        }
    
      }
      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_A, stateA ? 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;
        }
      }
    
      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_B, stateB ? 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() {
        requestTime();
        wait (returnWait);                       // wait for time return.. this may need to be varied for your system
       if (oldTime != newTime){
         Serial.println("uplink re-established");
         request( CHILD_ID_A, V_STATUS);
         wait (returnWait);                        //wait needed to allow request to return from controller
        if (requestState != stateA) {              // 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
          oldTime = newTime;
        }
      }
      uplinkCheckTime = millis();                // reset the checktime
      Serial.println("uplinkchecktime reset");
    }
    
    
    void receiveTime(unsigned long time)
    {
      if (firstStart){
        oldTime = time;
        newTime = time;
      }
      else{
      newTime = time;
    }
      Serial.print("time received---- " );
      Serial.println(time);
    }```


  • Hi
    Can you help me convert this skecth for MySensors 2.2.0 because it was released. I upload to my Arduino MIni Pro this sketch but in Gateway Domoticz not show child to switch relay. Only show repeater child on ID 255.
    And also if you can please share me ready skecth for 2x releay.

    /*
       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_IS_RFM69HW
    #define RFM69_868MH
    #define MY_RFM69_NEW_DRIVER
    
    //#define MY_NODE_ID 203                       // Node id defaults to AUTO (tries to fetch id from controller) 
    
    #define MY_TRANSPORT_WAIT_READY_MS 5000        //set how long to wait for transport ready in milliseconds
    
    #define MY_REPEATER_FEATURE                    // Enabled repeater feature for this node
    
    #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 1
    #define RELAY_OFF 0
    
    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 = 1000;               // how long to wait for return from controller in milliseconds.. adjust as needed
    unsigned long oldTime = 0;
    unsigned long newTime = 0;
    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("1xRelay & Button", "2.2.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");
        requestTime();                             // get time from controller
        wait (returnWait);                         // delay to allow time to return
        if (oldTime == 0){                         // check to see if there was a return from the time request
          Serial.println("uplink not available");
          uplinkAvailable = false;                 // no uplink established
          uplinkCheckTime = millis();
        }
         else{
          Serial.println("uplink available");
          request( CHILD_ID, V_STATUS);            // get status of switch on controller
          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
          } 
         }   
      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
        requestTime();
        wait (returnWait);                                               // delay to allow time to return
        if (oldTime != newTime){                                  // if times are different then uplink is available
          send(msg.set(state), false);
          oldTime = newTime;
        }
        else{                                                    // if times are the same no uplink is available
         Serial.println("uplink not available");
          uplinkAvailable = false;                                // no uplink available, set flag false
          uplinkCheckTime = millis();                             // start the timer from now
        }
    
      }
      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() {
        requestTime();
        wait (returnWait);                       // wait for time return.. this may need to be varied for your system
       if (oldTime != newTime){
         Serial.println("uplink re-established");
         request( CHILD_ID, V_STATUS);
         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
          oldTime = newTime;
        }
      }
      uplinkCheckTime = millis();                // reset the checktime
      Serial.println("uplinkchecktime reset");
    }
    
    
    void receiveTime(unsigned long time)
    {
      if (firstStart){
        oldTime = time;
        newTime = time;
      }
      else{
      newTime = time;
    }
      Serial.print("time received---- " );
      Serial.println(time);
    }
    

Log in to reply
 

Suggested Topics

2
Online

11.2k
Users

11.1k
Topics

112.5k
Posts