You are overcomplicating the program. There is no point in remembering when each of the notes started. You just have to remember:
- what note is currently playing
- when you started playing this note
Then the logic of loop() becomes simply: “if we are done with the
current note, then start playing the next one.” In code:
Edit: Changed the code to include your button-scanning loop.
#includeint "pitches.h"current_button;
uint32_t note_started;
const
void uint8_tloop() speaker_pin{
= 3;
const int note_count// =Adjust 4;the notes on button presses.
const for (int pitches[note_count]button = {0; NOTE_B1,button NOTE_C2,< NOTE_CS2,N_BUTTONS; NOTE_D2button++) };{
const int note_duration = 1000;
if (digitalRead(button_pins[button])) {
int current_note = note_count; // whatAs notewe ishave currently78 playingpitches we divide the max Potentiometer
uint32_t note_started; // whenvalue theby note77. startedThis playing
equals 13.
void setup Pitches[button] = analogRead(A0){}
/13;
void loop() {
uint32_t now Durations[button] = millisanalogRead(A1);*4;
}
}
// Are we done with the current note?
uint32_t now = millis();
int tempo = analogRead(A2);
if (now - note_started >= note_durationDurations[current_button] + tempo) {
// Then move to the next note.
++current_note;++current_button;
// Finished the tune?
if (current_notecurrent_button == note_countN_BUTTONS) {
current_notecurrent_button = 0; // then restart from the beginning
}
// Play the note.
tone(speaker_pinspeakerPin,
pitches[current_note] Pitches[current_button], Durations[current_button]);
// Take note of when this started.
note_started = now;
}
}
Note that tune() is called with no duration parameter: the note is
going to be overridden by the next one anyway. You could add a duration
shorter than note_duration if you want to have a small silence between
consecutive notes.
You could also have different durations for different notes: store the
durations in an array, then replace note_duration by
duration[current_note].