I'm writing a program where I can play different melodies through a little Piezo buzzer and every time a button is pressed it plays the next song. The way my code is written right now, the current song has to finish playing before it will switch to the next song. My goal is to get it change songs immediately after the user clicks the button. What can I do to achieve this goal? For reference I am using an Arduino Nano Every for this project. It should also be noted I borrowed the code for the Piezo buzzer which had limited comments. My comments for that code is how I interpret it when I read it. There's a pretty good chance that I may have misunderstood something when reading it, however I can confirm that the actual code as written works. If you notice a misinterpretation of the code, please mention it in the comments.
#include "pitches.h"
#define button 2
#define buzzer 3
volatile int bCount = 0; // a counter for number of button presses
/* The first 3 arrays here are where the notes of the song are defined.
It references the "pitches.h" file where all of the notes are defined by
there corresponding frequencies.*/
int songA[] = {
//notes of song go here
};
int songB[] = {
//notes of song go here
};
int songC[] = {
//notes of song go here
};
/* The following 3 arrays defines the length of each note. These values are
equivalent to the written note duration in sheet music (e.g. quarter notes =
0.25, half notes = 0.5, etc.). It is important each of these arrays are the
same size as the matching song arrays above.*/
float songA_duration = {
//length of notes go here
};
float songB_duration = {
//length of notes go here
};
float songC_duration = {
//length of notes go here
};
void setup(){
pinMode(buzzer,OUTPUT); //Defines the digital pin connected to the buzzer as an output
pinMode(button,INPUT); //Defines the digital pin connected to the button as an input
attachInterrupt(button,button_pressed,RISING); //Defines the button as a hardware interrupt. When the digital pin sees a rising signal it will activate the ISR button_pressed.
}
void loop(){
/* This part of the code decides which song is played by getting
the current button count modulo 3 and adding 1. That number
will then be placed in the playSong function and the corresponding
song will play. */
song = bCount % 3 + 1;
playSong(song);
}
void button_pressed(){
// ISR. When button is pressed, increment counter.
bCount++;
}
void playSong(int song){
/* This function will play a song based on the number it is given. It
first determines the song length by dividing the size of the array
for each song and dividing it by the size of the first element of the
array. It will then loop through both the song array and the
duration array. The corresponding notes will be played through
the buzzer. Note: The constant (180/148) in the duration floating
point number was created to adjust for different tempos. Ideally,
the '148' value could be replaced with the tempo of each new song
and that exact tempo would be played. However, the tempo is not
greatly effected except for when the constant is equal to a whole
number. */
if(song == 1){
int songLength = sizeof(songA)/sizeof(songA[0]);
for(int thisNote = 0; thisNote < songLength; thisNote++){
float duration = (180/148) * 1000 * songA_duration[thisNote];
tone(buzzer,songA[thisNote],duration);
float pause = duration * 1.3;
delay(pause);
noTone(buzzer);
}
} else if(song == 2) {
int songLength = sizeof(songB)/sizeof(songB[0]);
for(int thisNote = 0; thisNote < songLength; thisNote++){
float duration = (180/148) * 1000 * songB_duration[thisNote];
tone(buzzer,songB[thisNote],duration);
float pause = duration * 1.3;
delay(pause);
noTone(buzzer);
}
} else if(song == 3){
int songLength = sizeof(songC)/sizeof(songC[0]);
for(int thisNote = 0; thisNote < songLength; thisNote++){
float duration = (180/148) * 1000 * songC_duration[thisNote];
tone(buzzer,songC[thisNote],duration);
float pause = duration * 1.3;
delay(pause);
noTone(buzzer);
}
}
}