0

This is a "water level alarm/display" sketch using and Arduino and ultrasonic sensor. The buzzer gets on when the water level hits 100% or more. But most of the time the water level will stay @ 100%, and I dont want the buzzer to run for long time. How can I set the buzzer to make sound only for 15 seconds ? It should turn off after 15 seconds, even if the water level is @ 100%

#define trigPin 8
#define echoPin 9
#include <LiquidCrystal.h>

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
int BUZZER = 10 ;

void setup(){
      int duration,distance,percentage,heightTank;
      Serial.begin (9600);
      pinMode(trigPin,OUTPUT);
      pinMode(echoPin,INPUT);
      lcd.begin(16,2);
      lcd.print("HELLO");
        pinMode(BUZZER,OUTPUT);
}

void loop(){
      int duration,distance,percentage,heightTank,deviation;
      //You'll probably want to change the next 2 lines.
      // The first one is the max. level of the water.
      // The next one is how high the sensor is above that max. level.
      heightTank=65;
      deviation=4;

      digitalWrite(trigPin,HIGH);
      delayMicroseconds(1000);
      digitalWrite(trigPin,LOW);
      duration=pulseIn(echoPin,HIGH);
      distance=(duration/2)/29.1;
      percentage=100-(((distance-deviation)*100)/heightTank);
      Serial.println(distance);
      Serial.println(percentage);
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.print("Current tank");
      //lcd.print(distance);
      //lcd.print(" cm");
      lcd.setCursor(0,1);
      lcd.print("level: ");
      lcd.print(percentage);
      lcd.print(" %");
      delay(1000);

      digitalWrite(BUZZER,HIGH);
  if (percentage > 99) {digitalWrite(BUZZER,HIGH); delay(100); digitalWrite(BUZZER,LOW); delay(100);}
  else  {digitalWrite(BUZZER,LOW);}
  }

2 Answers 2

0

Try this at the end of loop

static unsigned long lastBuzzer = 0;

if(percentage > 99 && lastBuzzer == 0) {
    lastBuzzer = millis();
}

if(percentage > 99) {
    if(millis() - lastBuzzer < 15000L) {
        digitalWrite(BUZZER,HIGH);
        delay(100);
        digitalWrite(BUZZER,LOW);
        delay(100);
    }
} else  {
    digitalWrite(BUZZER,LOW);
    lastBuzzer = 0;
}

lastBuzzer is the last buzzer activation time (in ms). It's use to control that buzzing stop after 15 seconds. It's zero when the percentage is < 99; it's not zero when percentage >= 100.

(Not tested). (Two if's instead of one for clarity).

2
  • 2
    May be nitpicking but... 0 is a perfectly valid return value for millis(), once every 49.7 days. Commented Dec 9, 2017 at 10:30
  • @EdgarBonet. True, but I can't see how it affects operation. If millis is zero in lastBuzzer = millis();, then millis() - lastBuzzer (both unsigned long) still will be < 15000L.
    – user31481
    Commented Dec 9, 2017 at 12:53
0

For this you will have to implement a finite state machine. This is a very common paradigm in the embedded world. I recommend you start by studying this tutorial: The Finite State Machine, by Majenko.

Four your particular problem, I would implement a machine with three states: IDLE, ARMED and ALARM, the ALARM state being the only one in which the buzzer is on. The transitions would be:

  • ARMED → ALARM when the level hits 100%
  • ALARM → IDLE after 15 seconds spent in the ALARM state
  • IDLE → ARMED when the level gets below 90%

Note that the only difference between IDLE and ARMED is that the IDLE state will not go into ALARM when the level reads 100%, as you have to go through the ARMED state before. The threshold at 90% percent is meant to add some hysteresis. You can tweak the threshold value to your taste.

I leave the implementation to you. It should be easy one you have studied Majenko's tutorial.


Edit: Just to illustrate the generality of the concept, I would like to point out that the code in Look Alterno's answer can be thought of as a finite state machine where the state is implicitly encoded into the variables lastBuzzer and percentage. The implicit state is:

  • ARMED when lastBuzzer == 0
  • ALARM when percentage > 99 && millis() - lastBuzzer < 15000L
  • IDLE when percentage > 99 && millis() - lastBuzzer >= 15000L

The line lastBuzzer = 0 establishes the ARMED state as soon as percentage ≤ 99. Note that this lacks hysteresis: if the reading fluctuates between 99% and 100%, the alarm will sound again and again.

I personally prefer using an explicit state variable, as it makes the code clearer to me. But then, the best approach is whichever makes the code clearer to you.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.