Need help trimming my code for 2 piezo song/alarm

Hey you!

I have been working on an alarm clock for a while now, and I decided to use 2 piezo buzzers and a song as an alarm for it. I have encountered a few problems while using Tone command (and overall), but decided on using improved Tone Lib.
First I tried using Pokemon wild battle theme, but decided not to because it needed more than 2 tones at the same time playing to sound correct, and I'm using arduino uno which doesn't have enough timers for it.
So I composed oldschool Doom for it and it works fine with only 2. But my code is way too long for the song part and I want it to be shorter, so I am asking help accomplishing that.
So which way would be best to shorten it? I tried using the code and idea from Play a Melody using the tone() function
and inserting the commands from Tone.h but couldn't get the song sound right.
In my alarm clock I have designed the song to be in if or for structure.

Here's a small clip of the song code.

#include <Tone.h>
Tone tone1;
Tone tone2;

void setup() {
tone1.begin(2);
tone2.begin(4);
}
void loop() {
int x = 125;
int y = 62;
//10-11 this is only a small part of the song
tone1.play(NOTE_E2, 100);
tone2.play(NOTE_E1, 100);
delay(x);
tone1.play(NOTE_E2, 100);
tone2.play(NOTE_E1, 100);
delay(x);
tone1.play(NOTE_E2, 100);
tone2.play(NOTE_E3, 100);
delay(x);
tone1.play(NOTE_E2, 100);
tone2.play(NOTE_E1, 100);
delay(x);
tone1.play(NOTE_E2, 100);
tone2.play(NOTE_E1, 100);
delay(x);
tone1.play(NOTE_D2, 100);
tone2.play(NOTE_D3, 100);
delay(x);
tone1.play(NOTE_E2, 100);
tone2.play(NOTE_E1, 100);
delay(x);
tone1.play(NOTE_E2, 100);
tone2.play(NOTE_E1, 100);
//
delay(x);
}

Put your note and duration data in an array of structs. Two actually, one for tone1 and another for tone2.

1 Like

Could you give me an example? I tried the example from Play a Melody using the tone() function and it didn't work as I hoped.

This is what I tried but its off. It seems like it doesn't play the tones at the same time as it should

#include <Tone.h>
Tone tone1;
Tone tone2;
int melody1 = {
NOTE_E2, NOTE_E2, NOTE_E3, NOTE_E2, NOTE_E2, NOTE_D3, NOTE_E2, NOTE_E2,
NOTE_C3, NOTE_E2, NOTE_E2, NOTE_AS2, NOTE_E2, NOTE_E2, NOTE_B2, NOTE_C3,
NOTE_E2, NOTE_E2, NOTE_E3, NOTE_E2, NOTE_E2, NOTE_D3, NOTE_E2, NOTE_E2
};
int melody2 = {
NOTE_E1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
NOTE_E1, 0, 0, 0, 0, 0, 0, 0,
};

int noteDurations1 = {
4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4,
};

int noteDurations2 = {
4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4,
};

void setup() {
tone1.begin(2);
tone2.begin(4);
}
void loop()
{
for (int thisNote = 0; thisNote < 24; thisNote++) {
int noteDuration1 = 400 / noteDurations1[thisNote];
int noteDuration2 = 400 / noteDurations2[thisNote];
tone1.play(melody1[thisNote], noteDuration1);
tone2.play(melody2[thisNote], noteDuration2);
int pauseBetweenNotes = noteDuration1 * 1.25;
delay(pauseBetweenNotes);
}
delay(4000);
}

My maths was just off. It works fine now. Well maybe someone will get some help if they are trying to achieve the same thing as I did. There were no similar examples anywhere.

I'm glad to see you got it working. Here's what I was thinking:

struct NoteData 
{
int note;
int duration;
};

NoteData Tone1Notes[]={{NOTE_E2, 100},{NOTE_E2, 100}};
const int NumNotes = sizeof Tone1Notes/sizeof Tone1Notes[0];

@wildbill
Well now I encountered a new problem with the example code.
If tone2 should be playing longer note than tone 1, it doesn't. Or the code stops until the tone2 has done playing the long tone and tone1 shorter tones are waiting.
So how would have your example worked? Or figure out any workarounds for my code?

It's the classic problem in Arduino. You're going to need to to ditch delay and use millis for timing instead.

I haven't used millis before, I tried but it plays only the first note. What am I not understanding?

...
const unsigned long eventInterval = 200;
unsigned long previousTime = 0;
...
void loop()
{
unsigned long currentTime = millis();
{
for (int thisNote = 0; thisNote < 32 && (currentTime - previousTime >= eventInterval); thisNote++) {
int noteDuration1 = 800 / noteDurations1[thisNote];
int noteDuration2 = 800 / noteDurations2[thisNote];
tone1.play(melody1[thisNote], noteDuration1);
tone2.play(melody2[thisNote], noteDuration2);
previousTime = currentTime;
}
}
}

At the end of your for loop you set previous time to current time, so the difference isn't greater than eventInterval, so your loop condition is false and the loop ends.

I think you're going to need to do the two tones independently. Keep timers for each and decide when time is up for the note you're on and move to the next.

I can't get the millis to work, can you help me understand how should I fix the for function?

2 different for functions?

No, drop the for and let loop itself take care of it.

But then I lose the basis of my code, which reads the next note every time the for loop has gone through.
If I do that I need to rewrite the code in a new way, and I don't have any idea how to do that other than the example way from Play Melody using tone
PS. Thank you for helping, I haven't coded in C++ in years and my skills were never on a advanced level. And I'm very willing to learn and understand everything, and don't need a ready code.

Edit; Ofc the code works without the for loops, I could go back to where it was but the code was too long and my arduino doesn't have enough space for it.

When the melody starts, I.e. In setup in your example, save millis and set an index variable to zero. Call tone for the first note.

In loop, check if millis is greater than saved millis by the note duration or more. When it is, save millis again, increment index and play the tone that index tells you to.

Same thing for tone two.

Hello again @wildbill
If I understood correctly, I did what you suggested, but still the sounds are short.

#include <Tone.h>
unsigned long time_now1 = 0;
unsigned long time_now2 = 0;
int period1 = 25;
int period2 = 25;
int thisNote1 = 0;
int thisNote2 = 0;
Tone tone1;
Tone tone2;
int melody1 = {
NOTE_E2, NOTE_E2, NOTE_E3, NOTE_E2, NOTE_E2, NOTE_D3, NOTE_E2, NOTE_E2,
NOTE_C3, NOTE_E2, NOTE_E2, NOTE_AS2, NOTE_E2, NOTE_E2, NOTE_B2, NOTE_C3,
NOTE_E2, NOTE_E2, NOTE_E3, NOTE_E2, NOTE_E2, NOTE_D3, NOTE_E2, NOTE_E2,
NOTE_C3, NOTE_E2, NOTE_E2, NOTE_E2, NOTE_E2, 0, 0, 0,

};
int noteDurations1 = {
100, 100, 100, 100, 100, 100, 100, 100,
100, 100, 100, 100, 100, 100, 100, 100,
100, 100, 100, 100, 100, 100, 100, 100,
100, 100, 100, 100, 100, 100, 100, 100,
};

int melody2 = {
NOTE_C6, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
NOTE_C6, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, NOTE_AS6, NOTE_AS6,
};
int noteDurations2 = {
1000, 100, 100, 100, 100, 100, 100, 100,
100, 100, 100, 100, 100, 100, 100, 100,
1000, 100, 100, 100, 100, 100, 100, 100,
100, 100, 100, 100, 1000,
};

void setup() {
tone1.begin(2);
tone2.begin(4);
}
void loop()
{
unsigned long currentTime = millis();
{
if (millis() >= time_now1 + period1 && thisNote1 < 32) {
int noteDuration1 = noteDurations1[thisNote1];
tone1.play(melody1[thisNote1], noteDuration1);
time_now1 += period1 + noteDuration1;
thisNote1++;
}
}
{
if (millis() >= time_now2 + period2 && thisNote2 < 32) {
int noteDuration2 = noteDurations1[thisNote2];
tone2.play(melody2[thisNote2], noteDuration2);
time_now2 += period2 + noteDuration2;
thisNote2++;
}
}
}

You have your array of durations, but you're using Period1 instead to decide when to do the next tone. After 25 milliseconds, the next note overwrites what you were doing.

if (millis() >= time_now2 + period2 && thisNote2 < 32) {
int noteDuration2 = noteDurations1[thisNote2];

noteDurations1 should have been noteDurations2
Seems to be working, for now. Thanks for helping me!

@wildbill Now I'm having an another memory problem.

Sketch uses 4872 bytes (15%) of program storage space. Maximum is 32256 bytes.
Global variables use 1711 bytes (83%) of dynamic memory, leaving 337 bytes for local variables. Maximum is 2048 bytes.
Low memory available, stability problems may occur.

I was thinking of shortening the note data from "NOTE_XY" to only "XY" but the int doesn't allow it ("'XY' was not declared in this scope"), and it seems like I need to use string then where I put the information together back to NOTE_XY. Can you give me a headstart to this problem? Thank you.

And shall I encounter new problems when shortening the data inside int? For example I have part of code which tells the code when to stop which basically is:

const int noteCount = sizeof(melody2);
if (millis() >= time_now1 + noteDuration1 && thisNote1 < noteCount)

Take a look at progmem. You can use it to keep your melody data out of RAM.

Thank you again and again, and again.
And then I need help again. I have had this next problem for a while but had let it slide and trying to figure it out on the side, but now when everything else seems to be fine, I hacen't been able to point out why its happening.
I'm getting a offsync between the 2 tones (or the if functions) after 8 lines (32 notes) of code. Care to help?
I was thinking it has to do something with the 0's (Don't divide anything with 0), but the code seems to work fine before the code hits a very long note (1) (I have pointed it out with "//offsync" in the code. But I was thinking it must be something else.

#include <Tone.h>
unsigned long time_now1 = 0;
unsigned long time_now2 = 0;
int thisNote1 = 0;
int thisNote2 = 0;
Tone tone1;
Tone tone2;
const int melody1 PROGMEM = {
NOTE_E2, NOTE_E2, NOTE_E3, NOTE_E2, NOTE_E2, NOTE_D3, NOTE_E2, NOTE_E2,
NOTE_C3, NOTE_E2, NOTE_E2, NOTE_AS2, NOTE_E2, NOTE_E2, NOTE_B2, NOTE_C3,
NOTE_E2, NOTE_E2, NOTE_E3, NOTE_E2, NOTE_E2, NOTE_D3, NOTE_E2, NOTE_E2,
NOTE_C3, NOTE_E2, NOTE_E2, NOTE_E2, NOTE_E2, 0, 0, 0,

NOTE_E2, NOTE_E2, NOTE_E3, NOTE_E2, NOTE_E2, NOTE_D3, NOTE_E2, NOTE_E2,
NOTE_C3, NOTE_E2, NOTE_E2, NOTE_AS2, NOTE_E2, NOTE_E2, NOTE_B2, NOTE_C3,
NOTE_E2, NOTE_E2, NOTE_E3, NOTE_E2, NOTE_E2, NOTE_D3, NOTE_E2, NOTE_E2,
NOTE_C3, NOTE_E2, NOTE_E2, NOTE_E2, NOTE_E2, 0, 0, 0,

NOTE_E2, NOTE_E2, NOTE_E3, NOTE_E2, NOTE_E2, NOTE_D3, NOTE_E2, NOTE_E2,
NOTE_C3, NOTE_E2, NOTE_E2, NOTE_AS2, NOTE_E2, NOTE_E2, NOTE_B2, NOTE_C3,
NOTE_E2, NOTE_E2, NOTE_E3, NOTE_E2, NOTE_E2, NOTE_D3, NOTE_E2, NOTE_E2,
NOTE_C3, NOTE_E2, NOTE_E2, NOTE_AS2, NOTE_AS2, 0, 0, 0,

NOTE_E2, NOTE_E2, NOTE_E3, NOTE_E2, NOTE_E2, NOTE_D3, NOTE_E2, NOTE_E2,
NOTE_C3, NOTE_E2, NOTE_E2, NOTE_AS2, NOTE_E2, NOTE_E2, NOTE_B2, NOTE_C3,
NOTE_E2, NOTE_E2, NOTE_E3, NOTE_E2, NOTE_E2, NOTE_D3, NOTE_E2, NOTE_E2,

NOTE_FS4, NOTE_E4, NOTE_DS4, NOTE_FS4, NOTE_GS4, NOTE_G4, NOTE_FS4, NOTE_D4,
NOTE_FS4, NOTE_G4, NOTE_A4, NOTE_B4, NOTE_A4, NOTE_G4, NOTE_FS4, NOTE_D4,

NOTE_E2, NOTE_E2, NOTE_E2, NOTE_E2, NOTE_E2, NOTE_D2, NOTE_E2, NOTE_E2,
NOTE_C2, NOTE_E2, NOTE_E2, NOTE_AS2, NOTE_E2, NOTE_E2, NOTE_B2, NOTE_C3,
NOTE_E2, NOTE_E2, NOTE_E2, NOTE_E2, NOTE_E2, NOTE_D2, NOTE_E2, NOTE_E2,
NOTE_C2, NOTE_E2, NOTE_E2, NOTE_E2, NOTE_E2, NOTE_E2, NOTE_E2, NOTE_E2,

NOTE_E2, NOTE_E2, NOTE_E2, NOTE_E2, NOTE_E2, NOTE_D2, NOTE_E2, NOTE_E2,
NOTE_C2, NOTE_E2, NOTE_E2, NOTE_AS2, NOTE_E2, NOTE_E2, NOTE_B2, NOTE_C3,
NOTE_E2, NOTE_E2, NOTE_E2, NOTE_E2, NOTE_E2, NOTE_D2, NOTE_E2, NOTE_E2,

NOTE_B4, NOTE_G4, NOTE_E4, NOTE_G4, NOTE_B4, NOTE_G4, NOTE_B4, NOTE_E5,
NOTE_B4, NOTE_G4, NOTE_B4, NOTE_G4, NOTE_B4, NOTE_E5, NOTE_G5, NOTE_B5,
};
const int noteDurations1 PROGMEM = {
8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 2, 0, 0, 0,

8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 2, 0, 0, 0,

8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 2, 0, 0, 0,

8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8,

16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,

8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8,

8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8,

16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,
};
const int melody2 PROGMEM = {
NOTE_C3, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
NOTE_C3, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, NOTE_AS2, NOTE_AS2, 0, 0, 0,

NOTE_C3, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
NOTE_C3, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, NOTE_AS2, NOTE_AS2, 0, 0, 0,

NOTE_E1, 0, 0, 0, 0, 0, 0, 0,
NOTE_E1, 0, 0, 0, 0, 0, 0, 0,
NOTE_E1, 0, 0, 0, 0, 0, 0, 0,
NOTE_E1, 0, 0, 0, 0, 0, 0, 0,

NOTE_E1, 0, 0, 0, 0, 0, 0, 0,
NOTE_E1, 0, 0, 0, 0, 0, 0, 0,
NOTE_E1, 0, 0, 0, 0, 0, 0, 0,

0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,

NOTE_E1, NOTE_E1, NOTE_E3, NOTE_E1, NOTE_E1, NOTE_D3, NOTE_E2, NOTE_E2,
NOTE_C3, NOTE_E1, NOTE_E1, NOTE_AS1, NOTE_E1, NOTE_E1, NOTE_B1, NOTE_C2,
NOTE_E1, NOTE_E1, NOTE_E3, NOTE_E1, NOTE_E1, NOTE_D3, NOTE_E2, NOTE_E2,
NOTE_C3, NOTE_E1, NOTE_E1, NOTE_AS2, NOTE_AS2, 0, 0, 0,

NOTE_E1, NOTE_E1, NOTE_E3, NOTE_E1, NOTE_E1, NOTE_D3, NOTE_E2, NOTE_E2,
NOTE_C3, NOTE_E1, NOTE_E1, NOTE_AS1, NOTE_E1, NOTE_E1, NOTE_B1, NOTE_C2,
NOTE_E1, NOTE_E1, NOTE_E3, NOTE_E1, NOTE_E1, NOTE_D3, NOTE_E2, NOTE_E2,

0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
};
const int noteDurations2 PROGMEM = {
8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 2, 0, 0, 0,

8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 2, 0, 0, 0,
//OFFSYNC!
1, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0,

1, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0,

16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,

8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 2, 0, 0, 0,

8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8,

16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,

};

//const int noteCount = sizeof (melody2);
void setup() {
tone1.begin(2);
tone2.begin(4);
}
void loop()
{
unsigned long currentTime = millis();
unsigned long pauseBetweenNotes1 = 0;
unsigned long pauseBetweenNotes2 = 0;
unsigned long noteDuration1 = 0;
unsigned long noteDuration2 = 0;
{
if (millis() >= time_now1 + noteDuration1 && thisNote1 < 208) {
noteDuration1 = 800 / pgm_read_byte (noteDurations1 + thisNote1);
pauseBetweenNotes1 = 200 / pgm_read_byte(noteDurations1 + thisNote1);
tone1.play(pgm_read_byte(melody1 + thisNote1), noteDuration1);
thisNote1++;
time_now1 += noteDuration1 + pauseBetweenNotes1;
}
}
{
if (millis() >= time_now2 + noteDuration2 && thisNote2 < 208) {
noteDuration2 = 800 / pgm_read_byte(noteDurations2+thisNote2);
pauseBetweenNotes2 = 200 / pgm_read_byte(noteDurations2+thisNote2);
tone2.play(pgm_read_byte(melody2 + thisNote2), noteDuration2);
thisNote2++;
time_now2 += noteDuration2 + pauseBetweenNotes2;
}
}
if (thisNote2 == 208){
tone1.stop();
tone2.stop();
}
}