Hi,
I am playing some music with 2 piezo elements and a standalone Atmega328P.
I store the frequencies of the notes in constants, then I created a struct, which contains the notes for both piezos and the length of the note, and I create an array of these structs, which is later passed to a function which plays the music.
Everything works fine, but as I add more and more music my RAM gets full too quickly.
Here is the code:
#include <Tone.h>
//Define the notes frq
#define G2 98
#define Gs2 104
#define Ab2 104
#define A2 110
#define As2 116
... and so on with many other music notes ...
#define Fs7 2960
#define Gb7 2960
#define G7 3136
//Rest
#define R 0
typedef struct {
int n1;
int n2;
byte units;
} NOTES;
Tone buzzer1; //The buzzer name is because of a mistake//
Tone buzzer2;
int marioTempo = 50;
NOTES superMario[] = {
{E5, Fs4, 3},
{E5, Fs4, 3},
{R, R, 3},
{E5, Fs4, 3},
{R, R, 3},
{C5, Fs4, 3},
{E5, Fs4, 3},
{R, R, 3},
{G5, G4, 6},
{R, R, 6},
{G4, G4, 6},
{R, R, 6},
{C5, E4, 6},
{R, R, 3},
{G4, C4, 6},
{R, R, 3},
{E4, G3, 6},
{R, R, 3},
{A4, C5, 3},
{R, R, 3},
{B4, D4, 3},
{R, R, 3},
{Bb4, Db4, 3},
{A4, C4, 6},
{G4, C4, 3},
{R, R, 1},
{E5,G4, 3},
{R, R, 1},
{G5, B4, 3},
{R, R, 1},
{A5,C5, 3},
{R, R, 3},
{F5, A4, 3},
{G5, B4, 3},
{R, R, 3},
{E5, A4, 3},
{R, R, 3},
{C5, E4, 3},
{D5, F4, 3},
{B4, D4, 6},
{R, R, 3},
{C5, E4, 6},
{R, R, 3},
{G4, C4, 6},
{R, R, 3},
{E4, G3, 6},
{R, R, 3},
{A4, C4, 3},
{R, R, 3},
{B4, D4, 3},
{R, R, 3},
{Bb4, Db4, 3},
{A4, C4, 6},
{G4, C4, 3},
{R, R, 1},
{E5, G4, 3},
{R, R, 1},
{G5, B4, 3},
{R, R, 1},
{A5, C5, 3},
{R, R, 3},
{F5, A4, 3},
{G5, B4, 3},
{R, R, 3},
{E5, A4, 3},
{R, R, 3},
{C5, E4, 3},
{D5, F4, 3},
{B4, D4, 6},
{R, R, 3}
};
void playSong(NOTES song[], size_t numNotes, int tempo)
{
//We store the frw of the second pizo in this variable
int secondFrq = 0;
//Walk through the array of music
for(int i = 0; i < numNotes; i++)
{
// Only play if it is not a rest
if(song[i].n1 > 0)
{
//Play the note of the first piezo
buzzer1.play(song[i].n1, (song[i].units*tempo));
//If the frq of the second piezo is 0, we play the same note as the first, else the note set for the second one
if(song[i].n2 == 0)
{
secondFrq = song[i].n1;
}else{
secondFrq = song[i].n2;
}
buzzer2.play(secondFrq, (song[i].units*tempo));
}
//Then we wait for the note to end plus a little, between two notes
delay((song[i].units*tempo) + 10);
}
}
void setup() {
buzzer1.begin(buzzer1Pin);
buzzer2.begin(buzzer2Pin);
}
void loop() {
playSong3(superMario, sizeof(superMario)/sizeof(superMario[0]), marioTempo);
}
I thought that I put references in the structs like:
typedef struct {
const int n1;
const int n2;
byte units;
} NOTES;
but surprisingly it took even more room in the RAM.
I read some about the PROGMEM but I am not sure if it is possible to put my array of struct and the constants to the PROGMEM.
If it is possible, how can I access it later?
I heard that it is quite diddicult to read from there.
Or what is the most efficient way to do this?
Thanks in advance for any help.