0

I have a smoke detector with a piezo buzzer. I want to operate the arduino in low power mode so that it will last on a 9V battery. I've attached an interrupt, and when the digital output of the MQ-2 sensor goes high, it switches to a monitor function.

In the while loop, I check to see if the analog sensor has reached the threshold value, and I output to serial to see if I am in the conditional. If I use:

digitalWrite(buzzer, HIGH);

then the piezo sounds, however if I use

tone(buzzer, 1000,200);
delay(200);

it does not. I'm confused as to why this would be the case.

Full code as follows:

#include "LowPower.h"

int redLed = 12;
int greenLed = 11;
int buzzer = 10;
int smokeA0 = A5;
// Your threshold value
int sensorThres = 50;
int smokeD0 = 2;

void setup() {
  pinMode(redLed, OUTPUT);
  digitalWrite(redLed, LOW);
  pinMode(greenLed, OUTPUT);
  digitalWrite(greenLed, HIGH);
  pinMode(buzzer, OUTPUT);
  pinMode(smokeA0, INPUT);
  pinMode(smokeD0, INPUT);


}
void switchToMonitor() {
  Serial.begin(9600);
  int digitalSensor = digitalRead(smokeD0);
  if (digitalRead(smokeD0) == HIGH)
  {
    digitalWrite(redLed, HIGH);
    digitalWrite(greenLed, LOW);
  }
  else {
    digitalWrite(redLed, LOW);
    digitalWrite(greenLed, HIGH);
  }
  //This will be updated later to use the analog input
  //Using digital to make debugging easier
  while (digitalSensor == HIGH) {
    int analogSensor = analogRead(smokeA0);
    Serial.print("Pin A0: ");
    Serial.println(analogSensor);
    Serial.print("Pin D0: ");
    Serial.println(digitalSensor);
    // Checks if it has reached the threshold value
    if (analogSensor > sensorThres) {
      digitalWrite(buzzer, HIGH);
      //tone(buzzer, 1000,200);
      Serial.println("here");
      delay(1000);
    }
    else {
//      digitalWrite(redLed, LOW);
//      digitalWrite(greenLed, HIGH);
      noTone(buzzer);
      Serial.println("also here?");
    }
    //delay(100);
    digitalSensor = digitalRead(smokeD0);
  }
  noTone(buzzer); 
}

void loop() {
  //delay(100);
  //LowPower.standby();
  attachInterrupt(0, switchToMonitor, CHANGE);
  LowPower.powerDown(SLEEP_FOREVER, ADC_ON, BOD_ON); 
  detachInterrupt(0); 
}
2
  • @Juraj The tone function works when used within void loop() and not switching between low power and operational. It's only not working in the code example given Commented Jan 25, 2020 at 18:06
  • connect the buzzer to a battery ... does it make a sound?
    – jsotola
    Commented Jan 25, 2020 at 18:33

1 Answer 1

1

You can't use delay() or timer based tone() function in interrupt handler. Set a flag in interrupt and run the code in loop() conditionally based on the flag state. Do not forget to have the flag variable volatile.

1
  • Took it out of the interrupt handler and it worked. Thanks Commented Jan 25, 2020 at 19:13

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.