gw.sleep on battery powered magnet door switch



  • Hi all,

    I have made a magnet door contact using a Arduino mini Pro 3v3 powered with 2 coin cells battery. To save battery life, I want to use gw.sleep to let the Arduino mini to sleep and trigger when the door is open.

    Unfortunately, the arduino is not trigger when contact is open or closed due to gw.sleep. I was wonder how to use the sleep comment and still making the debounce action works. I have tried to use INTERRUPT but with no luck.

    Thanks

    /**
     * The MySensors Arduino library handles the wireless radio link and protocol
     * between your home built sensors/actuators and HA controller of choice.
     * The sensors forms a self healing radio network with optional repeaters. Each
     * repeater and gateway builds a routing tables in EEPROM which keeps track of the
     * network topology allowing messages to be routed to nodes.
     *
     * Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
     * Copyright (C) 2013-2015 Sensnology AB
     * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
     *
     * Documentation: http://www.mysensors.org
     * Support Forum: http://forum.mysensors.org
     *
     * This program is free software; you can redistribute it and/or
     * modify it under the terms of the GNU General Public License
     * version 2 as published by the Free Software Foundation.
     *
     *******************************
     *
     * DESCRIPTION
     *
     * Simple binary switch example 
     * Connect button or door/window reed switch between 
     * digitial I/O pin 3 (BUTTON_PIN below) and GND.
     * http://www.mysensors.org/build/binary
     */
    
    
    #include <MySensor.h>
    #include <SPI.h>
    #include <Bounce2.h>
    
    #define CHILD_ID 3
    #define BUTTON_PIN  3  // Arduino Digital I/O pin for button/reed switch
    #define INTERRUPT BUTTON_PIN -2 // Usually the interrupt = pin -2 (on uno/nano anyway)
    unsigned long SLEEP_TIME = 120000; // Sleep time between reports (in milliseconds)
    
    MySensor gw;
    Bounce debouncer = Bounce(); 
    int oldValue=-1;
    
    // Change to V_LIGHT if you use S_LIGHT in presentation below
    MyMessage msg(CHILD_ID,V_TRIPPED);
    
    void setup()  
    {  
      gw.begin();
    
     // 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);
      
      // Register binary input sensor to gw (they will be created as child devices)
      // You can use S_DOOR, S_MOTION or S_LIGHT here depending on your usage. 
      // If S_LIGHT is used, remember to update variable type you send in. See "msg" above.
      gw.present(CHILD_ID, S_DOOR);  
    }
    
    
    //  Check if digital input has changed and send in new value
    void loop() 
    {
      debouncer.update();
      // Get the update value
      int value = debouncer.read();
     
      if (value != oldValue) {
         // Send in the new value
         gw.send(msg.set(value==HIGH ? 1 : 0));
         oldValue = value;
      }
     
      gw.sleep(INTERRUPT,CHANGE, SLEEP_TIME);
      
      
    } 
    
    

  • Hardware Contributor

    @Chakkie - Looks right, Do you see anything in the serial debug log when you try?


  • Mod

    The code looks ok to me (except that you might as well set SLEEP_TIME to 0 since the loop only will report on change, regardless of the sleep time).
    Maybe add a few Serial.println statements in different parts of the loop so you can debug what happens?



  • @sundberg84

    I have added some print to debugged. It seems like the code with sleep does not verify and send the high 1 or low 0 when I open and close the contact. See the serial debug log. The repeated sleep in the log is when i open and close the contact. Normally it will send 1 or 0 " send: 204-204-0-0 s=3,c=1,t=16,pt=2,l=2,sg=0,st=ok:0"

    void loop() 
    {
      debouncer.update();
      // Get the update value
      int value = debouncer.read();
    
      if (value != oldValue) {
         // Send in the new value
         Serial.println("Trigger");
         gw.send(msg.set(value==HIGH ? 1 : 0));
         oldValue = value;
      }     
      gw.sleep(INTERRUPT,CHANGE, SLEEP_TIME);
      Serial.println("Sleep");
    
    send: 204-204-0-0 s=255,c=3,t=15,pt=2,l=2,sg=0,st=ok:0
    send: 204-204-0-0 s=255,c=0,t=17,pt=0,l=5,sg=0,st=ok:1.5.4
    send: 204-204-0-0 s=255,c=3,t=6,pt=1,l=1,sg=0,st=ok:0
    read: 0-0-204 s=255,c=3,t=6,pt=0,l=1,sg=0:M
    sensor started, id=204, parent=0, distance=1
    send: 204-204-0-0 s=3,c=0,t=0,pt=0,l=0,sg=0,st=ok:
    Trigger
    send: 204-204-0-0 s=3,c=1,t=16,pt=2,l=2,sg=0,st=ok:0
    Sleep
    Sleep
    Sleep
    Sleep
    Sleep
    Sleep
    Sleep
    Sleep
    


  • @mfalkvidd Hi thanks

    Changing the sleep time to 0 does not help. When I open and close the contact the status will not be sent. That's weird


  • Hardware Contributor

    @Chakkie - add a debugline and see what value and oldvalue says.
    See if you can measure the input when you close the contact and when its open so its not a hardware failure.


  • Hero Member

    @Chakkie debouncer does not function when you use the sleep function. Reason is that sleep puts the internal timer which is used by debouncer to rest. Remove the debouncer routine and debounce by including a gw.wait(40) before going to sleep. This avoids a retrigger by an eventual contact bounce.



  • @sundberg84 I have debugged a several times. I am now sure it is not a hardware failure.



  • @AWI Thank you so much. Yes I have came to the conclusion that the debouncer does not seems to work fine with sleep function. So I have used a method other than debouncer.

    Here the working script below:

    #include <MySensor.h>
    #include <SPI.h>
    
    
    #define CHILD_ID_Deur 11
    #define CHILD_ID_Post 12
    #define BUTTON_PIN_Deur  2  // Arduino Digital I/O pin for button/reed switch
    #define BUTTON_PIN_Post  3  // Arduino Digital I/O pin for button/reed switch
    
    MySensor gw;
    
    
    // Change to V_LIGHT if you use S_LIGHT in presentation below
    MyMessage msgDeur(CHILD_ID_Deur,V_TRIPPED);
    MyMessage msgPost(CHILD_ID_Post,V_TRIPPED);
    
    void setup()  
    {  
      gw.begin();
    gw.sendSketchInfo("Voordeur contacts", "1.0");
     // Setup the button
      pinMode(BUTTON_PIN_Deur,INPUT);
      pinMode(BUTTON_PIN_Post,INPUT);
      // Activate internal pull-up
      digitalWrite(BUTTON_PIN_Deur,HIGH);
      digitalWrite(BUTTON_PIN_Post,HIGH);
    
      // Register binary input sensor to gw (they will be created as child devices)
      // You can use S_DOOR, S_MOTION or S_LIGHT here depending on your usage. 
      // If S_LIGHT is used, remember to update variable type you send in. See "msg" above.
      gw.present(CHILD_ID_Deur, S_DOOR);
      gw.present(CHILD_ID_Post, S_DOOR);   
    }
    
    
    //  Check if digital input has changed and send in new value
    void loop() 
    {
      uint8_t value;
      static uint8_t sentValue = 2;
      static uint8_t sentValue2 = 2;
    
      // Short delay to allow buttons to properly settle
      gw.sleep(5);
    
      value = digitalRead(BUTTON_PIN_Deur);
    
      if (value != sentValue) {
        // Value has changed from last transmission, send the updated value
        gw.send(msgDeur.set(value == HIGH ? 1 : 0));
        sentValue = value;
      }
    
      value = digitalRead(BUTTON_PIN_Post);
    
      if (value != sentValue2) {
        // Value has changed from last transmission, send the updated value
        gw.send(msgPost.set(value == HIGH ? 1 : 0));
        sentValue2 = value;
      }
    
    
      // Sleep until something happens with the sensor
      gw.sleep(BUTTON_PIN_Deur - 2, CHANGE, BUTTON_PIN_Post - 2, CHANGE, 86400000);// changing Secondary button to correct pin (-3) does not work. So keep it on (-2)
      Serial.println("Sleep");
    
    }
    
    

    Notice that the script does not work properly when I set BUTTON_PIN_Post - 3. The button pin post will not trigger. But when I change it to -2, both switches will work

    gw.sleep(BUTTON_PIN_Deur - 2, CHANGE, BUTTON_PIN_Post - 2, CHANGE, 86400000);
    

  • Hero Member

    @Chakkie Good to hear. Using "-3" makes the interrupt number the same for _Deur and _Post. Using -2 activates both interrupt 0 and 1.
    You'r ready for the next project..


  • Mod

    We should really get rid of the confusing "- 2" stuff in the examples and start using DigtalPinToInterrupt instead.
    I'm annoyed enough to see if I can create a pull request later this week.



  • @AWI Thanks. By the way would you care to explain the interrupt index number? or may be a link for explanation?


  • Hero Member

    @Chakkie In a few words.. The ATMEGA has two external interrupts 0 and 1 which are connected to pins 2 and 3. ("-2" translates the pin number to the interrupt number, which is rather confusing as @mfalkvidd meant)



  • @mfalkvidd Thanks for the info. Does DigitalPinTolnterrupt works better?



  • @AWI Thanks this clear thinks up but at the same time also confusing too.

    So "-2" activates both 0 and 1 on pin 2 or pin 3 as you mentioned earlier. I always though it represents a pin number.


  • Hero Member

    @Chakkie The function digitalPinToInterrupt(pin) translates the pin number to the attached interrupt like "-2" does but in a reliable and more understandable way.



  • @AWI thanks. this looks like more promising.


  • Mod

    Pull request done for the development version: https://github.com/mysensors/Arduino/pull/441



  • I would like to build the same but I am still very confused now. Could you upload some pictures so I can make myself an image of how you wirde things together?

    Also I don´t really understand what happens here: gw.sleep(BUTTON_PIN_Deur - 2, CHANGE, BUTTON_PIN_Post - 2, CHANGE, 86400000);


  • Hero Member

    @siod If you are using a "standard" Atmega328 (pro-mini, etc.) don't make it hard for yourself. This processor has two external interrupts (0 & 1) connected to pins 2 & 3. Taking your line of code gw.sleep(BUTTON_PIN_Deur - 2, CHANGE, BUTTON_PIN_Post - 2, CHANGE, 86400000); the arguments are respectively:

    1. Use interrupt "0" (connected to pin 2 is BUTTON_PIN_Deur)
    2. Have is fired on change (i.e Rising and Falling)
    3. Use interrupt "1" (connected to pin 3 is BUTTON_PIN_Post)
    4. Have is fired on change (i.e Rising and Falling)
    5. Wake after every 86400000 ms (24 hrs) if no interrupt fired. To be safe you should use 86400000UL (the UL indicating that it is an Unsigned long type)

Log in to reply
 

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