I’m getting stuttering issues with calls to tone
, and it’s really a head-scratcher for me. The code is pasted below. The main thing to realize is that I’m calling tone
, then setting a timer, then calling noTone
when the timer completes. The function tick
is called every time the main Arduino loop runs. So the timer is basically in charge of shutting off the tone when the duration is over, and then tick
advances to the next note and starts playing it.
The output from the buzzer is very stuttered. I can hear the tones in there, but it’s garbled and broken.
In the past, I have gotten it to make tones using tone(pin, freq, duration)
and it’s on pin A4, so I know that should work. I’m just wondering if there is some kind of issue with running software timers (ie. new Timer()
) while also doing tone playback.
Update: For future reference, I was able to determine that the timers definitely seem to be an issue, although it’s not necessarily this timer in my MusicPlayer
class. I’ve got a few other timers running, specifically one that is controlling a NeoPixel LED strip. If that timer is running, or more accurately, if it is stopping and restarting, the tone
function stutters.
In other words, if you’re using tone
and Timer
together in the same app, you might run into stutter problems.
#include "Particle.h";
#include "pitches.h";
#include "definitions.h";
#include "MusicPlayer.h";
MusicPlayer::MusicPlayer() {
timer = new Timer(1000, &MusicPlayer::endNote, *this);
noteInProgress = false;
tuneInProgress = false;
}
bool MusicPlayer::playInProgress() {
return tuneInProgress;
}
void MusicPlayer::playTune(String tuneId) {
if(noteInProgress) {
return;
}
if(tuneId == "win") {
melodyIndex = 0;
} else if(tuneId == "live") {
melodyIndex = 1;
}
noteIndex = 0;
tuneInProgress = true;
noteInProgress = false;
}
void MusicPlayer::tick() {
if(noteInProgress || !tuneInProgress) {
return;
}
int note = notes[melodyIndex][noteIndex];
int duration = 1000 / noteDurations[melodyIndex][noteIndex];
this->playNote(note, duration);
}
void MusicPlayer::playNote(int note, int duration) {
noteInProgress = true;
tone(SPEAKER_PIN, note);
timer->changePeriod(duration);
timer->reset();
}
void MusicPlayer::endNote() {
timer->stop();
noTone(SPEAKER_PIN);
noteInProgress = false;
noteIndex++;
if(noteIndex > noteCounts[melodyIndex]) {
this->endPlay();
}
}
void MusicPlayer::endPlay() {
timer->stop();
noTone(SPEAKER_PIN);
noteInProgress = false;
tuneInProgress = false;
}