Doorbell node



  • Not quite sure how to do this but I think I'm on the right way.
    I've got my doorbell connected to a Nano with a normal radio.
    This node is a repeater because I will use it for more functions (Gasmeter, temp or even more stuff) but nothing planned at this moment.

    This node detects that my doorbell is pressed and switches a directly connected relay for 500 ms to my Siemens Gigaset. This time cannot be longer because the Gigaset will enable DECT Handset learning and people can link new handsets to my basestation. Pushing this button will cause all my DECT phones to ring a internal ringtone to announce that somebody is at the door. The doorbell-switch-pressed-message is a button / light switch in my gateway / controller. Triggering this button / switch will start a script what sends a photo with a piece of text that somebody is at my door and wants my attention.

    The following challenge is a real headache:

    I want the button pressed signal to the gateway only once per 10 seconds. So when somebody pushes the button 30 times within 10 seconds only 1 message will be send and the relay can only switch once during this time otherwise it will cancel the current "doorbell-signal". Hence a cooldown timer is a solution. I don't know how to do this.

    The relay is not necessary in my controller so I will leave it standalone in the sketch. This means that if my gateway / controller is offline for some reason the Gigaset will sound to announce somebody at my door that wants my attention.

    So the challenge is the cooldown-timer but preserving the repeater functionality. I would like to switch the relay directly after the first push because otherwise it takes 10 seconds longer and people will be annoyed.

    I'm totally clueless how to do this. Is there somebody that can point me in the right direction? Or have an example maybe?



  • calling the millis(); function will return a time variable in milli seconds. Save it into a variable and compare it to the current value later to see how much time has passed.



  • Hmm simply sleeping for 30secs after sending a bell message is not enough? the other sensors did not seem to be timing critical?#

    EDIT: a i see you need the repeating capabilities. so sleeping might be a problem. then u need to calculate a time diff



  • Something like that:

    long ringSendtAt;
    boolean isRinging;
    void setup() {
      ringSendtAt = millis() - 10000;
      ...
    }
    
    
    void loop() {
      ...
      if ( isRinging && millis()- ringSendtAt > 10000)
        sendRingingMessage();
        ringSendtAt = millis();
      }
      ...
    


  • Thanks @Heizelmann ! It helped me out a lot!

    I've created this script with a button leaving the relay out:

    #include <MySensor.h>
    #include <SPI.h>
    #include <Bounce2.h>
    
    #define CHILD_ID 12
    #define BUTTON_PIN 2  // Arduino Digital I/O pin for button/reed switch\
    #define RELAY_1 4
    
    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);
    
    long buttonpushed;
    long ringSendAt;
    long timenu;
    
    // Define 10 seconds of cooltime
    ringerdelay = 10000;
    
    void setup()  
    {  
      gw.begin(NULL,9,true);
    
     // Setup the button
      pinMode(BUTTON_PIN,INPUT);
      // Activate internal pull-up
      digitalWrite(BUTTON_PIN,HIGH);
    
      // Setup the button
      pinMode(RELAY_1,OUTPUT);
      // Activate internal pull-up
      digitalWrite(RELAY_1,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)
      gw.present(CHILD_ID, S_DOOR);
      
      // If startup has taken place set the intial values because otherwise the doorbell will ring after powerloss
      if (buttonpushed == NULL || buttonpushed > 1 || ringSendAt == NULL || ringSendAt > 1) {
         buttonpushed = millis();
         ringSendAt = millis();
    }
    }
    
    void loop() 
    {
      debouncer.update();
      // Get the update value
      int value = debouncer.read();
    
    // Time now to check for a difference
    timenu = millis();
     // Check the if the current time is bigger the the button pushed and the current time with a 10 second time-out to prevent ringing again
     if (timenu > buttonpushed && timenu > buttonpushed + ringerdelay) {
      // I only want to fire the relay when the value of the button hits the pushed state
      if (value == 0) {
         // Setting the time when the button is pressed
         buttonpushed = millis();
         //Serial.print("Ding dong!");
         //Serial.println();
         // Send message on to gateway
         gw.send(msg.set(1));
         // Switch the relay for 0,5 second
         digitalWrite(RELAY_1,LOW);
         delay(500);
         digitalWrite(RELAY_1,HIGH);
         // Send message off to gateway
         gw.send(msg.set(0));
         // Set the value always to 1 because I only want to fire it when pressed and not when released.
         oldValue = 1;
      }
    }
    }```


  • Some optimization to check:

    • ringerdelay needs to be defined with a type
    • if condition in setup() not necessary initialize buttonpushed and ringSendAt unconditioned
    • normalize logic in if (timenu > buttonpushed && timenu > buttonpushed + ringerdelay) to if (timenu > buttonpushed + ringerdelay), it is the same
    • variable timenu not necessary use millis() directly: if (millis() > buttonpushed + ringerdelay)
    • on relay initialisation the two comments are wrong

Log in to reply
 

Suggested Topics

16
Online

11.4k
Users

11.1k
Topics

112.7k
Posts