Delay alarm tone only once?

Hello, my husband is in the early stages of dementia and lately he has been sometimes forgetting to close the fridge door all the way. I am working on an alarm that will tell me if the door has been left open but not to have the alarm go off every time we open the fridge door. I would like the alarm to go off only after the door has been open for 30 seconds then continue to go off so I can go and close the door. I am not very experienced with code so I was using a simple delay in the void loop but that is not working the way I need it to. I would really appreciate some guidance in how to approach the problem.

//Fridge Door Alarm using Hall Effect Sensor

const int halleffectPin = 2; // the hall effect sensor pin
const int redledPin =  13;   // the red LED pin
const int greenledPin =  12;  // the green LED pin
const int buzzer = 5; // // the buzzer pin
int halleffectState = 0;  // variable for reading the hall sensor status

void setup() {
  pinMode(redledPin, OUTPUT);   // initialize the LED pins and hall effect pin
  pinMode(greenledPin, OUTPUT);     
  pinMode(halleffectPin, INPUT_PULLUP);      
}

void loop(){
  halleffectState = digitalRead(halleffectPin); // read the state of the hall effect sensor

  if (halleffectState == HIGH) {
    // the door is left open
    digitalWrite(greenledPin, LOW); // turn green LED off      
    digitalWrite(redledPin, HIGH); // turn red LED on
    delay(30000);        // for 30 seconds
    
    tone(buzzer, 1000); // generate 1KHz alarm tone
    delay(1000);        // for 1 second
    noTone(buzzer);     // stop sound
    delay(1000);        // for 1 second
  
  } 
  
  else {
    // door is closed
    noTone(buzzer); // Stop sound
    digitalWrite(redledPin, LOW); // turn red LED off
    digitalWrite(greenledPin, HIGH); // turn green LED on
  }
}

You can't really use delay in this instance as this blocks the code... so even if you close the door the delay continues.

You need to use a different technique. This is demonstrated in the "Blink Without Delay" example in the IDE. Instead of using delay, instead you keep track of the time (using a function called millis()) that certain things happen (like the door first being opened)... and then check the current time to determine what you need to do. This all happens within loop.

Also be aware that you are pulling the Hall effect pin HIGH with...

  pinMode(halleffectPin, INPUT_PULLUP);

You would normally do this if the sensor is active LOW... so you probably want to be checking for LOW not HIGH.

 if (halleffectState == HIGH)

Thank you red_car for taking the time to help. :slight_smile:

The fundamental which you need to look at, as well as using non-blocking millis() code…

…is to identify WHEN the door is opened, not IF the door is open, then you can start your millis() time period from that point.

Similarly, IF the door is closed, it disables the events that trigger the alarm until the door is next opened.

Couple of other things to consider.

You need to be able to tell when the door was first opened, to start your timer. The easiest way to do that is continually check the sensor on each loop and compare its value to the loop before. When it changes from HIGH -> LOW that's the point you start your timer from.

Also, to start with I'd recommended just turning ON/OFF the LEDs and the buzzer ON. Don't try and have the buzzer turn ON/OFF every second. That's another timing consideration and adds a bit of complication, but get the basic program working first before you try that bit.

Thank you both for the assistance, I really appreciate it. I am studying the Blink Without Delay example but it would be more helpful for a newbie like me if it was more about turning on an LED with delay and didn't have all the blinking code to make it more complicated. :thinking:

You know how to tug at ones heart :woozy_face:

Try this:

//Fridge Door Alarm using Hall Effect Sensor


//********************************************^************************************************
#define PUSHED                        LOW
#define RELEASED                      HIGH

#define CLOSED                        LOW
#define OPEN                          HIGH

#define ENABLED                       true
#define DISABLED                      false

#define LEDon                         HIGH
#define LEDoff                        LOW

//********************************************^************************************************
const byte halleffectPin            = 2;    //the hall effect sensor pin

const byte buzzer                   = 5;    //the buzzer pin
const byte heartbeatLED             = 11;
const byte greenledPin              = 12;   //the green LED pin
const byte redledPin                = 13;   //the red LED pin

boolean halleffectTimerFlag         = DISABLED;
boolean buzzerFlag                  = DISABLED;
boolean buzzerState                 = DISABLED;

byte lastHalleffectState;

//timing stuff
unsigned long heartbeatMillis;
unsigned long switchMillis;
unsigned long halleffectMillis;
unsigned long buzzerMillis;

const unsigned long alarmInterval      = 30000ul;  //30 seconds
const unsigned long buzzerInterval     = 1000ul;   //1  seconds


//                                       s e t u p ( )
//********************************************^************************************************
void setup()
{
  pinMode(redledPin, OUTPUT);
  digitalWrite(redledPin, LEDoff);

  pinMode(greenledPin, OUTPUT);
  digitalWrite(greenledPin, LEDon);

  pinMode(heartbeatLED, OUTPUT);

  pinMode(buzzer, OUTPUT);
  noTone(buzzer);

  pinMode(halleffectPin, INPUT_PULLUP);

}


//                                       l o o p ( )
//********************************************^************************************************
void loop()
{
  //*********************************                             h e a r t b e a t   T I M E R
  //is it time to toggle the heartbeatLED ?
  if (millis() - heartbeatMillis >= 500ul)
  {
    //restart this TIMER
    heartbeatMillis = millis();

    //toggle the heartbeatLED
    digitalWrite(heartbeatLED, !digitalRead(heartbeatLED));
  }

  //*********************************                      c h e c k   s w i t c h   T I M E R
  //is it time to check the switches ?
  if (millis() - switchMillis >= 50ul)
  {
    //restart this TIMER
    switchMillis = millis();

    checkSwitches();
  }

  //*********************************                          h a l l e f f e c t   T I M E R
  //if this TIMER is enabled, has it expired ?
  if (halleffectTimerFlag == ENABLED && millis() - halleffectMillis >= alarmInterval)
  {
    //disable this TIMER
    halleffectTimerFlag = DISABLED;

    //enable the buzzer TIMER
    buzzerFlag = ENABLED;

    //start the TIMER
    buzzerMillis = millis();

    //turning on the buzzer
    buzzerState = ENABLED;

    tone(buzzer, 1000);
  }

  //*********************************                                   b u z z e r   T I M E R
  //if this TIMER is enabled, has it expired ?
  if (buzzerFlag == ENABLED && millis() - buzzerMillis >= buzzerInterval)
  {
    //restart this TIMER
    buzzerMillis = millis();

    buzzerState = !buzzerState;

    if (buzzerState == ENABLED)
    {
      tone(buzzer, 1000);
    }

    else
    {
      noTone(buzzer);
    }
  }

} //END of    loop()


//                              c h e c k S w i t c h e s ( )
//********************************************^************************************************
//this function runs every 50ms; this effectively debounces your inputs
void checkSwitches()
{
  byte currentState;

  //************************************************                      b u t t o n 1 P i n
  currentState = digitalRead(halleffectPin);

  //has this switch changed state ?
  if (lastHalleffectState != currentState)
  {
    //update to the new switch state
    lastHalleffectState = currentState;

    //*************************
    //has this door opened ?
    if (currentState == OPEN)
    {
      //the door is open
      digitalWrite(redledPin, LEDon);
      digitalWrite(greenledPin, LEDoff);

      //disable this TIMER
      buzzerFlag = DISABLED;

      //enabled this TIMER
      halleffectTimerFlag = ENABLED;

      //start the TIMER
      halleffectMillis = millis();
    }

    //door is closed
    else
    {
      //disable this TIMER
      halleffectTimerFlag = DISABLED;

      //disable this TIMER
      buzzerFlag = DISABLED;

      noTone(buzzer);
      digitalWrite(redledPin, LEDoff);
      digitalWrite(greenledPin, LEDon);
    }

  } //END of   this switch


  //*********************************
  // Future switches go here
  //*********************************

} //END of   checkSwitches()

Hi Larry, I read elsewhere on the forum that it is best when asking questions on this forum to state clearly what I need my code to do and what I am trying to achieve with my project. I hope it did not come across as trying to get sympathy, that was not my intent.

No, just had similar situation years back.

The sketch I post you in post #7 should be close to what you asked for.

Thank you Larry, I'l have a look at it. :slight_smile:

Here's another version. This doesn't toggle the buzzer yet... but hopefully you get the idea and can see how you would achieve that.

//Fridge Door Alarm using Hall Effect Sensor

const int halleffectPin = 2;  // the hall effect sensor pin
const int redledPin     = 13; // the red LED pin
const int greenledPin   = 12; // the green LED pin
const int buzzer        = 5;  // the buzzer pin

int halleffectState     = 0;  // variable for reading the hall sensor status
int previousState       = 0;  // value on previsou loop.
unsigned long openTime  = 0;  // Time when door first opened. 

void setup() 
{
  pinMode(redledPin,     OUTPUT);   
  pinMode(greenledPin,   OUTPUT);     
  pinMode(halleffectPin, INPUT_PULLUP);      
}

void loop()
{
  halleffectState = digitalRead(halleffectPin); // read the state of the hall effect sensor

  
  if (halleffectState == LOW)         // Door open
  {
    if (previousState == HIGH)        // Door has just been opened
    {
      openTime = millis();            // Keep track on when the door was opened.
    }

    if (millis() - openTime > 20000)  // Has the door has been open too long?
    {
      digitalWrite(greenledPin, LOW); // turn green LED off      
      digitalWrite(redledPin, HIGH);  // turn red LED on
      tone(buzzer, 1000);             // generate 1KHz alarm tone
    }     
  } 
  else                                // Door closed
  {
    noTone(buzzer);                   // Stop sound
    digitalWrite(redledPin, LOW);     // turn red LED off
    digitalWrite(greenledPin, HIGH);  // turn green LED on
  }

  previousState = halleffectState;    // Update the previous state for checking next loop.
}

Thank you red_car, that is so clear and easy to understand. :grinning: I feel confident now that I can experiment with it to get it to do exactly what I need. This is so much more helpful for me as a newbie to millis than the BlinkWIthoutDelay example, thank you again for taking the time to write it out for me. Cheers!

I think that I might use a sound module to say "the fridge door is open" repeatedly rather than the buzzer. There are other things that beep in a similar fashion around our home and having the spoken words as the alarm might be easier to for him to recognize that it is the fridge that needs to be responded to. I have used mp3 player modules in previous projects so I don't require help with that, I just thought I'd mention the idea in case it helps someone else with a similar project. :slight_smile:

Hello arduinokov
And now you have a wide range of solutions for your project.

//Fridge Door Alarm using Hall Effect Sensor
const int halleffectPin = 2; // the hall effect sensor pin
const int redledPin =  13;   // the red LED pin
const int greenledPin =  12;  // the green LED pin
const int buzzer = 5; // // the buzzer pin
int halleffectState = 0;  // variable for reading the hall sensor status
int halleffectStateOld = 0;  // variable for reading the hall sensor status old
unsigned long timeStamp;    // time stamp for door open event
const unsigned long time4alert {30000};    // time to go before alert
bool timerRun;
int alertState; // 0 = no alert, 1 = alert
enum Alerts {NoAlert, Alert};
void setup() {
  Serial.begin(9600); 
  pinMode(redledPin, OUTPUT);   // initialize the LED pins and hall effect pin
  pinMode(greenledPin, OUTPUT);
  pinMode(buzzer, OUTPUT);
  pinMode(halleffectPin, INPUT_PULLUP);
}
void loop() {
  halleffectState = !digitalRead(halleffectPin); // read the state of the hall effect sensor
  if (halleffectStateOld != halleffectState) // any changes ?
  { //if yes
    halleffectStateOld = halleffectState;  //save new state
    if (!halleffectState) // door open?
    { // is open
      timeStamp = millis(); // start timer
      timerRun = true;
      Serial.println(F("door open"));
    } else { // is closed
      alertState = NoAlert;
      timerRun = false;  // stop timer
      Serial.println(F("door closed"));
    }
  }
  if (millis() - timeStamp >= time4alert && timerRun) timerRun = false, alertState = Alert; // out of time
  digitalWrite(greenledPin, !alertState);
  digitalWrite(redledPin, alertState);
  digitalWrite(buzzer, alertState);
}

Have a nice day and enjoy programming in C++ and learning.
Errors and omissions excepted.
Дайте миру шанс!

Thank you for taking the time to share this code as well, I have a lot to study now and hopefully improve my coding. :slight_smile:

Hello again,

I have been using the alarm on the fridge now for a week and it is working well. The only issue is that the alarm buzzer, while loud enough to get my husband's attention, is a bit overwhelming. So now I am trying to make it beep at first, say once every 30 seconds for a few minutes to give him a chance to respond to it before going for the full tone. I have not been able to get the tone to beep though.

//Fridge Door Alarm using Hall Effect Sensor

const int halleffectPin = 2;  // the hall effect sensor pin
const int redledPin     = 13; // the red LED pin
const int greenledPin   = 12; // the green LED pin
const int buzzer        = 5;  // the buzzer pin

int halleffectState     = 0;  // variable for reading the hall sensor status
int previousState       = 0;  // value on previous loop.
unsigned long openTime  = 0;  // time when door first opened. 

void setup() 
{
  pinMode(redledPin,     OUTPUT);   
  pinMode(greenledPin,   OUTPUT);     
  pinMode(halleffectPin, INPUT_PULLUP);      
}

void loop()
{
  halleffectState = digitalRead(halleffectPin); // read the state of the hall effect sensor

    if (halleffectState == HIGH)        // door open
    {

    if (previousState == HIGH)         // door opened and ok
    digitalWrite(greenledPin, HIGH);  // turn green LED on
    {
    
    if (previousState == LOW)         // door has just been opened
    {
      openTime = millis();            // keep track on when the door was opened.
    }

    if (millis() - openTime > 30000)  // the door is open
    {
      digitalWrite(greenledPin, LOW); // turn green LED off      
      digitalWrite(redledPin, HIGH);   // blink red LED
      delay(500);                       
      digitalWrite(redledPin, LOW);    
      delay(500);                       

    }     

    if (millis() - openTime > 150000)  // has the door has been open too long?
    {
      tone(buzzer, 1000);             // generate 1KHz alarm tone
      delay(30000);   
    }      

  }
  } 
    else                                // door closed
  {
    noTone(buzzer);                   // stop sound
    digitalWrite(redledPin, LOW);     // turn red LED off
    digitalWrite(greenledPin, LOW);  // turn green LED off
  }

  previousState = halleffectState;    // update the previous state for checking next loop
}

You should just continue on with your last topic rather than starting a new one :confused: .

What do you not understand about the sketch offered to you back there ?


Do you know what a State Machine is ?

Hi, oops, I'll go and add it to that thread.

Just ask the Moderator to combine the two posts.

Thanks, I will.