Is there a method to play a Melody with Tone() without using the delay() function?
tone(8, melody[thisNote], noteDuration);
int pauseBetweenNotes = noteDuration;
**delay(pauseBetweenNotes);**
Is there a method to play a Melody with Tone() without using the delay() function?
tone(8, melody[thisNote], noteDuration);
int pauseBetweenNotes = noteDuration;
**delay(pauseBetweenNotes);**
As others have noted, this can be done using the same method as used in the standard 'BlinkWithoutDelay' example sketch, and combining that with a state-machine type approach. In a simple state machine you'd assume you can be in one of two states: outputting a tone, and not outputting a tone.
Applying these ideas to your code snippet above:
// BEFORE SETUP
const int tonePin = 8;
unsigned long previousMillis = 0;
const long interval = pauseBetweenNotes;
const long interval = noteDuration;
boolean outputTone = false; // Records current state
// IN LOOP
unsigned long currentMillis = millis();
if (outputTone) {
// We are currently outputting a tone
// Check if it's been long enough and turn off if so
if (currentMillis - previousMillis >= noteDuration) {
previousMillis = currentMillis;
noTone(tonePin);
outputTone = false;
}
} else {
// We are currently in a pause
// Check if it's been long enough and turn on if so
if (currentMillis - previousMillis >= pauseBetweenNotes) {
previousMillis = currentMillis;
tone(tonePin, melody[thisNote]);
outputTone = true;
}
}
Adding a bit to kabdulla's great example, to be able to use a MelodyArray
// declaring variables
const int tonePin = 10;
unsigned long previousMillis = 0;
const long pauseBetweenNotes = 250; // interval between notes (ms)
const long noteDuration = 400; // (ms)
boolean outputTone = false; // Records current state
const int MelodyLength = 2;
const int Melody[MelodyLength] = {880, 698};
int MelodyIndex = 0;
unsigned long currentMillis;
void setup() {
}
void loop() {
currentMillis = millis();
PlayMelody();
}
void PlayMelody() {
if (outputTone) {
// We are currently outputting a tone
// Check if it's been long enough and turn off if so
if (currentMillis - previousMillis >= noteDuration) {
previousMillis = currentMillis;
noTone(tonePin);
outputTone = false;
}
} else {
// We are currently in a pause
// Check if it's been long enough and turn on if so
if (currentMillis - previousMillis >= pauseBetweenNotes) {
previousMillis = currentMillis;
tone(tonePin, Melody[MelodyIndex]);
outputTone = true;
//Update to play the next tone, next time
MelodyIndex = MelodyIndex + 1;
if (MelodyIndex >= MelodyLength) {
MelodyIndex = 0;
}
}
}
}
this is a minimal modification of the basic Arduino toneMelody example to a non-blocking version
#include "pitches.h"
// notes in the melody:
int melody[] = {
NOTE_C4, NOTE_G3, NOTE_G3, NOTE_A3, NOTE_G3, 0, NOTE_B3, NOTE_C4
};
// note durations: 4 = quarter note, 8 = eighth note, etc.:
int noteDurations[] = {
4, 8, 8, 4, 4, 4, 4, 4
};
unsigned long previousMillis = 0;
unsigned long pauseBetweenNotes;
int thisNote;
void setup() {
}
void loop() {
// iterate over the notes of the melody:
unsigned long currentMillis = millis();
if (thisNote < 8 && currentMillis - previousMillis >= pauseBetweenNotes) {
previousMillis = currentMillis;
// to calculate the note duration, take one second divided by the note type.
//e.g. quarter note = 1000 / 4, eighth note = 1000/8, etc.
int noteDuration = 1000 / noteDurations[thisNote];
tone(8, melody[thisNote], noteDuration);
// to distinguish the notes, set a minimum time between them.
// the note's duration + 30% seems to work well:
pauseBetweenNotes = noteDuration * 1.30;
thisNote++;
}
}