How to make a buzzer beep for a second when a state change is detected

Hey guys! I am trying to make a simple photoresistor/LED circuit that enables an LED when it gets dark and switches it off when it is bright. However, when it gets dark, there is also a buzzer that beeps for a second and then remains off for the remainder of the dark state. This does not have to happen when it becomes bright again. This is my code so far. If I start off in darkness, the LED and buzzer work as intended. But when I transition back to a dark state from a lit one, the buzzer doesn't beep at all. I am terrible with intuitively understanding flags and tend to overcomplicate things a LOT. Can anyone please guide me as to what I am completely messing up? I attempted to use the global variable startMode as my flag in several places.

const int LIGHT_SENSOR_PIN = A0; // Arduino pin connected to light sensor's  pin
const int LED_PIN          = 6;  // Arduino pin connected to LED's pin
const int ANALOG_THRESHOLD = 960;
const int BUZZER_PIN       = 4;
int startMode = 1; // set to 1 by default

int analogValue;
unsigned desiredinterval = 1000; // sets desired buzzer interval to 1 second

void setup() {
  Serial.begin(9600);
  pinMode(LED_PIN, OUTPUT); // set arduino pin to output mode
  pinMode(BUZZER_PIN, OUTPUT);
}

void loop() {
  unsigned currentTime;
  analogValue = analogRead(LIGHT_SENSOR_PIN); // read the input on analog pin

  if (analogValue > ANALOG_THRESHOLD && startMode == 1) {
    unsigned currentTime = millis();
    startMode = 0;
  }

  if (analogValue > ANALOG_THRESHOLD){ 
    digitalWrite (LED_PIN, HIGH);

    if (millis() - currentTime <= desiredinterval && startMode == 0){
      digitalWrite (BUZZER_PIN, HIGH);
    }

    else digitalWrite (BUZZER_PIN, LOW);

  }

  else {
    digitalWrite (LED_PIN, LOW);
    digitalWrite (BUZZER_PIN, LOW);
    startMode = 1;
  }

  Serial.println(analogValue);
 
}

unsigned is shorthand for unsigned int which is NOT what millis() returns. You want unsigned long

The problem is you are declaring a completely new variable inside your if() statement. As a human, it looks like the same currentTime but to the compiler, it is a new variable with a new scope. You should be just doing the assignment, without the declaration

currentTime = millis()

because of this, your code never assigns a value to the currentTime variable declared at the top of loop()

You mean unsigned long ?

You did overcomplicate it a bit, but you had most of the ideas there.

edit: added pinMode to setup - the simulator didn't seem to miss it!

See it in action here


beep once simulation

It's basically the "state change transition" example from the IDE, combined wit hthe timing mecahanism of "blink without delay".

Both of which sketches you shoud come to a full understanding of, and then see how those pieces can be combined with a simple flag variable.

Look where and why the flag gets set (true) and cleard (flase), look also carefully to see how the timer based on startTime is used.

And yes, unsigned alone is the same as an unsigned int, whenever you are using millis() it is important to use unsigned long, or know exactly when you don't have to.

// https://wokwi.com/projects/353032053211476993

const int LIGHT_SENSOR_PIN = A0; // Arduino pin connected to light sensor's  pin
const int LED_PIN          = 6;  // Arduino pin connected to LED's pin
const int ANALOG_THRESHOLD = 777;
// const int BUZZER_PIN       = 4;

// int startMode = 1; // set to 1 by default

void setup() {
  Serial.begin(9600);
  Serial.println("Hello Beep World!\n");

  pinMode(LED_PIN, OUTPUT);
}

bool needABeep;     // state change on analog "button" sets this
byte buttonState;		// sorry, borrowed from state change detection example!
byte lastButtonState;

unsigned long startTime;
const unsigned long desiredinterval = 1222;

void loop() {
  buttonState = analogRead(LIGHT_SENSOR_PIN) > ANALOG_THRESHOLD;

  if (buttonState != lastButtonState) {
    if (buttonState == HIGH) {
      needABeep = true;
    }
  }
  lastButtonState = buttonState;

// start a beep?
  if (needABeep) {
    digitalWrite (LED_PIN, HIGH);
    startTime = millis();
    needABeep = false;  // we started the beep, OK?
  }

// turn off beep?
  if (millis() - startTime > desiredinterval) {
    digitalWrite(LED_PIN, LOW);
  }

  delay(50);  // global poor man's debouncing
}

HTH

a7

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.