Pages: [1]   Go Down
Author Topic: using flash storage with the Tone() function  (Read 1055 times)
0 Members and 1 Guest are viewing this topic.
South East USA
Offline Offline
God Member
*****
Karma: 5
Posts: 651
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
#include <Flash.h>

/* named tables */
FLASH_TABLE(int, Tone1, 5 /* width of table */,
    {NOTE_C6, NOTE_D6, NOTE_C6, NOTE_B5, NOTE_C6},
    {20,20,4,10,4});
FLASH_TABLE(int, Tone2, 3 /* width of table */,
    {NOTE_C6, NOTE_B5, NOTE_A5},
    {20,8,4});

I've been using the example tone melody sketch fine, but I'm trying to move my tone data to flash memory.  I have numerous short tones that I thought I would put in tables like the above example, the first row containing the notes, the 2nd row containing the duration.
I could post what I've come up with so far, but it's so hopelessly messed up, I'm afraid it'd be more of a detriment! What I was hoping to come up with was to convert the normal ToneMelody sketch into a function which I could call, maybe like this:
Code:
Play_Tone(Tone2);
Then it would get the data from the 2 rows in the table (Tone2).  One thing I figured out was that I should change the line in the example sketch (ToneMelody) from:
Code:
for (int thisNote = 0; thisNote < 8; thisNote++) {
to:
Code:
for (int thisNote = 0; thisNote < mytone.rows(); thisNote++) {
...I'm really not sure I'm sure about that even!
Logged

Left Coast, USA
Offline Offline
Sr. Member
****
Karma: 5
Posts: 499
Sometimes I just can't help myself.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

...I'm trying to move my tone data to flash memory...

The FLASH_TABLE macro creates a _FLASH_TABLE object that you can use as a function argument (to play the tunes).

Problem number 1 (not really a problem, but it's presents a "learning experience" for some):
_FLASH_TABLE is a template class.  Since your tables are integer arrays, the specific object will be _FLASH_ARRAY<int>

Problem number 2: A "minor" shortcoming of the current version of the Arduino environment is that it will not automatically create function prototypes for functions that have the object of a template class as an argument.  You have to do it yourself.

Here's an example that just prints out values from your arrays.  Obviously, your function would play each tone for the specified duration instead of just printing the integer values:

Code:
//
// testTunes.pde
//
// Demonstration of getting values from a _FLASH_TABLE
//
//  davekw7x
//
#include <Flash.h>
#include <Tone.h>

FLASH_TABLE(int, Tune1, 5, /* Number of notes in the tune */
    {NOTE_C6, NOTE_D6, NOTE_C6, NOTE_B5, NOTE_C6},
    {20,20,4,10,4});

FLASH_TABLE(int, Tune2, 3, /* Number of notes in the tune */
    {NOTE_C6, NOTE_B5, NOTE_A5},
    {20,8,4});

// Arduino will not automatically create prototypes for function templates,
// so you have to put it in before the function is invoked.
//
void printTuneTable(const _FLASH_TABLE<int> & ft);

void setup()
{
    Serial.begin(9600);
}

void loop()
{
    Serial.println("Calling printTuneTable(Tune1)");
    printTuneTable(Tune1);
    Serial.println("Calling printTuneTable(Tune2)");
    printTuneTable(Tune2);
    delay(10000);
}

void printTuneTable(const _FLASH_TABLE<int> & ft)
{
    for (int i = 0; i < ft.cols(); i++) {
        Serial.print("Note ");Serial.print(i);
        Serial.print(": Tone = ");Serial.print(ft[0][i]);
        Serial.print(", duration = ");Serial.println(ft[1][i]);
    }
    Serial.println();
}


Output:


Calling printTuneTable(Tune1)
Note 0: Tone = 1047, duration = 20
Note 1: Tone = 1175, duration = 20
Note 2: Tone = 1047, duration = 4
Note 3: Tone = 988, duration = 10
Note 4: Tone = 1047, duration = 4

Calling printTuneTable(Tune2)
Note 0: Tone = 1047, duration = 20
Note 1: Tone = 988, duration = 8
Note 2: Tone = 880, duration = 4


Regards,

Dave

Footnote:
Instead of having a 2-D array and having to make sure the sequence of tones matches the sequences of durations, I might just use a 1-D array (FLASH_ARRAY instead of FLASH_TABLE) with pairs of entries (tone and duration) for each note.  The array could be declared something like this:
Code:
FLASH_ARRAY(int, Tune3,
            NOTE_C6, 20,
            NOTE_D6, 20,
            NOTE_C6, 4,
            NOTE_B5, 10,
            NOTE_C6, 4)

And the function to access the tones could be something like this:
Code:
void printTuneArray(const _FLASH_ARRAY<int> & fa)
{
    for (int i = 0; i < fa.count()-1; i += 2) {
        Serial.print("Note ");Serial.print(i);
        Serial.print(": Tone = ");Serial.print(fa[i]);
        Serial.print(", duration = ");Serial.println(fa[i+1]);
    }
    Serial.println();
}

It might make for easier tune entry and debugging.
« Last Edit: May 02, 2011, 01:30:23 am by davekw7x » Logged

South East USA
Offline Offline
God Member
*****
Karma: 5
Posts: 651
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks, it'll take me a bit to soak this in.  So much of this is foreign when you're only coding experience is self taught BASIC.
Logged

Left Coast, USA
Offline Offline
Sr. Member
****
Karma: 5
Posts: 499
Sometimes I just can't help myself.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks, it'll take me a bit to soak this in.  So much of this is foreign when you're only coding experience is self taught BASIC.
The designers and developers of the Arduino system have worked mightily to hide some of the details of the underlying C++ language so that beginners (and some not-so-beginners) can do interesting things with simple hardware like the ATmega chips.

Once you get very far beyond the examples and canned applications that some library implementers supply, well, the training wheels come off and then you have be prepared to actually learn some of this stuff.  "Easy" for some.  For others---not so much.

It is my observation that people on this forum are ready, and willing, and even eager to help people like yourself who know how to ask questions in a way that we can actually try to offer an approach to a solution.  I try to give complete sample programs, where appropriate, in the hope that once you see a way of doing something you can go on to higher forms of learning.  (Or at least if the method is suitable for your needs then you can get on to the creative part of your project and not get bogged down in some reference or text book.)


Regards,

Dave
Logged

South East USA
Offline Offline
God Member
*****
Karma: 5
Posts: 651
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks.  I like your 2nd example, but I can't figure out why I get the error
Quote
printTuneArray was not declared in this scope

Code:
//
// testTunes.pde
//
// Demonstration of getting values from a _FLASH_TABLE
//
//  davekw7x
//
#include <Flash.h>
#include "Tone.h"

FLASH_TABLE(int, Tune1, 5, /* Number of notes in the tune */
    {NOTE_C5, NOTE_D6, NOTE_C6, NOTE_B5, NOTE_C6},
    {20,20,4,10,4});

FLASH_TABLE(int, Tune2, 3, /* Number of notes in the tune */
    {NOTE_C6, NOTE_B5, NOTE_A5},
    {20,8,4});

FLASH_ARRAY(int, Tune3,
            NOTE_C6, 20,
            NOTE_D6, 20,
            NOTE_C6, 4,
            NOTE_B5, 10,
            NOTE_C6, 4)

// Arduino will not automatically create prototypes for function templates,
// so you have to put it in before the function is invoked.
//
void printTuneTable(const _FLASH_TABLE<int> & ft);

void setup()
{
    Serial.begin(9600);
}

void loop()
{
    Serial.println("Calling printTuneTable(Tune1)");
    printTuneTable(Tune1);
    Serial.println("Calling printTuneTable(Tune2)");
    printTuneTable(Tune2);
    Serial.println("Calling printTuneTable(Tune3)");   
    printTuneArray(Tune3);
    delay(10000);
}

void printTuneTable(const _FLASH_TABLE<int> & ft)
{
    for (int i = 0; i < ft.cols(); i++) {
        Serial.print("Note ");Serial.print(i);
        Serial.print(": Tone = ");Serial.print(ft[0][i]);
        Serial.print(", duration = ");Serial.println(ft[1][i]);
    }
    Serial.println();
}


void printTuneArray(const _FLASH_ARRAY<int> & fa)
{
    for (int i = 0; i < fa.count()-1; i += 2) {
        Serial.print("Note ");Serial.print(i);
        Serial.print(": Tone = ");Serial.print(fa[i]);
        Serial.print(", duration = ");Serial.println(fa[i+1]);
    }
    Serial.println();
}
Logged

South East USA
Offline Offline
God Member
*****
Karma: 5
Posts: 651
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

...the part in yellow is what gives the error.  I can't figure out why???
Code:
//
// testTunes.pde
//
// Demonstration of getting values from a _FLASH_TABLE
//
//  davekw7x
//
#include <Flash.h>
#include "Tone.h"

FLASH_TABLE(int, Tune1, 5, /* Number of notes in the tune */
    {NOTE_C5, NOTE_D6, NOTE_C6, NOTE_B5, NOTE_C6},
    {20,20,4,10,4});

FLASH_TABLE(int, Tune2, 3, /* Number of notes in the tune */
    {NOTE_C6, NOTE_B5, NOTE_A5},
    {20,8,4});

FLASH_ARRAY(int, Tune3,
            NOTE_C6, 20,
            NOTE_D6, 20,
            NOTE_C6, 4,
            NOTE_B5, 10,
            NOTE_C6, 4)

// Arduino will not automatically create prototypes for function templates,
// so you have to put it in before the function is invoked.
//
void printTuneTable(const _FLASH_TABLE<int> & ft);

void setup()
{
    Serial.begin(9600);
}

void loop()
{
    Serial.println("Calling printTuneTable(Tune1)");
    printTuneTable(Tune1);
    Serial.println("Calling printTuneTable(Tune2)");
    printTuneTable(Tune2);
    Serial.println("Calling printTuneTable(Tune3)");  
    printTuneArray(Tune3);
    delay(10000);
}

void printTuneTable(const _FLASH_TABLE<int> & ft)
{
    for (int i = 0; i < ft.cols(); i++) {
        Serial.print("Note ");Serial.print(i);
        Serial.print(": Tone = ");Serial.print(ft[0][i]);
        Serial.print(", duration = ");Serial.println(ft[1][i]);
    }
    Serial.println();
}


void printTuneArray(const _FLASH_ARRAY<int> & fa)
{
    for (int i = 0; i < fa.count()-1; i += 2) {
        Serial.print("Note ");Serial.print(i);
        Serial.print(": Tone = ");Serial.print(fa[i]);
        Serial.print(", duration = ");Serial.println(fa[i+1]);
    }
    Serial.println();
}
printTuneArray(Tune3);
[/quote]
Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 290
Posts: 25816
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You have no prototype for printTuneArray.
You must have a prototype for functions with reference arguments.
Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Left Coast, USA
Offline Offline
Sr. Member
****
Karma: 5
Posts: 499
Sometimes I just can't help myself.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

...the part in yellow is what gives the error.  I can't figure out why???

Code:
.
.
.
// Arduino will not automatically create prototypes for function templates,
// so you have to put it in before the function is invoked.
//
void printTuneTable(const _FLASH_TABLE<int> & ft);
void printTuneArray(const _FLASH_ARRAY<int> & fa); // <---This is what was missing.
.
.
.

    Serial.println("Calling printTuneArray(Tune3)");   // <--- Change message to show what you are actually calling
    printTuneArray(Tune3);

.
.
.

Regards,

Dave
Logged

South East USA
Offline Offline
God Member
*****
Karma: 5
Posts: 651
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

GOT IT!, THANKS!  I can use this in future codes, too, to make it easy to add sounds...
Code:
#include <Flash.h>
#include "Tone.h"
int speakerPin = 8;
FLASH_ARRAY(int, Tune3,
            NOTE_C6, 40,
            NOTE_D6, 40,
            NOTE_C6, 160,
            NOTE_B5, 40,
            NOTE_C6, 400)
void PlayTune(const _FLASH_ARRAY<int> & fa);
void setup()
{
    Serial.begin(9600);
}

void loop()
{
    PlayTune(Tune3);
    delay(10000);
}

void PlayTune(const _FLASH_ARRAY<int> & fa)
{
    for (int i = 0; i < fa.count()-1; i += 2) {
        tone(speakerPin, fa[i],fa[i+1]);
        int pauseBetweenNotes = fa[i+1] * 1.30;
        delay(pauseBetweenNotes);
       noTone(8);    // stop the tone playing:
    }
}

Logged

Left Coast, USA
Offline Offline
Sr. Member
****
Karma: 5
Posts: 499
Sometimes I just can't help myself.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

GOT IT!...

Ahhhh...It's kind of fun when it works, right?

By the way, as a matter of style (for consistency):
Code:
       noTone(8);    // stop the tone playing:

Would be better if it were
Code:
       noTone(speakerPin);    // stop the tone playing:


Regards,

Dave

Footnote:
"After all---No one was born knowing this stuff..."
---davekw7x
« Last Edit: May 02, 2011, 02:36:54 pm by davekw7x » Logged

Pages: [1]   Go Up
Jump to: