your code kinda works if you hold de stop button for more than one second because your while loop
only evaluates the state of the button every second due to the presence of delay() inside the while loop
test your code here:
if you want immediate reaction, you need a small state machine for example and using millis
For extra information and examples look at
- Using millis() for timing. A beginners guide
- Several things at the same time
- Flashing multiple LEDs at the same time
(instead of flashing the leds you would turn the sound on or off)
if you can't make it and want a ready made solution
try this
nonBlockingSoundPlayStop - Wokwi ESP32, STM32, Arduino Simulator
the code:
const byte playPin = 7;
const byte stopPin = 8;
const byte buzzerPin = 4;
enum state {SILENT, BEEPING_ON, BEEPING_OFF} state = SILENT;
unsigned long chrono;
const unsigned long soundOnDuration = 500; // ms
const unsigned long soundOffDuration = 500; // ms
void setup() {
pinMode(buzzerPin, OUTPUT);
pinMode(playPin, INPUT_PULLUP);
pinMode(stopPin, INPUT_PULLUP);
}
void loop() {
switch (state) {
case SILENT:
// we are silent, if we press the play button, then start playing the sound
if (digitalRead(playPin) == LOW) {
tone(buzzerPin, 3150); // start the sound
chrono = millis(); // note the start time
state = BEEPING_ON;
}
break;
case BEEPING_ON:
// the beeping is on, check if we need to stop
if (digitalRead(stopPin) == LOW) {
noTone(buzzerPin);
state = SILENT;
} else // check if ON duration has elapsed
if (millis() - chrono >= soundOnDuration) {
noTone(buzzerPin);
chrono = millis(); // note the start time
state = BEEPING_OFF;
}
break;
case BEEPING_OFF:
// the beeping is off check if we need to stop
if (digitalRead(stopPin) == LOW) {
noTone(buzzerPin);
state = SILENT;
} else // check if OFF duration has elapsed
if (millis() - chrono >= soundOffDuration) {
tone(buzzerPin, 3150); // start the sound again
chrono = millis(); // note the start time
state = BEEPING_ON;
}
break;
}
}
