Hi, I’m trying to play a little tune using a passive piezo. Usine the “tone()” function, the buzzer will sound, but it will not stop, and the code no longer seems to function when the sound starts. I suspect there is some interference between the buzzer pins and some other critical function of the Xiao BLE Sense. I recall that certain GPOs shouldn’t be used under certain circumstances but have tried a few pin combinations and still getting the issue. Any suggestions for which pins to use with a buzzer if I also have to use pins to signal a motor driver and pins to sense button pushes etc?
It is entirely possible that the code has a problem, so I’ll post it here. This code should play a little melody using a state machine. In the below, the serial monitor will only print a single millis row after the button is pushed and then freeze while the buzzer continuously sounds. In this instance, the piezo is playing the desired note. However, using different pins, I sometimes got the situation that the piezo would play a super high pitch and the xiao would lock up, only getting back to bootloader through a double reset click, some that’s why I suspect there’s something up with using the tone() function with certain pins:
#include <ezButton.h>
ezButton DrinkButton(D7);
const int Buzzer = A0;
enum Notes {GS4=415, FS4=369, E4=329, B3=246};
enum PlayState {Done, Playing, Pausing};
int playState = Done;
int playStep = 0;
unsigned long startTone = 0;
unsigned long startPause = 0;
int Tones[8]
= {E4, FS4, GS4, E4, GS4, E4, FS4, B3};
int Durations[8]
= {700, 700, 700, 700, 700, 700, 700, 2100};
int Pauses[8]
= {100, 100, 100, 1400, 100, 100, 100, 10};
int lastStep = 7;
void setup() {
pinMode( Buzzer, OUTPUT );
Serial.begin(115200);
}
void loop() {
DrinkButton.loop();
if ( playState==Done and DrinkButton.isPressed() ) {
playState = Playing;
startTone = millis();
playStep = 0;
PlaySong();
}
}
void PlaySong() {
switch (playState) {
case Done: break;
case Playing:
tone ( Buzzer, Tones[playStep] );
Serial.print ("millis ");
Serial.print (millis());
Serial.print (" timer ");
Serial.println (startTone + Durations[playStep]);
if ( millis() > startTone + Durations[playStep] ){
startPause = millis();
playState = Pausing;
}
break;
case Pausing:
noTone(Buzzer);
if( millis() > startPause + Pauses[playStep] ){
playStep++;
startTone = millis();
playState = Playing;
};
if ( playStep > lastStep ) {
playStep = 0;
playState = Done;
}
break;
default: break;
}
}