I am trying to play a tone with a buzzer connected on an arduino nano pin. I have also connected a reed switch with INPUT_PULLUP on INT0 and a led. The program loops continuously (it's an environmental monitor and alarm personal project) until the reed switch is set on HIGH where a function is called and the buzzer should play an one-second high pitch tone.
void doorStateChange() {
static unsigned long last_interrupt_time = 0;
unsigned long interrupt_time = millis();
if (interrupt_time - last_interrupt_time > 1000)
{
led_B_state = !led_B_state;
digitalWrite(buzzPin, HIGH);
digitalWrite(led_A_Pin, HIGH);
if (millis() - interrupt_time <= 1000 ){
digitalWrite(buzzPin, LOW);
digitalWrite(led_A_Pin, LOW);
}
}
last_interrupt_time = interrupt_time;
}
The interrupt is called, the Led lights up but I can't make the buzzer sound right. I 've tried with tone(buzzPin, 5000, 1000);
but seems that the delay does not work - The sound is heard but after the 1000ms it continuous to work in a different tone (strange?).
The only way I could make it work is with buzzPin_state = ! buzzPin_state;
where the buzzer beeps as long as the reed switch is HIGH.
I also need to say that attachInterrupt(0, doorStateChange, CHANGE);
.
The information I get from googling this issue is gibberish: some say that delays don't run in interrupts, others call external functions etc.
What is the proper way to achieve this ?
1 Answer 1
Don't do delay() calls inside an ISR. In all probability it will hang indefinitely. If you want to play the tone for a second all you need to do in the ISR is set a flag, which you test in the main loop. Turn the buzzer on when the flag changes state. Remember when you did that. When a second is up turn the buzzer off again.
In fact in your case you probably don't need the interrupt at all. Test for the reed switch change in the main loop as well. Don't overcomplicate it.
tone()
then, correct? (Rising/change/falling are really irrelevant in this case)