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. Troubleshooting
  3. Prevent Relay from triggering on power loss or broker reboot

Prevent Relay from triggering on power loss or broker reboot

Scheduled Pinned Locked Moved Troubleshooting
22 Posts 8 Posters 8.3k Views 8 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.
  • hekH Online
    hekH Online
    hek
    Admin
    wrote on last edited by hek
    #3

    You can use load/saveState to save the state the local EEPROM. Then at startup you set the relay in the last known state.

    1 Reply Last reply
    0
    • gohanG Offline
      gohanG Offline
      gohan
      Mod
      wrote on last edited by
      #4

      It is something that is triggering a pulse in some pins during startup, because I tried to set all pins to low during setup, but that was happening anyway so my guess is something else is pulsing before the setup is executed.

      1 Reply Last reply
      0
      • rhuehnR Offline
        rhuehnR Offline
        rhuehn
        wrote on last edited by
        #5

        @hek Thanks for the reply, but I'm not 100% sure as I am still somewhat new to mysensors and arduino. Is there any chance you could possibly show an example using the above sketch I pasted previously?

        Thanks!

        1 Reply Last reply
        0
        • hekH Online
          hekH Online
          hek
          Admin
          wrote on last edited by
          #6

          https://github.com/mysensors/MySensorsArduinoExamples/blob/master/examples/RelayWithButtonActuator/RelayWithButtonActuator.ino

          1 Reply Last reply
          0
          • gohanG Offline
            gohanG Offline
            gohan
            Mod
            wrote on last edited by
            #7

            That's not very different from the code I used in setup, but the issue I noticed it was just in a couple of pins that were triggering the relay, not all of them.

            1 Reply Last reply
            0
            • rhuehnR rhuehn

              Hey guys:

              I'm currently using a relay to control a garage door opener, but when the MQTT broker reboots, or the Arduino reboots, the relay's click on and off, of course opening / closing the garage door. Is there a way to have the relay's remember state and NOT click on and off in case of power or broker restart? I am not much of a coder, and combled this together, so if anyone can help it would be greatly appreciated!

              
              #define MY_DEBUG
              #define MY_RADIO_NRF24
              #define MY_REPEATER_FEATURE
              #define MY_NODE_ID 50
              
              #include <SPI.h>
              #include <MySensors.h>
              #include <Bounce2.h>  
              #include <DHT.h>  
              
              #define CHILD_ID_TEMP 11
              #define CHILD_ID_HUM 10
              #define CHILD_ID_MOT 3   // Id of the sensor child
              #define HUMIDITY_SENSOR_DIGITAL_PIN 7
              #define DIGITAL_INPUT_SENSOR 3   // The digital input you attached your motion sensor.  (Only 2 and 3 generates interrupt!)
              #define INTERRUPT DIGITAL_INPUT_SENSOR-2 // Usually the interrupt = pin -2 (on uno/nano anyway)
              #define RELAY_PIN  4
              #define CHILD_ID_REL 1
              #define RELAY_ON 1
              #define RELAY_OFF 0
              #define TOGGLE_INTERVAL 350  //Tells how many milliseconds the relay will be held closed
              #define CHILD_ID_SW 2
              #define BUTTON_PIN_2  2  // Arduino Digital I/O pin for button/reed switch
              
              Bounce debouncer = Bounce();
              bool state = false;
              bool initialValueSent = false;
              
              Bounce debouncer2 = Bounce(); 
              int oldValue2=-1;
              
              unsigned long SLEEP_TIME = 60000; // Sleep time between reads (in milliseconds)
              
              DHT dht;
              float lastTemp;
              float lastHum;
              boolean metric = true; 
              MyMessage msgHum(CHILD_ID_HUM, V_HUM);
              MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP);
              MyMessage msgMot(CHILD_ID_MOT, V_TRIPPED);
              MyMessage msg(CHILD_ID_REL, V_STATUS);
              MyMessage msgSW(CHILD_ID_SW,V_TRIPPED);
              
              void presentation()  
              { 
                // Send the Sketch Version Information to the Gateway
                sendSketchInfo("Temp/Hum/Mot", "1.3");
                // Register all sensors to gw (they will be created as child devices)
                delay(100);
                present(CHILD_ID_TEMP, S_TEMP);
                delay(100);
                present(CHILD_ID_HUM, S_HUM);
                delay(100);
                present(CHILD_ID_MOT, S_MOTION);
                delay(100);
                present(CHILD_ID_REL, S_BINARY);
                delay(100);
                present(CHILD_ID_SW, S_DOOR); 
              
                metric = getConfig().isMetric;
              }
              
              void setup()
              {
                  // Setup the button
                pinMode(BUTTON_PIN_2,INPUT);
                // Activate internal pull-up
                digitalWrite(BUTTON_PIN_2,HIGH);
                // After setting up the button, setup debouncer
                debouncer2.attach(BUTTON_PIN_2);
                debouncer2.interval(5);
                // Make sure relays are off when starting up
                digitalWrite(RELAY_PIN, RELAY_OFF);
                pinMode(RELAY_PIN, OUTPUT);
                dht.setup(HUMIDITY_SENSOR_DIGITAL_PIN); 
                if (SLEEP_TIME <= dht.getMinimumSamplingPeriod()) {
                  Serial.println("Warning: UPDATE_INTERVAL is smaller than supported by the sensor!");
                }
                // Sleep for the time of the minimum sampling period to give the sensor time to power up
                // (otherwise, timeout errors might occure for the first reading)
                sleep(dht.getMinimumSamplingPeriod());
              
              //  metric = getConfig().isMetric;
              
                pinMode(DIGITAL_INPUT_SENSOR, INPUT);      // sets the motion sensor digital pin as input
                delay(100);
                send(msgTemp.set("0"));
                delay(100);
                send(msgHum.set("0"));
                delay(100);
                send(msgMot.set("0"));
              }
              
              void loop()
              {
                debouncer2.update();
                // Get the update value
                int value2 = debouncer2.read();
              
                if (value2 != oldValue2) {
                   // Send in the new value
                   send(msgSW.set(value2==HIGH ? 1 : 0));
                   oldValue2 = value2;
                }
              {
                if (!initialValueSent) {
                  Serial.println("Sending initial value");
                  send(msg.set(state?RELAY_ON:RELAY_OFF));
                  Serial.println("Requesting initial value from controller");
                  request(CHILD_ID_REL, V_STATUS);
                  wait(2000, C_SET, V_STATUS);
                }
                if (debouncer.update()) {
                  if (debouncer.read()==LOW) {
                    state = !state;
                    // Send new state and request ack back
                    send(msg.set(state?RELAY_ON:RELAY_OFF), true);
                  }
                }
                // Read digital motion value
                boolean tripped = digitalRead(DIGITAL_INPUT_SENSOR) == HIGH; 
                      
                Serial.println(tripped);
                send(msgMot.set(tripped?"1":"0"));  // Send tripped value to gw 
                
                delay(dht.getMinimumSamplingPeriod());
               
                // Fetch temperatures from DHT sensor
                float temperature = dht.getTemperature();
                if (isnan(temperature)) {
                    Serial.println("Failed reading temperature from DHT");
                } else if (temperature != lastTemp) {
                  lastTemp = temperature;
                  if (!metric) {
                    temperature = dht.toFahrenheit(temperature);
                  }
                  send(msgTemp.set(temperature, 1));
                  #ifdef MY_DEBUG
                  Serial.print("T: ");
                  Serial.println(temperature);
                  #endif
                }
                
                // Fetch humidity from DHT sensor
                float humidity = dht.getHumidity();
                if (isnan(humidity)) {
                    Serial.println("Failed reading humidity from DHT");
                } else if (humidity != lastHum) {
                    lastHum = humidity;
                    send(msgHum.set(humidity, 1));
                    #ifdef MY_DEBUG
                    Serial.print("H: ");
                    Serial.println(humidity);
                    #endif
                }
                
                sleep(INTERRUPT,CHANGE, SLEEP_TIME); //sleep a bit
                }
              }
              
              void receive(const MyMessage &message) {
                if (message.isAck()) {
                   Serial.println("This is an ack from gateway");
                }
              
                if (message.type == V_STATUS) {
                  if (!initialValueSent) {
                    Serial.println("Receiving initial value from controller");
                    initialValueSent = true;
                  }
                  // Change relay state
                  state = (bool)message.getInt();
                  digitalWrite(RELAY_PIN, state?RELAY_ON:RELAY_OFF);
                  digitalWrite( RELAY_PIN, RELAY_ON );
                  //Keep the relay on for the amount of time defined by TOGGLE_INTERVAL
                  delay( TOGGLE_INTERVAL );
                  digitalWrite( RELAY_PIN, RELAY_OFF );
                  //Added this to tell the controller that we shut off the relay
                   // Store state in eeprom
                  saveState(message.sensor, message.getBool());
                  send(msg.set(state?RELAY_ON:RELAY_OFF));
                }
              }
              
              Boots33B Offline
              Boots33B Offline
              Boots33
              Hero Member
              wrote on last edited by Boots33
              #8

              @rhuehn I think the problem may be in the implementation of your initialValueSent code.
              at the start of your code you set state and initialValueSent to false

              bool state = false;
              bool initialValueSent = false;```
              
              

              So when the loop first runs your code is executed

              if (!initialValueSent) {
                  Serial.println("Sending initial value");
                  send(msg.set(state?RELAY_ON:RELAY_OFF));                  /* here you send the off state to the controller */
                  Serial.println("Requesting initial value from controller");
                  request(CHILD_ID_REL, V_STATUS);                                      /* you then request the status of the relay  you just turned off ?*/
                  wait(2000, C_SET, V_STATUS);
                }
              

              When the request returns yo use the status to turn off the relay but then you immediately turn the relay on and off again. that may cause the problem you have encountered.

              void receive(const MyMessage &message) {
                if (message.isAck()) {
                   Serial.println("This is an ack from gateway");
                }
              
                if (message.type == V_STATUS) {
                  if (!initialValueSent) {
                    Serial.println("Receiving initial value from controller");
                    initialValueSent = true;                                                                     /* you set to true so initial code will no longer  be executed
                  }
                  // Change relay state
                  state = (bool)message.getInt();
                  digitalWrite(RELAY_PIN, state?RELAY_ON:RELAY_OFF);                                                  /* You set the relay to the current state, which is off */
                  digitalWrite( RELAY_PIN, RELAY_ON );                                                                                 /* you then switch the relay back on  ?  /*
                  //Keep the relay on for the amount of time defined by TOGGLE_INTERVAL
                  delay( TOGGLE_INTERVAL );                                                                                             /* then a delay */
                  digitalWrite( RELAY_PIN, RELAY_OFF );                                                                          /* then back off
                  //Added this to tell the controller that we shut off the relay  
                   // Store state in eeprom
                  saveState(message.sensor, message.getBool());
                  send(msg.set(state?RELAY_ON:RELAY_OFF));
                }
              }
              

              you seem to have a lot happening at the startup of your node, you have already turned the relay off in your setup code so do you need to bother with the rest?

              // Make sure relays are off when starting up
                digitalWrite(RELAY_PIN, RELAY_OFF);
                pinMode(RELAY_PIN, OUTPUT);           /* I think normally you would set pinmode before writing so you may want to move this line up one */
              
              1 Reply Last reply
              0
              • rhuehnR Offline
                rhuehnR Offline
                rhuehn
                wrote on last edited by
                #9

                @Boots33 Thanks very much for the reply, and I know this is late in my response so I apologize about that....

                So this sketch does the following. A Replay that momentarily interrupts the garage door button to simulate a press of the control button, has a PIR and a DHT for motion and temp / hum, and also has a reed switch that can determine if the door is open or closed. I've been playing none stop with the sketch, and have tweaked it to the best of my ability, but STILL on power loss, the relay always clicks... therefore opening or closing the door...... Based on these changes, is there any way I can clean this up ( I'm at a loss unfortunately ) so that on power loss the relay remains as it was "state"? I've tried a few combinations without any luck to this point. My revised sketch is below, and I really appreciate any help.

                Thanks

                #define MY_DEBUG
                #define MY_RADIO_NRF24
                #define MY_REPEATER_FEATURE
                #define MY_NODE_ID 50
                
                #include <SPI.h>
                #include <MySensors.h>
                #include <Bounce2.h>  
                #include <DHT.h>  
                
                #define CHILD_ID_TEMP 11
                #define CHILD_ID_HUM 10
                #define CHILD_ID_MOT 3   // Id of the sensor child
                #define CHILD_ID_REL 1
                #define RELAY_PIN  4
                #define RELAY_ON 1
                #define RELAY_OFF 0
                #define TOGGLE_INTERVAL 350  //Tells how many milliseconds the relay will be held closed
                #define CLOSED 0
                #define OPEN 1
                #define BUTTON_PIN_1  2
                #define CHILD_ID_SW 2
                #define HUMIDITY_SENSOR_DIGITAL_PIN 7
                #define DIGITAL_INPUT_SENSOR 3   // The digital input you attached your motion sensor.  (Only 2 and 3 generates interrupt!)
                #define INTERRUPT DIGITAL_INPUT_SENSOR-2 // Usually the interrupt = pin -2 (on uno/nano anyway)
                
                // Set this offset if the sensor has a permanent small offset to the real temperatures
                #define SENSOR_TEMP_OFFSET 1
                
                Bounce debouncer = Bounce();
                int oldValue=-1;
                
                bool state = false;
                bool initialValueSent = false;
                byte StatePIR=0;
                byte oldStatePIR=0;
                unsigned long SLEEP_TIME = 60000; // Sleep time between reads (in milliseconds)
                
                DHT dht;
                float lastTemp;
                float lastHum;
                boolean metric = true; 
                bool StateREL=0, StateREL1=0;
                MyMessage msgHum(CHILD_ID_HUM, V_HUM);
                MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP);
                MyMessage msgMot(CHILD_ID_MOT, V_TRIPPED);
                MyMessage msg(CHILD_ID_REL, V_STATUS);
                MyMessage msgSW(CHILD_ID_SW,V_TRIPPED);
                
                void presentation()  
                { 
                  // Send the Sketch Version Information to the Gateway
                  sendSketchInfo("Garage Multi Sensor", "1.0");
                
                  // Register all sensors to gw (they will be created as child devices)
                  delay(100);
                  present(CHILD_ID_TEMP, S_TEMP);
                  delay(100);
                  present(CHILD_ID_HUM, S_HUM);
                  delay(100);
                  present(CHILD_ID_MOT, S_MOTION);
                  delay(100);
                  present(CHILD_ID_REL, S_BINARY);
                  delay(100);
                  present(CHILD_ID_SW, S_DOOR);
                
                  metric = getConfig().isMetric;
                }
                
                void setup()
                {
                  // Setup the button
                  pinMode(BUTTON_PIN_1,INPUT);
                  // Activate internal pull-up
                  digitalWrite(BUTTON_PIN_1,HIGH);
                  // After setting up the button, setup debouncer
                  debouncer.attach(BUTTON_PIN_1);
                  debouncer.interval(5);
                
                
                  // Make sure relays are off when starting up
                  pinMode(RELAY_PIN, OUTPUT);
                  digitalWrite(RELAY_PIN, StateREL1);
                
                  dht.setup(HUMIDITY_SENSOR_DIGITAL_PIN); 
                  if (SLEEP_TIME <= dht.getMinimumSamplingPeriod()) {
                    Serial.println("Warning: UPDATE_INTERVAL is smaller than supported by the sensor!");
                  }
                  // Sleep for the time of the minimum sampling period to give the sensor time to power up
                  // (otherwise, timeout errors might occure for the first reading)
                  sleep(dht.getMinimumSamplingPeriod());
                
                //  metric = getConfig().isMetric;
                
                  pinMode(DIGITAL_INPUT_SENSOR, INPUT);      // sets the motion sensor digital pin as input
                }
                
                void loop()
                {
                    debouncer.update();
                  // Get the update value
                  int value = debouncer.read();
                
                  if (value != oldValue) {
                     // Send in the new value
                     send(msgSW.set(value==HIGH ? 1 : 0));
                     oldValue = value;
                  }
                  StatePIR=digitalRead(DIGITAL_INPUT_SENSOR);
                  if (StatePIR != oldStatePIR) {
                    oldStatePIR=StatePIR;
                    send(msgMot.set(StatePIR ? 1 : 0));
                  }
                 
                  if (!initialValueSent) {
                    Serial.println("Sending initial value");
                    send(msg.set(state?RELAY_ON:RELAY_OFF));
                    Serial.println("Requesting initial value from controller");
                    request(CHILD_ID_REL, V_STATUS);
                    wait(2000, C_SET, V_STATUS);
                  }
                  if (debouncer.update()) {
                    if (debouncer.read()==LOW) {
                      state = !state;
                      // Send new state and request ack back
                      send(msg.set(state?RELAY_ON:RELAY_OFF), true);
                    }
                  }
                 
                  // Read digital motion value
                  boolean tripped = digitalRead(DIGITAL_INPUT_SENSOR) == HIGH; 
                        
                  Serial.println(tripped);
                  send(msgMot.set(tripped?"1":"0"));  // Send tripped value to gw 
                  
                  delay(dht.getMinimumSamplingPeriod());
                 
                  // Fetch temperatures from DHT sensor
                  float temperature = dht.getTemperature();
                  if (isnan(temperature)) {
                      Serial.println("Failed reading temperature from DHT");
                  } else if (temperature != lastTemp) {
                    lastTemp = temperature;
                    if (!metric) {
                      temperature = dht.toFahrenheit(temperature);
                    }
                    temperature += SENSOR_TEMP_OFFSET;
                    send(msgTemp.set(temperature, 1));
                    #ifdef MY_DEBUG
                    Serial.print("T: ");
                    Serial.println(temperature);
                    #endif
                  }
                  
                  // Fetch humidity from DHT sensor
                  float humidity = dht.getHumidity();
                  if (isnan(humidity)) {
                      Serial.println("Failed reading humidity from DHT");
                  } else if (humidity != lastHum) {
                      lastHum = humidity;
                      send(msgHum.set(humidity, 1));
                      #ifdef MY_DEBUG
                      Serial.print("H: ");
                      Serial.println(humidity);
                      #endif
                  }
                  
                  sleep(INTERRUPT,CHANGE, SLEEP_TIME); //sleep a bit
                }
                
                void receive(const MyMessage &message) {
                  if (message.isAck()) {
                     Serial.println("This is an ack from gateway");
                  }
                  if (message.type == V_STATUS) {
                    if (!initialValueSent) {
                      Serial.println("Receiving initial value from controller");
                      initialValueSent = true;
                    }
                    // Change relay state
                    state = (bool)message.getInt();
                    digitalWrite(RELAY_PIN, state?RELAY_ON:RELAY_OFF);
                    //Keep the relay on for the amount of time defined by TOGGLE_INTERVAL
                    delay( TOGGLE_INTERVAL );
                    digitalWrite( RELAY_PIN, RELAY_OFF );
                    // Store state in eeprom
                    saveState(message.sensor, message.getBool());
                    send(msg.set(state?RELAY_ON:RELAY_OFF));
                  }
                }
                
                Boots33B 1 Reply Last reply
                0
                • rhuehnR rhuehn

                  @Boots33 Thanks very much for the reply, and I know this is late in my response so I apologize about that....

                  So this sketch does the following. A Replay that momentarily interrupts the garage door button to simulate a press of the control button, has a PIR and a DHT for motion and temp / hum, and also has a reed switch that can determine if the door is open or closed. I've been playing none stop with the sketch, and have tweaked it to the best of my ability, but STILL on power loss, the relay always clicks... therefore opening or closing the door...... Based on these changes, is there any way I can clean this up ( I'm at a loss unfortunately ) so that on power loss the relay remains as it was "state"? I've tried a few combinations without any luck to this point. My revised sketch is below, and I really appreciate any help.

                  Thanks

                  #define MY_DEBUG
                  #define MY_RADIO_NRF24
                  #define MY_REPEATER_FEATURE
                  #define MY_NODE_ID 50
                  
                  #include <SPI.h>
                  #include <MySensors.h>
                  #include <Bounce2.h>  
                  #include <DHT.h>  
                  
                  #define CHILD_ID_TEMP 11
                  #define CHILD_ID_HUM 10
                  #define CHILD_ID_MOT 3   // Id of the sensor child
                  #define CHILD_ID_REL 1
                  #define RELAY_PIN  4
                  #define RELAY_ON 1
                  #define RELAY_OFF 0
                  #define TOGGLE_INTERVAL 350  //Tells how many milliseconds the relay will be held closed
                  #define CLOSED 0
                  #define OPEN 1
                  #define BUTTON_PIN_1  2
                  #define CHILD_ID_SW 2
                  #define HUMIDITY_SENSOR_DIGITAL_PIN 7
                  #define DIGITAL_INPUT_SENSOR 3   // The digital input you attached your motion sensor.  (Only 2 and 3 generates interrupt!)
                  #define INTERRUPT DIGITAL_INPUT_SENSOR-2 // Usually the interrupt = pin -2 (on uno/nano anyway)
                  
                  // Set this offset if the sensor has a permanent small offset to the real temperatures
                  #define SENSOR_TEMP_OFFSET 1
                  
                  Bounce debouncer = Bounce();
                  int oldValue=-1;
                  
                  bool state = false;
                  bool initialValueSent = false;
                  byte StatePIR=0;
                  byte oldStatePIR=0;
                  unsigned long SLEEP_TIME = 60000; // Sleep time between reads (in milliseconds)
                  
                  DHT dht;
                  float lastTemp;
                  float lastHum;
                  boolean metric = true; 
                  bool StateREL=0, StateREL1=0;
                  MyMessage msgHum(CHILD_ID_HUM, V_HUM);
                  MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP);
                  MyMessage msgMot(CHILD_ID_MOT, V_TRIPPED);
                  MyMessage msg(CHILD_ID_REL, V_STATUS);
                  MyMessage msgSW(CHILD_ID_SW,V_TRIPPED);
                  
                  void presentation()  
                  { 
                    // Send the Sketch Version Information to the Gateway
                    sendSketchInfo("Garage Multi Sensor", "1.0");
                  
                    // Register all sensors to gw (they will be created as child devices)
                    delay(100);
                    present(CHILD_ID_TEMP, S_TEMP);
                    delay(100);
                    present(CHILD_ID_HUM, S_HUM);
                    delay(100);
                    present(CHILD_ID_MOT, S_MOTION);
                    delay(100);
                    present(CHILD_ID_REL, S_BINARY);
                    delay(100);
                    present(CHILD_ID_SW, S_DOOR);
                  
                    metric = getConfig().isMetric;
                  }
                  
                  void setup()
                  {
                    // Setup the button
                    pinMode(BUTTON_PIN_1,INPUT);
                    // Activate internal pull-up
                    digitalWrite(BUTTON_PIN_1,HIGH);
                    // After setting up the button, setup debouncer
                    debouncer.attach(BUTTON_PIN_1);
                    debouncer.interval(5);
                  
                  
                    // Make sure relays are off when starting up
                    pinMode(RELAY_PIN, OUTPUT);
                    digitalWrite(RELAY_PIN, StateREL1);
                  
                    dht.setup(HUMIDITY_SENSOR_DIGITAL_PIN); 
                    if (SLEEP_TIME <= dht.getMinimumSamplingPeriod()) {
                      Serial.println("Warning: UPDATE_INTERVAL is smaller than supported by the sensor!");
                    }
                    // Sleep for the time of the minimum sampling period to give the sensor time to power up
                    // (otherwise, timeout errors might occure for the first reading)
                    sleep(dht.getMinimumSamplingPeriod());
                  
                  //  metric = getConfig().isMetric;
                  
                    pinMode(DIGITAL_INPUT_SENSOR, INPUT);      // sets the motion sensor digital pin as input
                  }
                  
                  void loop()
                  {
                      debouncer.update();
                    // Get the update value
                    int value = debouncer.read();
                  
                    if (value != oldValue) {
                       // Send in the new value
                       send(msgSW.set(value==HIGH ? 1 : 0));
                       oldValue = value;
                    }
                    StatePIR=digitalRead(DIGITAL_INPUT_SENSOR);
                    if (StatePIR != oldStatePIR) {
                      oldStatePIR=StatePIR;
                      send(msgMot.set(StatePIR ? 1 : 0));
                    }
                   
                    if (!initialValueSent) {
                      Serial.println("Sending initial value");
                      send(msg.set(state?RELAY_ON:RELAY_OFF));
                      Serial.println("Requesting initial value from controller");
                      request(CHILD_ID_REL, V_STATUS);
                      wait(2000, C_SET, V_STATUS);
                    }
                    if (debouncer.update()) {
                      if (debouncer.read()==LOW) {
                        state = !state;
                        // Send new state and request ack back
                        send(msg.set(state?RELAY_ON:RELAY_OFF), true);
                      }
                    }
                   
                    // Read digital motion value
                    boolean tripped = digitalRead(DIGITAL_INPUT_SENSOR) == HIGH; 
                          
                    Serial.println(tripped);
                    send(msgMot.set(tripped?"1":"0"));  // Send tripped value to gw 
                    
                    delay(dht.getMinimumSamplingPeriod());
                   
                    // Fetch temperatures from DHT sensor
                    float temperature = dht.getTemperature();
                    if (isnan(temperature)) {
                        Serial.println("Failed reading temperature from DHT");
                    } else if (temperature != lastTemp) {
                      lastTemp = temperature;
                      if (!metric) {
                        temperature = dht.toFahrenheit(temperature);
                      }
                      temperature += SENSOR_TEMP_OFFSET;
                      send(msgTemp.set(temperature, 1));
                      #ifdef MY_DEBUG
                      Serial.print("T: ");
                      Serial.println(temperature);
                      #endif
                    }
                    
                    // Fetch humidity from DHT sensor
                    float humidity = dht.getHumidity();
                    if (isnan(humidity)) {
                        Serial.println("Failed reading humidity from DHT");
                    } else if (humidity != lastHum) {
                        lastHum = humidity;
                        send(msgHum.set(humidity, 1));
                        #ifdef MY_DEBUG
                        Serial.print("H: ");
                        Serial.println(humidity);
                        #endif
                    }
                    
                    sleep(INTERRUPT,CHANGE, SLEEP_TIME); //sleep a bit
                  }
                  
                  void receive(const MyMessage &message) {
                    if (message.isAck()) {
                       Serial.println("This is an ack from gateway");
                    }
                    if (message.type == V_STATUS) {
                      if (!initialValueSent) {
                        Serial.println("Receiving initial value from controller");
                        initialValueSent = true;
                      }
                      // Change relay state
                      state = (bool)message.getInt();
                      digitalWrite(RELAY_PIN, state?RELAY_ON:RELAY_OFF);
                      //Keep the relay on for the amount of time defined by TOGGLE_INTERVAL
                      delay( TOGGLE_INTERVAL );
                      digitalWrite( RELAY_PIN, RELAY_OFF );
                      // Store state in eeprom
                      saveState(message.sensor, message.getBool());
                      send(msg.set(state?RELAY_ON:RELAY_OFF));
                    }
                  }
                  
                  Boots33B Offline
                  Boots33B Offline
                  Boots33
                  Hero Member
                  wrote on last edited by
                  #10

                  @rhuehn Can you explain in more detail how your project is meant to work? How and when is the relay meant to be triggered, what is the motion sensor used for?

                  In the code below what are you trying to achieve.

                   if (!initialValueSent) {
                      Serial.println("Sending initial value");
                      send(msg.set(state?RELAY_ON:RELAY_OFF));
                      Serial.println("Requesting initial value from controller");
                      request(CHILD_ID_REL, V_STATUS);
                      wait(2000, C_SET, V_STATUS);
                    }
                  

                  Your node is a repeater as well as expecting to receive messages so you should not be using sleep or delay in your code, use wait instead

                  What is the saveState for in your message receive code?

                  Try this and see if it stops your relay from activating

                  if (message.type == V_STATUS) {
                      if (!initialValueSent) {
                        Serial.println("Receiving initial value from controller");
                        initialValueSent = true;
                      }
                  else {
                      // Change relay state
                      state = (bool)message.getInt();
                      digitalWrite(RELAY_PIN, state?RELAY_ON:RELAY_OFF);
                      //Keep the relay on for the amount of time defined by TOGGLE_INTERVAL
                      delay( TOGGLE_INTERVAL );
                      digitalWrite( RELAY_PIN, RELAY_OFF );
                      // Store state in eeprom
                      saveState(message.sensor, message.getBool());
                      send(msg.set(state?RELAY_ON:RELAY_OFF));
                    }
                  }
                  
                  1 Reply Last reply
                  0
                  • rhuehnR Offline
                    rhuehnR Offline
                    rhuehn
                    wrote on last edited by
                    #11

                    Hey @Boots33 Thanks very much for the reply. I apologize I should have elaborated further.

                    My home automation platform is Home Assistant. I am using a few mysensors around the house for temp, motion etc, and the purpose of this very sensor / sketch is to be used as a garage door opener. I am using an Uno, with the following PINS:

                    PIR - PIN 3
                    DHT - PIN 7
                    Relay - PIN 4
                    Reed switch - PIN 2

                    The PIR and the DHT are just fun addon sensors that might trigger an action based on motion or temp.

                    The Reed switch can tell when the garage door is open or closed based on contact, and the relay's purpose is to provide a momentary "press" of the garage door wall control, ( I have it wired into the opener and relay ).

                    It currently works great, but on loss of power at the house ( The arduino is plugged in ), the relay trips on reload, causing the garage door to open / close, and well, if we are away from the house, this is obviously not good. ;)

                    I just tried implementing your change you recommended, and unfortunately on reboot, the relay still triggers. Ideally, if I could have the relay not trigger on reboot, then I would consider it safe. I'm sure it's possible, I just can't figure out how to not have it reset / trigger on AC power fail. The interface appears as follows:

                    0_1488935309554_upload-d5417f76-6875-4689-bc03-2fa7f45d760c

                    I did make the modification, but the results are the same, so I won't re paste the code block.

                    Thanks very much for the help @Boots33 if there are any other code mods I could make, I really would appreciate it.

                    Thanks!

                    Boots33B 1 Reply Last reply
                    0
                    • rhuehnR rhuehn

                      Hey @Boots33 Thanks very much for the reply. I apologize I should have elaborated further.

                      My home automation platform is Home Assistant. I am using a few mysensors around the house for temp, motion etc, and the purpose of this very sensor / sketch is to be used as a garage door opener. I am using an Uno, with the following PINS:

                      PIR - PIN 3
                      DHT - PIN 7
                      Relay - PIN 4
                      Reed switch - PIN 2

                      The PIR and the DHT are just fun addon sensors that might trigger an action based on motion or temp.

                      The Reed switch can tell when the garage door is open or closed based on contact, and the relay's purpose is to provide a momentary "press" of the garage door wall control, ( I have it wired into the opener and relay ).

                      It currently works great, but on loss of power at the house ( The arduino is plugged in ), the relay trips on reload, causing the garage door to open / close, and well, if we are away from the house, this is obviously not good. ;)

                      I just tried implementing your change you recommended, and unfortunately on reboot, the relay still triggers. Ideally, if I could have the relay not trigger on reboot, then I would consider it safe. I'm sure it's possible, I just can't figure out how to not have it reset / trigger on AC power fail. The interface appears as follows:

                      0_1488935309554_upload-d5417f76-6875-4689-bc03-2fa7f45d760c

                      I did make the modification, but the results are the same, so I won't re paste the code block.

                      Thanks very much for the help @Boots33 if there are any other code mods I could make, I really would appreciate it.

                      Thanks!

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

                      @rhuehn

                      could you please explain the code shown below.
                      Why do you send this initial value
                      Why do you need to request the relay status.
                      Why does the reed switch status effect the relay status.

                      if (!initialValueSent) {
                          Serial.println("Sending initial value");
                          send(msg.set(state?RELAY_ON:RELAY_OFF));
                          Serial.println("Requesting initial value from controller");
                          request(CHILD_ID_REL, V_STATUS);
                          wait(2000, C_SET, V_STATUS);
                        }
                        if (debouncer.update()) {
                          if (debouncer.read()==LOW) {
                            state = !state;
                            // Send new state and request ack back
                            send(msg.set(state?RELAY_ON:RELAY_OFF), true);
                          }
                        }
                      

                      The code to receive an on signal from your controller could be as simple as shown below but I am not sure how the above code will work with that.

                      void receive(const MyMessage &message) {
                      /*  if (message.isAck()) {
                           Serial.println("This is an ack from gateway");
                        }
                        if (message.type == V_STATUS) {
                          if (!initialValueSent) {
                            Serial.println("Receiving initial value from controller");
                            initialValueSent = true;
                          }
                          // Change relay state
                          state = (bool)message.getInt();
                          digitalWrite(RELAY_PIN, state?RELAY_ON:RELAY_OFF);
                          //Keep the relay on for the amount of time defined by TOGGLE_INTERVAL
                          delay( TOGGLE_INTERVAL );
                          digitalWrite( RELAY_PIN, RELAY_OFF );
                          // Store state in eeprom
                          saveState(message.sensor, message.getBool());
                          send(msg.set(state?RELAY_ON:RELAY_OFF));
                        }
                      */
                       if (message.type == V_STATUS && message.sensor == CHILD_ID_REL && message.getBool == true) {
                          digitalWrite(RELAY_PIN, RELAY_ON);
                          //Keep the relay on for the amount of time defined by TOGGLE_INTERVAL
                          wait( TOGGLE_INTERVAL );
                          digitalWrite( RELAY_PIN, RELAY_OFF );               //turn relay off
                          send(msg.set(false), false);                       // send off state to controller, no ack requested
                       }  
                      }
                      
                      1 Reply Last reply
                      0
                      • Daniel OliveiraD Offline
                        Daniel OliveiraD Offline
                        Daniel Oliveira
                        wrote on last edited by
                        #13

                        Hi,

                        I'm not an expert and honestly I didn't read all the comments, but to avoid the relay to change status on reboots would not be a simpler solution to add a "flip-flop" mechanism that will "save" the last sate for some minutes?

                        Best regards

                        MySensors rules my home :)

                        1 Reply Last reply
                        0
                        • rhuehnR Offline
                          rhuehnR Offline
                          rhuehn
                          wrote on last edited by
                          #14

                          Hello @Boots33

                          The Reed switch should NOT have any effect on the relay. ( It shouldn't anyways, it only senses open / closed

                          From my understanding here:

                          https://home-assistant.io/components/mysensors/

                          It needs to be done in the loop function:

                          Present the sensor’s S_TYPE.
                          Send at least one initial value per V_TYPE. In version 2.0 of MySensors this has to be done in the loop function. See below for an example in 2.0 of how to make sure the initial value has been received by the controller.

                          Below is an example from that page:

                          /*
                           * Documentation: http://www.mysensors.org
                           * Support Forum: http://forum.mysensors.org
                           *
                           * http://www.mysensors.org/build/relay
                           */
                          
                          #define MY_DEBUG
                          #define MY_RADIO_NRF24
                          #define MY_REPEATER_FEATURE
                          #define MY_NODE_ID 1
                          #include <SPI.h>
                          #include <MySensors.h>
                          #include <Bounce2.h>
                          
                          #define RELAY_PIN  5
                          #define BUTTON_PIN  3
                          #define CHILD_ID 1
                          #define RELAY_ON 1
                          #define RELAY_OFF 0
                          
                          Bounce debouncer = Bounce();
                          bool state = false;
                          bool initialValueSent = false;
                          
                          MyMessage msg(CHILD_ID, V_STATUS);
                          
                          void setup()
                          {
                            pinMode(BUTTON_PIN, INPUT_PULLUP);
                            debouncer.attach(BUTTON_PIN);
                            debouncer.interval(10);
                          
                            // Make sure relays are off when starting up
                            digitalWrite(RELAY_PIN, RELAY_OFF);
                            pinMode(RELAY_PIN, OUTPUT);
                          }
                          
                          void presentation()  {
                            sendSketchInfo("Relay+button", "1.0");
                            present(CHILD_ID, S_BINARY);
                          }
                          
                          void loop()
                          {
                            if (!initialValueSent) {
                              Serial.println("Sending initial value");
                              send(msg.set(state?RELAY_ON:RELAY_OFF));
                              Serial.println("Requesting initial value from controller");
                              request(CHILD_ID, V_STATUS);
                              wait(2000, C_SET, V_STATUS);
                            }
                            if (debouncer.update()) {
                              if (debouncer.read()==LOW) {
                                state = !state;
                                // Send new state and request ack back
                                send(msg.set(state?RELAY_ON:RELAY_OFF), true);
                              }
                            }
                          }
                          
                          void receive(const MyMessage &message) {
                            if (message.isAck()) {
                               Serial.println("This is an ack from gateway");
                            }
                          
                            if (message.type == V_STATUS) {
                              if (!initialValueSent) {
                                Serial.println("Receiving initial value from controller");
                                initialValueSent = true;
                              }
                              // Change relay state
                              state = (bool)message.getInt();
                              digitalWrite(RELAY_PIN, state?RELAY_ON:RELAY_OFF);
                              send(msg.set(state?RELAY_ON:RELAY_OFF));
                            }
                          }
                          

                          I was just following some guidelines to use HASS+ My Sensors together.

                          Boots33B 1 Reply Last reply
                          0
                          • rhuehnR rhuehn

                            Hello @Boots33

                            The Reed switch should NOT have any effect on the relay. ( It shouldn't anyways, it only senses open / closed

                            From my understanding here:

                            https://home-assistant.io/components/mysensors/

                            It needs to be done in the loop function:

                            Present the sensor’s S_TYPE.
                            Send at least one initial value per V_TYPE. In version 2.0 of MySensors this has to be done in the loop function. See below for an example in 2.0 of how to make sure the initial value has been received by the controller.

                            Below is an example from that page:

                            /*
                             * Documentation: http://www.mysensors.org
                             * Support Forum: http://forum.mysensors.org
                             *
                             * http://www.mysensors.org/build/relay
                             */
                            
                            #define MY_DEBUG
                            #define MY_RADIO_NRF24
                            #define MY_REPEATER_FEATURE
                            #define MY_NODE_ID 1
                            #include <SPI.h>
                            #include <MySensors.h>
                            #include <Bounce2.h>
                            
                            #define RELAY_PIN  5
                            #define BUTTON_PIN  3
                            #define CHILD_ID 1
                            #define RELAY_ON 1
                            #define RELAY_OFF 0
                            
                            Bounce debouncer = Bounce();
                            bool state = false;
                            bool initialValueSent = false;
                            
                            MyMessage msg(CHILD_ID, V_STATUS);
                            
                            void setup()
                            {
                              pinMode(BUTTON_PIN, INPUT_PULLUP);
                              debouncer.attach(BUTTON_PIN);
                              debouncer.interval(10);
                            
                              // Make sure relays are off when starting up
                              digitalWrite(RELAY_PIN, RELAY_OFF);
                              pinMode(RELAY_PIN, OUTPUT);
                            }
                            
                            void presentation()  {
                              sendSketchInfo("Relay+button", "1.0");
                              present(CHILD_ID, S_BINARY);
                            }
                            
                            void loop()
                            {
                              if (!initialValueSent) {
                                Serial.println("Sending initial value");
                                send(msg.set(state?RELAY_ON:RELAY_OFF));
                                Serial.println("Requesting initial value from controller");
                                request(CHILD_ID, V_STATUS);
                                wait(2000, C_SET, V_STATUS);
                              }
                              if (debouncer.update()) {
                                if (debouncer.read()==LOW) {
                                  state = !state;
                                  // Send new state and request ack back
                                  send(msg.set(state?RELAY_ON:RELAY_OFF), true);
                                }
                              }
                            }
                            
                            void receive(const MyMessage &message) {
                              if (message.isAck()) {
                                 Serial.println("This is an ack from gateway");
                              }
                            
                              if (message.type == V_STATUS) {
                                if (!initialValueSent) {
                                  Serial.println("Receiving initial value from controller");
                                  initialValueSent = true;
                                }
                                // Change relay state
                                state = (bool)message.getInt();
                                digitalWrite(RELAY_PIN, state?RELAY_ON:RELAY_OFF);
                                send(msg.set(state?RELAY_ON:RELAY_OFF));
                              }
                            }
                            

                            I was just following some guidelines to use HASS+ My Sensors together.

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

                            @rhuehn Ahh... I use Domoticz so was unaware of HA's need for the extra code to register the node.

                            So the problem you face is then likely the code below the registration code.
                            This code is using the bouncer instance which you have connected to your reed switch and then sends a message to change the state of your relay.

                            if (debouncer.update()) {
                                if (debouncer.read()==LOW) {
                                  state = !state;
                                  // Send new state and request ack back
                                  send(msg.set(state?RELAY_ON:RELAY_OFF), true);
                                }
                              }
                            

                            So if you could can you try these 2 changes to your code and see if we are any close to the desired result :)
                            I have changed the initial code slightly to just sen an off state for the switch. It should make no difference as all you are needing is an initial response from the sensor.
                            I have also commented out the bouncer code

                             if (!initialValueSent) {
                                Serial.println("Sending initial value");
                                //send(msg.set(state?RELAY_ON:RELAY_OFF));
                                send(msg.set(RELAY_OFF));
                                Serial.println("Requesting initial value from controller");
                                request(CHILD_ID_REL, V_STATUS);
                                wait(2000, C_SET, V_STATUS);
                              }
                              /*
                              if (debouncer.update()) {
                                if (debouncer.read()==LOW) {
                                  state = !state;
                                  // Send new state and request ack back
                                  send(msg.set(state?RELAY_ON:RELAY_OFF), true);
                                }
                              }
                             */
                            

                            Then change your receive code to

                            void receive(const MyMessage &message) {
                              if (message.isAck()) {
                                 Serial.println("This is an ack from gateway");
                              }
                              if (message.type == V_STATUS) {
                                if (!initialValueSent) {
                                  Serial.println("Receiving initial value from controller");
                                  initialValueSent = true;
                                }
                            /*    // Change relay state
                                state = (bool)message.getInt();
                                digitalWrite(RELAY_PIN, state?RELAY_ON:RELAY_OFF);
                                //Keep the relay on for the amount of time defined by TOGGLE_INTERVAL
                                delay( TOGGLE_INTERVAL );
                                digitalWrite( RELAY_PIN, RELAY_OFF );
                                // Store state in eeprom
                                saveState(message.sensor, message.getBool());
                                send(msg.set(state?RELAY_ON:RELAY_OFF));
                              }
                            */
                            
                            else if (message.sensor == CHILD_ID_REL && message.getBool == true) {
                                digitalWrite(RELAY_PIN, RELAY_ON);
                                //Keep the relay on for the amount of time defined by TOGGLE_INTERVAL
                                wait( TOGGLE_INTERVAL );
                                digitalWrite( RELAY_PIN, RELAY_OFF );               //turn relay off
                                send(msg.set(false), false);                       // send off state to controller, no ack requested
                             }  
                            }
                            
                            
                            1 Reply Last reply
                            0
                            • BrydenB Offline
                              BrydenB Offline
                              Bryden
                              wrote on last edited by
                              #16

                              What type of relay are you using?

                              My guess is a LOW TRIGGER relay, which is bad for this task.

                              If you are using a low trigger relay the fault is in the hardware not the code.

                              The microcontroller takes time to reboot and enable a high to keep the relay open.

                              When you loose power, your microcontroller is going to take time to reboot,
                              But I bet your power supply is going to instantly give power to your relay board,
                              hence there is a small period in time where there is a ground on your pin before the initial setup of the pin to high in the microcontroller, causing your relay to trigger.

                              This is why I hate low trigger relays, they are useless when it comes to power interrupts and you're trusting your house security to them.

                              My suggestions to test my theory, then you will know where your fault lies.

                              throw an LED on your relay out to light up when switched high, Apply power to your microcontroller and see how long it takes for the relay to turn on.

                              Why do people use low level relays?
                              Output pins are generally 3.3v, that's not enough voltage to trigger most high level relays, using a low level trigger overcomes this.

                              Use a high level relay, but you will need a transistor circuit to feed it 5v as the 3.3v generally wont trigger the relay with a high output.

                              hopefully my rant helps

                              Boots33B 1 Reply Last reply
                              0
                              • BrydenB Offline
                                BrydenB Offline
                                Bryden
                                wrote on last edited by
                                #17

                                I noticed on my ESP8266-01b that it does power surge a voltage during initial power up as well, also bad for a high level relay

                                1 Reply Last reply
                                0
                                • BrydenB Bryden

                                  What type of relay are you using?

                                  My guess is a LOW TRIGGER relay, which is bad for this task.

                                  If you are using a low trigger relay the fault is in the hardware not the code.

                                  The microcontroller takes time to reboot and enable a high to keep the relay open.

                                  When you loose power, your microcontroller is going to take time to reboot,
                                  But I bet your power supply is going to instantly give power to your relay board,
                                  hence there is a small period in time where there is a ground on your pin before the initial setup of the pin to high in the microcontroller, causing your relay to trigger.

                                  This is why I hate low trigger relays, they are useless when it comes to power interrupts and you're trusting your house security to them.

                                  My suggestions to test my theory, then you will know where your fault lies.

                                  throw an LED on your relay out to light up when switched high, Apply power to your microcontroller and see how long it takes for the relay to turn on.

                                  Why do people use low level relays?
                                  Output pins are generally 3.3v, that's not enough voltage to trigger most high level relays, using a low level trigger overcomes this.

                                  Use a high level relay, but you will need a transistor circuit to feed it 5v as the 3.3v generally wont trigger the relay with a high output.

                                  hopefully my rant helps

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

                                  @Bryden thanks for your input. In the code the relay is switched high for on and low for off so it should not be the type of relay to cause problems . Worth checking though.

                                  1 Reply Last reply
                                  0
                                  • BrydenB Offline
                                    BrydenB Offline
                                    Bryden
                                    wrote on last edited by
                                    #19

                                    check to see if the output pins are having any voltage applied on initial boot as well.
                                    As mentioned I had an esp8266-01b on my desk here, and when power was applied I saw voltage on one of the gpio's intermittently.

                                    1 Reply Last reply
                                    0
                                    • rhuehnR Offline
                                      rhuehnR Offline
                                      rhuehn
                                      wrote on last edited by
                                      #20

                                      Hey guys! Thanks so very much for all the great comments. I haven't replied in a few days as I wanted to go back to the drawing board..... I didn't like that sketch, the sleep functions, etc etc.... It didn't also make sense clearly based on everyone's feedback ( Sorry I am just getting started with IDE... ) So, based on that, I've come up with the following, and if you could comment, modify where I messed up, it would be greatly appreciated. This sketch seems to work, and keep state on power LOSS. There's a relay for the garage door ( trigger, PIN 4 ), a reed switch to detect if the door is open or closed ( PIN 2 ), a DHT for Temp / Humidity ( PIN 7 ), and a PIR ( PIN 3 ) for motion activated events. Below is the sketch, and would really appreciate any great feedback.

                                      Thanks again!

                                      
                                      #define MY_DEBUG
                                      #define MY_RADIO_NRF24
                                      #define MY_REPEATER_FEATURE
                                      #define MY_NODE_ID 50
                                      
                                      #include <SPI.h>
                                      #include <MySensors.h>
                                      #include <Bounce2.h>
                                      #include <DHT.h>
                                      
                                      #define RELAY_1  4  // Arduino Digital I/O pin number for first relay (second on pin+1 etc)
                                      #define NUMBER_OF_RELAYS 1 // Total number of attached relays
                                      #define RELAY_ON 1  // GPIO value to write to turn on attached relay
                                      #define RELAY_OFF 0 // GPIO value to write to turn off attached relay
                                      #define TOGGLE_INTERVAL 350
                                      
                                      #define CHILD_ID_SW 2
                                      #define BUTTON_PIN  2  // Arduino Digital I/O pin for button/reed switch
                                      
                                      // Sleep time between sensor updates (in milliseconds)
                                      // Must be >1000ms for DHT22 and >2000ms for DHT11
                                      static const uint64_t UPDATE_INTERVAL = 60000;
                                      
                                      // Force sending an update of the temperature after n sensor reads, so a controller showing the
                                      // timestamp of the last update doesn't show something like 3 hours in the unlikely case, that
                                      // the value didn't change since;
                                      // i.e. the sensor would force sending an update every UPDATE_INTERVAL*FORCE_UPDATE_N_READS [ms]
                                      static const uint8_t FORCE_UPDATE_N_READS = 10;
                                      
                                      float lastTemp;
                                      float lastHum;
                                      uint8_t nNoUpdatesTemp;
                                      uint8_t nNoUpdatesHum;
                                      bool metric = true;
                                      
                                      #define CHILD_ID_HUM 10
                                      #define CHILD_ID_TEMP 11
                                      #define HUMIDITY_SENSOR_DIGITAL_PIN 7
                                      
                                      // Set this offset if the sensor has a permanent small offset to the real temperatures
                                      #define SENSOR_TEMP_OFFSET -1
                                      
                                      #define CHILD_ID_PIR 3
                                      #define PIR_PIN 3
                                      
                                      byte StatePIR=0;
                                      byte oldStatePIR=0;
                                      
                                      Bounce debouncer = Bounce(); 
                                      int oldValue=-1;
                                      
                                      MyMessage msgSw(CHILD_ID_SW,V_TRIPPED);
                                      MyMessage msgHum(CHILD_ID_HUM, V_HUM); // 1
                                      MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP); // 0
                                      MyMessage msgPir(CHILD_ID_PIR, V_TRIPPED);
                                      
                                      DHT dht;
                                      
                                      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()
                                      {
                                      
                                        dht.setup(HUMIDITY_SENSOR_DIGITAL_PIN); // set data pin of DHT sensor
                                        if (UPDATE_INTERVAL <= dht.getMinimumSamplingPeriod()) {
                                          Serial.println("Warning: UPDATE_INTERVAL is smaller than supported by the sensor!");
                                        }
                                        // Sleep for the time of the minimum sampling period to give the sensor time to power up
                                        // (otherwise, timeout errors might occure for the first reading)
                                        sleep(dht.getMinimumSamplingPeriod());
                                      
                                        pinMode(PIR_PIN, INPUT_PULLUP);
                                        // Setup the button
                                        pinMode(BUTTON_PIN,INPUT);
                                        // Activate internal pull-up
                                        digitalWrite(BUTTON_PIN,HIGH);
                                      
                                        // After setting up the button, setup debouncer
                                        debouncer.attach(BUTTON_PIN);
                                        debouncer.interval(5);
                                      }
                                      
                                      void presentation()
                                      {
                                          // Send the sketch version information to the gateway and Controller
                                          sendSketchInfo("Garage Multi Sensor", "1.0");
                                      
                                          for (int sensor=1, pin=RELAY_1; sensor<=NUMBER_OF_RELAYS; sensor++, pin++) {
                                              // Register all sensors to gw (they will be created as child devices)
                                              present(sensor, S_BINARY);
                                              present(CHILD_ID_SW, S_DOOR);
                                              present(CHILD_ID_HUM, S_HUM);
                                              present(CHILD_ID_TEMP, S_TEMP);
                                              present(CHILD_ID_PIR, S_MOTION);
                                      
                                              metric = getConfig().isMetric;
                                          }
                                      }
                                      
                                      void loop()
                                      {
                                      
                                      StatePIR=digitalRead(PIR_PIN);
                                        if (StatePIR != oldStatePIR) {
                                          oldStatePIR=StatePIR;
                                          send(msgPir.set(StatePIR ? "ON" : "OFF"));
                                        
                                        // Force reading sensor, so it works also after sleep()
                                        dht.readSensor(true);
                                      
                                        // Get temperature from DHT library
                                        float temperature = dht.getTemperature();
                                        if (isnan(temperature)) {
                                          Serial.println("Failed reading temperature from DHT!");
                                        } else if (temperature != lastTemp || nNoUpdatesTemp == FORCE_UPDATE_N_READS) {
                                          // Only send temperature if it changed since the last measurement or if we didn't send an update for n times
                                          lastTemp = temperature;
                                          if (!metric) {
                                            temperature = dht.toFahrenheit(temperature);
                                          }
                                          // Reset no updates counter
                                          nNoUpdatesTemp = 0;
                                          temperature += SENSOR_TEMP_OFFSET;
                                          send(msgTemp.set(temperature, 1));
                                      
                                          #ifdef MY_DEBUG
                                          Serial.print("T: ");
                                          Serial.println(temperature);
                                          #endif
                                        } else {
                                          // Increase no update counter if the temperature stayed the same
                                          nNoUpdatesTemp++;
                                        }
                                      
                                        // Get humidity from DHT library
                                        float humidity = dht.getHumidity();
                                        if (isnan(humidity)) {
                                          Serial.println("Failed reading humidity from DHT");
                                        } else if (humidity != lastHum || nNoUpdatesHum == FORCE_UPDATE_N_READS) {
                                          // Only send humidity if it changed since the last measurement or if we didn't send an update for n times
                                          lastHum = humidity;
                                          // Reset no updates counter
                                          nNoUpdatesHum = 0;
                                          send(msgHum.set(humidity, 1));
                                      
                                          #ifdef MY_DEBUG
                                          Serial.print("H: ");
                                          Serial.println(humidity);
                                          #endif
                                        } else {
                                          // Increase no update counter if the humidity stayed the same
                                          nNoUpdatesHum++;
                                        }
                                      
                                      }
                                      
                                        debouncer.update();
                                        // Get the update value
                                        int value = debouncer.read();
                                      
                                        if (value != oldValue) {
                                           // Send in the new value
                                           send(msgSw.set(value==HIGH ? 1 : 0));
                                           oldValue = value;
                                        }
                                      }
                                      
                                      void receive(const MyMessage &message)
                                      {
                                          // We only expect one type of message from controller. But we better check anyway.
                                          if (message.type==V_STATUS) {
                                              // Change relay state
                                              digitalWrite(message.sensor-1+RELAY_1, message.getBool()?RELAY_ON:RELAY_OFF);
                                              //Keep the relay on for the amount of time defined by TOGGLE_INTERVAL
                                              delay( TOGGLE_INTERVAL );
                                              digitalWrite( RELAY_1, RELAY_OFF );
                                              // Store state in eeprom
                                              saveState(message.sensor, message.getBool());
                                              // Write some debug info
                                              Serial.print("Incoming change for sensor:");
                                              Serial.print(message.sensor);
                                              Serial.print(", New status: ");
                                              Serial.println(message.getBool());
                                          }
                                      }
                                      
                                      B 1 Reply Last reply
                                      0
                                      • D Offline
                                        D Offline
                                        djzang
                                        wrote on last edited by
                                        #21

                                        I'm wondering if its not your code that is bringing the PIN high momentarily during boot up but the device or boot loader itself. Try flashing it with blank code and power cycle it and see if it triggers the relay still. If it does then you may need to put a pullup resistor on the pin to prevent it from happening.

                                        1 Reply Last reply
                                        0
                                        • rhuehnR rhuehn

                                          Hey guys! Thanks so very much for all the great comments. I haven't replied in a few days as I wanted to go back to the drawing board..... I didn't like that sketch, the sleep functions, etc etc.... It didn't also make sense clearly based on everyone's feedback ( Sorry I am just getting started with IDE... ) So, based on that, I've come up with the following, and if you could comment, modify where I messed up, it would be greatly appreciated. This sketch seems to work, and keep state on power LOSS. There's a relay for the garage door ( trigger, PIN 4 ), a reed switch to detect if the door is open or closed ( PIN 2 ), a DHT for Temp / Humidity ( PIN 7 ), and a PIR ( PIN 3 ) for motion activated events. Below is the sketch, and would really appreciate any great feedback.

                                          Thanks again!

                                          
                                          #define MY_DEBUG
                                          #define MY_RADIO_NRF24
                                          #define MY_REPEATER_FEATURE
                                          #define MY_NODE_ID 50
                                          
                                          #include <SPI.h>
                                          #include <MySensors.h>
                                          #include <Bounce2.h>
                                          #include <DHT.h>
                                          
                                          #define RELAY_1  4  // Arduino Digital I/O pin number for first relay (second on pin+1 etc)
                                          #define NUMBER_OF_RELAYS 1 // Total number of attached relays
                                          #define RELAY_ON 1  // GPIO value to write to turn on attached relay
                                          #define RELAY_OFF 0 // GPIO value to write to turn off attached relay
                                          #define TOGGLE_INTERVAL 350
                                          
                                          #define CHILD_ID_SW 2
                                          #define BUTTON_PIN  2  // Arduino Digital I/O pin for button/reed switch
                                          
                                          // Sleep time between sensor updates (in milliseconds)
                                          // Must be >1000ms for DHT22 and >2000ms for DHT11
                                          static const uint64_t UPDATE_INTERVAL = 60000;
                                          
                                          // Force sending an update of the temperature after n sensor reads, so a controller showing the
                                          // timestamp of the last update doesn't show something like 3 hours in the unlikely case, that
                                          // the value didn't change since;
                                          // i.e. the sensor would force sending an update every UPDATE_INTERVAL*FORCE_UPDATE_N_READS [ms]
                                          static const uint8_t FORCE_UPDATE_N_READS = 10;
                                          
                                          float lastTemp;
                                          float lastHum;
                                          uint8_t nNoUpdatesTemp;
                                          uint8_t nNoUpdatesHum;
                                          bool metric = true;
                                          
                                          #define CHILD_ID_HUM 10
                                          #define CHILD_ID_TEMP 11
                                          #define HUMIDITY_SENSOR_DIGITAL_PIN 7
                                          
                                          // Set this offset if the sensor has a permanent small offset to the real temperatures
                                          #define SENSOR_TEMP_OFFSET -1
                                          
                                          #define CHILD_ID_PIR 3
                                          #define PIR_PIN 3
                                          
                                          byte StatePIR=0;
                                          byte oldStatePIR=0;
                                          
                                          Bounce debouncer = Bounce(); 
                                          int oldValue=-1;
                                          
                                          MyMessage msgSw(CHILD_ID_SW,V_TRIPPED);
                                          MyMessage msgHum(CHILD_ID_HUM, V_HUM); // 1
                                          MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP); // 0
                                          MyMessage msgPir(CHILD_ID_PIR, V_TRIPPED);
                                          
                                          DHT dht;
                                          
                                          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()
                                          {
                                          
                                            dht.setup(HUMIDITY_SENSOR_DIGITAL_PIN); // set data pin of DHT sensor
                                            if (UPDATE_INTERVAL <= dht.getMinimumSamplingPeriod()) {
                                              Serial.println("Warning: UPDATE_INTERVAL is smaller than supported by the sensor!");
                                            }
                                            // Sleep for the time of the minimum sampling period to give the sensor time to power up
                                            // (otherwise, timeout errors might occure for the first reading)
                                            sleep(dht.getMinimumSamplingPeriod());
                                          
                                            pinMode(PIR_PIN, INPUT_PULLUP);
                                            // Setup the button
                                            pinMode(BUTTON_PIN,INPUT);
                                            // Activate internal pull-up
                                            digitalWrite(BUTTON_PIN,HIGH);
                                          
                                            // After setting up the button, setup debouncer
                                            debouncer.attach(BUTTON_PIN);
                                            debouncer.interval(5);
                                          }
                                          
                                          void presentation()
                                          {
                                              // Send the sketch version information to the gateway and Controller
                                              sendSketchInfo("Garage Multi Sensor", "1.0");
                                          
                                              for (int sensor=1, pin=RELAY_1; sensor<=NUMBER_OF_RELAYS; sensor++, pin++) {
                                                  // Register all sensors to gw (they will be created as child devices)
                                                  present(sensor, S_BINARY);
                                                  present(CHILD_ID_SW, S_DOOR);
                                                  present(CHILD_ID_HUM, S_HUM);
                                                  present(CHILD_ID_TEMP, S_TEMP);
                                                  present(CHILD_ID_PIR, S_MOTION);
                                          
                                                  metric = getConfig().isMetric;
                                              }
                                          }
                                          
                                          void loop()
                                          {
                                          
                                          StatePIR=digitalRead(PIR_PIN);
                                            if (StatePIR != oldStatePIR) {
                                              oldStatePIR=StatePIR;
                                              send(msgPir.set(StatePIR ? "ON" : "OFF"));
                                            
                                            // Force reading sensor, so it works also after sleep()
                                            dht.readSensor(true);
                                          
                                            // Get temperature from DHT library
                                            float temperature = dht.getTemperature();
                                            if (isnan(temperature)) {
                                              Serial.println("Failed reading temperature from DHT!");
                                            } else if (temperature != lastTemp || nNoUpdatesTemp == FORCE_UPDATE_N_READS) {
                                              // Only send temperature if it changed since the last measurement or if we didn't send an update for n times
                                              lastTemp = temperature;
                                              if (!metric) {
                                                temperature = dht.toFahrenheit(temperature);
                                              }
                                              // Reset no updates counter
                                              nNoUpdatesTemp = 0;
                                              temperature += SENSOR_TEMP_OFFSET;
                                              send(msgTemp.set(temperature, 1));
                                          
                                              #ifdef MY_DEBUG
                                              Serial.print("T: ");
                                              Serial.println(temperature);
                                              #endif
                                            } else {
                                              // Increase no update counter if the temperature stayed the same
                                              nNoUpdatesTemp++;
                                            }
                                          
                                            // Get humidity from DHT library
                                            float humidity = dht.getHumidity();
                                            if (isnan(humidity)) {
                                              Serial.println("Failed reading humidity from DHT");
                                            } else if (humidity != lastHum || nNoUpdatesHum == FORCE_UPDATE_N_READS) {
                                              // Only send humidity if it changed since the last measurement or if we didn't send an update for n times
                                              lastHum = humidity;
                                              // Reset no updates counter
                                              nNoUpdatesHum = 0;
                                              send(msgHum.set(humidity, 1));
                                          
                                              #ifdef MY_DEBUG
                                              Serial.print("H: ");
                                              Serial.println(humidity);
                                              #endif
                                            } else {
                                              // Increase no update counter if the humidity stayed the same
                                              nNoUpdatesHum++;
                                            }
                                          
                                          }
                                          
                                            debouncer.update();
                                            // Get the update value
                                            int value = debouncer.read();
                                          
                                            if (value != oldValue) {
                                               // Send in the new value
                                               send(msgSw.set(value==HIGH ? 1 : 0));
                                               oldValue = value;
                                            }
                                          }
                                          
                                          void receive(const MyMessage &message)
                                          {
                                              // We only expect one type of message from controller. But we better check anyway.
                                              if (message.type==V_STATUS) {
                                                  // Change relay state
                                                  digitalWrite(message.sensor-1+RELAY_1, message.getBool()?RELAY_ON:RELAY_OFF);
                                                  //Keep the relay on for the amount of time defined by TOGGLE_INTERVAL
                                                  delay( TOGGLE_INTERVAL );
                                                  digitalWrite( RELAY_1, RELAY_OFF );
                                                  // Store state in eeprom
                                                  saveState(message.sensor, message.getBool());
                                                  // Write some debug info
                                                  Serial.print("Incoming change for sensor:");
                                                  Serial.print(message.sensor);
                                                  Serial.print(", New status: ");
                                                  Serial.println(message.getBool());
                                              }
                                          }
                                          
                                          B Offline
                                          B Offline
                                          Ben Andrewes
                                          wrote on last edited by
                                          #22

                                          @rhuehn I know this is an old post but I had a similar issue which I solved by inserting a line in my sketch to pull the pin high before setting it as output

                                            digitalWrite(RELAY_1_PIN , HIGH);  //stops relays cycling state during boot
                                            digitalWrite(RELAY_2_PIN , HIGH);  //stops relays cycling state during boot
                                            
                                            pinMode(RELAY_1_PIN , OUTPUT);
                                            pinMode(RELAY_2_PIN , OUTPUT);
                                          
                                          1 Reply Last reply
                                          0
                                          Reply
                                          • Reply as topic
                                          Log in to reply
                                          • Oldest to Newest
                                          • Newest to Oldest
                                          • Most Votes


                                          19

                                          Online

                                          11.7k

                                          Users

                                          11.2k

                                          Topics

                                          113.0k

                                          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