Tone Trauma!?

I’m working on an Arduino based music generator, currently i’m experimenting with amplitude control, attack and decay and i’ve hit a sticking point - it’s not behaving as i’d hoped.

It plays notes and ramps the amps using analogWrite(), however it won’t play the notes in the right order and they get faster and faster the higher they get (As the pitch increases the notes get shorter). There’s also a few crazy, but cool sounding, anomalies near the end of the note sequence.

I wanted the program to play each note one after another from the lowest pitch to the highest, then it’s supposed to hit max and start from the beginning of the notes again.

Help is much appreciated, thanks Arduinovacates!

unsigned int c1 = 61156;   // Notes (values equal to half the wavelength in micro seconds)
unsigned int cs1 = 57724;
unsigned int d1 = 54484;
unsigned int ds1 = 51426;
unsigned int e1 = 48540;
unsigned int f1 = 45815;
unsigned int fs1 = 43244;
unsigned int g1 = 40817;
unsigned int gs1 = 38526;
unsigned int a1 = 36364;
unsigned int as1 = 34323;
unsigned int b1 = 32396;

unsigned int c2 = 30578;
unsigned int cs2 = 28862;
unsigned int d2 = 27242;
unsigned int ds2 = 25713;
unsigned int e2 = 24270;
unsigned int f2 = 22908;
unsigned int fs2 = 21622;
unsigned int g2 = 20408;
unsigned int gs2 = 19263;
unsigned int a2 = 18182;
unsigned int as2 = 17161;
unsigned int b2= 16198;

unsigned int c3 = 15289;
unsigned int cs3 = 14431;
unsigned int d3 = 13621;
unsigned int ds3 = 12856;
unsigned int e3 = 12135;
unsigned int f3 = 11454;
unsigned int fs3 = 10811;
unsigned int g3 = 10204;
unsigned int gs3 = 9631;
unsigned int a3 = 9091;
unsigned int as3 = 8581;
unsigned int b3 = 8099;

unsigned int c4 = 7644;
unsigned int cs4 = 7215;
unsigned int d4 = 6810;
unsigned int ds4 = 6428;
unsigned int e4 = 6067;
unsigned int f4 = 5727;
unsigned int fs4 = 5405;
unsigned int g4 = 5102;
unsigned int gs4 = 4816;
unsigned int a4 = 4545;
unsigned int as4 = 4290;
unsigned int b4 = 4049;

unsigned int c5 = 3822;
unsigned int cs5 = 3608;
unsigned int d5 = 3405;
unsigned int ds5 = 3214;
unsigned int e5 = 3034;
unsigned int f5 = 2863;
unsigned int fs5 = 2703;
unsigned int g5 = 2551;
unsigned int gs5 = 2408;
unsigned int a5 = 2273;
unsigned int as5 = 2145;
unsigned int b5 = 2025;

unsigned int c6 = 1911;
unsigned int cs6 = 1804;
unsigned int d6 = 1703;
unsigned int ds6 = 1607;
unsigned int e6 = 1517;
unsigned int f6 = 1432;
unsigned int fs6 = 1351;
unsigned int g6 = 1275;
unsigned int gs6 = 1204;
unsigned int a6 = 1136;
unsigned int as6 = 1073;
unsigned int b6 = 1012;

unsigned int c7 = 956;
unsigned int cs7 = 902;
unsigned int d7 = 851;
unsigned int ds7 = 803;
unsigned int e7 = 758;
unsigned int f7 = 716;
unsigned int fs7 = 676;
unsigned int g7 = 638;
unsigned int gs7 = 602;
unsigned int a7 = 568;
unsigned int as7 = 536;
unsigned int b7 = 506;

unsigned int c8 = 478;
unsigned int cs8 = 451;
unsigned int d8 = 426;
unsigned int ds8 = 402;
unsigned int e8 = 379;
unsigned int f8 = 358;
unsigned int fs8 = 338;
unsigned int g8 = 319;
unsigned int gs8 = 301;
unsigned int a8 = 284;
unsigned int as8 = 268;
unsigned int b8 = 253;

unsigned int c9 = 239;
unsigned int cs9 = 225;
unsigned int d9 = 213;
unsigned int ds9 = 201;
unsigned int e9 = 190;
unsigned int f9 = 179;
unsigned int fs9 = 169;
unsigned int g9 = 159;
unsigned int gs9 = 150;
unsigned int a9 = 142;
unsigned int as9 = 134;
unsigned int b9 = 126;

unsigned int c10 = 119;

unsigned int note = 0; // current note

unsigned int melody[] = {c1,cs1,d1,ds1,e1,f1,fs1,g1,gs1,a1,as1,b1, c2,cs2,d2,ds2,e2,f2,fs2,g2,gs2,a2,as2,b2, c3,cs3,d3,ds3,e3,f3,fs3,g3,gs3,a3,as3,b3, c4,cs4,d4,ds4,e4,f4,fs4,g4,gs4,a4,as4,b4, c5,cs5,d5,ds5,e5,f5,fs5,g5,gs5,a5,as5,b5, c6,cs6,d6,ds6,e6,f6,fs6,g6,gs6,a6,as6,b6, c7,cs7,d7,ds7,e7,f7,fs7,g7,gs7,a7,as7,b7, c8,cs8,d8,ds8,e8,f8,fs8,g8,gs8,a8,as8,b8, c9,cs9,d9,ds9,e9,f9,fs9,g9,gs9,a9,as9,b9, c10};

int VOLUME = 0; 
boolean state = false;
  
void setup()
{ 
Serial.begin(9600);
clearLCD();

/************************** PWM audio configuration ****************************/
// Configures PWM on pins 3 and 11 to run at maximum speed, rather than the default

pinMode(3,OUTPUT); //Speaker on pin 3

cli(); //disable interrupts while registers are configured

bitSet(TCCR2A, WGM20);
bitSet(TCCR2A, WGM21); //set Timer2 to fast PWM mode (doubles PWM frequency)

bitSet(TCCR2B, CS20);
bitClear(TCCR2B, CS21);
bitClear(TCCR2B, CS22);

sei(); //enable interrupts now that registers have been set
}

void loop()
{
    if(state == false) // Ramp Up Note (Attack)
    {
    VOLUME++;
    VOLUME++;
    VOLUME++;
    VOLUME++;
    VOLUME++;
    VOLUME++;
    VOLUME++;
    VOLUME++;
    playTone(melody[note], 1); 
    }
  
    if(state == true) // Ramp Down Note (Decay)
    {
    VOLUME--;
    VOLUME--;
    VOLUME--;
    VOLUME--;
    VOLUME--;
    VOLUME--;
    VOLUME--;
    VOLUME--;
    playTone(melody[note], 2);  
    }
    
    if(VOLUME >= 255) // If fully ramped up - begin ramp down
    {          
    state = true;
    } 
  
    if(VOLUME <= 0) // If fully ramped down - change to next note and ramp up
    {   
    note++;  
    state = false;
    } 
    
    if (note >= 120) // If last note in sequence is reached then reset to the begining
    {
    note = 0;  
    clearLCD();
    Serial.print("Reset Note Sequence");
    delay(2000);
    clearLCD();
    }
}

  
void playTone(long tone, int duration) 
{
  for (long i = 0; i < duration; i ++) 
  {
    analogWrite(3, VOLUME);
    delayMicroseconds(tone);
    analogWrite(3, 0);
    delayMicroseconds(tone);
  }
}


void clearLCD()
{
   Serial.print(0xFE, BYTE);   //command flag
   Serial.print(0x01, BYTE);   //clear command.
}
delayMicroseconds(tone);

that's why playing speed changes with tone. You probably want a constant there (or 'duration' while skipping the loop in playTone)

    VOLUME++;
    VOLUME++;
    VOLUME++;
    VOLUME++;
    VOLUME++;
    VOLUME++;
    VOLUME++;
    VOLUME++;

nobody is looking at VOLUME between the lines here, so why not make it

VOLUME+=8;
[glow]const[/glow] unsigned int c1 = 61156;
...

No need to declare a separate variable for each note, c1 is not going to change while the program is running. Make all of them "const" to save some memory.

Cheers that's a good help,

I've got loads of VOLUME++ cuz I was just experimenting with the speed of the ramp, will probably use a multiplier there to get faster ramps, just didn't get round to it.

Thanks for the tip on const - It's a new one for me.

I'll have to have a re-thunk on the delayMicroseconds(), thanks for the diagnosis DrHex 8-)

Wow - just updated the notes to 'const unsigned int' and the crazy anomalies near the end went even crazier :o

Code update - I’ve attempted to address the speed issue in playTone(), but the issue persists.

Thanks

const unsigned int c1 = 61156;   // Notes (values equal to half the wavelength in micro seconds)
const unsigned int cs1 = 57724;
const unsigned int d1 = 54484;
const unsigned int ds1 = 51426;
const unsigned int e1 = 48540;
const unsigned int f1 = 45815;
const unsigned int fs1 = 43244;
const unsigned int g1 = 40817;
const unsigned int gs1 = 38526;
const unsigned int a1 = 36364;
const unsigned int as1 = 34323;
const unsigned int b1 = 32396;

const unsigned int c2 = 30578;
const unsigned int cs2 = 28862;
const unsigned int d2 = 27242;
const unsigned int ds2 = 25713;
const unsigned int e2 = 24270;
const unsigned int f2 = 22908;
const unsigned int fs2 = 21622;
const unsigned int g2 = 20408;
const unsigned int gs2 = 19263;
const unsigned int a2 = 18182;
const unsigned int as2 = 17161;
const unsigned int b2= 16198;

const unsigned int c3 = 15289;
const unsigned int cs3 = 14431;
const unsigned int d3 = 13621;
const unsigned int ds3 = 12856;
const unsigned int e3 = 12135;
const unsigned int f3 = 11454;
const unsigned int fs3 = 10811;
const unsigned int g3 = 10204;
const unsigned int gs3 = 9631;
const unsigned int a3 = 9091;
const unsigned int as3 = 8581;
const unsigned int b3 = 8099;

const unsigned int c4 = 7644;
const unsigned int cs4 = 7215;
const unsigned int d4 = 6810;
const unsigned int ds4 = 6428;
const unsigned int e4 = 6067;
const unsigned int f4 = 5727;
const unsigned int fs4 = 5405;
const unsigned int g4 = 5102;
const unsigned int gs4 = 4816;
const unsigned int a4 = 4545;
const unsigned int as4 = 4290;
const unsigned int b4 = 4049;

const unsigned int c5 = 3822;
const unsigned int cs5 = 3608;
const unsigned int d5 = 3405;
const unsigned int ds5 = 3214;
const unsigned int e5 = 3034;
const unsigned int f5 = 2863;
const unsigned int fs5 = 2703;
const unsigned int g5 = 2551;
const unsigned int gs5 = 2408;
const unsigned int a5 = 2273;
const unsigned int as5 = 2145;
const unsigned int b5 = 2025;

const unsigned int c6 = 1911;
const unsigned int cs6 = 1804;
const unsigned int d6 = 1703;
const unsigned int ds6 = 1607;
const unsigned int e6 = 1517;
const unsigned int f6 = 1432;
const unsigned int fs6 = 1351;
const unsigned int g6 = 1275;
const unsigned int gs6 = 1204;
const unsigned int a6 = 1136;
const unsigned int as6 = 1073;
const unsigned int b6 = 1012;

const unsigned int c7 = 956;
const unsigned int cs7 = 902;
const unsigned int d7 = 851;
const unsigned int ds7 = 803;
const unsigned int e7 = 758;
const unsigned int f7 = 716;
const unsigned int fs7 = 676;
const unsigned int g7 = 638;
const unsigned int gs7 = 602;
const unsigned int a7 = 568;
const unsigned int as7 = 536;
const unsigned int b7 = 506;

const unsigned int c8 = 478;
const unsigned int cs8 = 451;
const unsigned int d8 = 426;
const unsigned int ds8 = 402;
const unsigned int e8 = 379;
const unsigned int f8 = 358;
const unsigned int fs8 = 338;
const unsigned int g8 = 319;
const unsigned int gs8 = 301;
const unsigned int a8 = 284;
const unsigned int as8 = 268;
const unsigned int b8 = 253;

const unsigned int c9 = 239;
const unsigned int cs9 = 225;
const unsigned int d9 = 213;
const unsigned int ds9 = 201;
const unsigned int e9 = 190;
const unsigned int f9 = 179;
const unsigned int fs9 = 169;
const unsigned int g9 = 159;
const unsigned int gs9 = 150;
const unsigned int a9 = 142;
const unsigned int as9 = 134;
const unsigned int b9 = 126;

const unsigned int c10 = 119;

unsigned int note = 0; // current note

unsigned int melody[] = {c1,cs1,d1,ds1,e1,f1,fs1,g1,gs1,a1,as1,b1, c2,cs2,d2,ds2,e2,f2,fs2,g2,gs2,a2,as2,b2, c3,cs3,d3,ds3,e3,f3,fs3,g3,gs3,a3,as3,b3, c4,cs4,d4,ds4,e4,f4,fs4,g4,gs4,a4,as4,b4, c5,cs5,d5,ds5,e5,f5,fs5,g5,gs5,a5,as5,b5, c6,cs6,d6,ds6,e6,f6,fs6,g6,gs6,a6,as6,b6, c7,cs7,d7,ds7,e7,f7,fs7,g7,gs7,a7,as7,b7, c8,cs8,d8,ds8,e8,f8,fs8,g8,gs8,a8,as8,b8, c9,cs9,d9,ds9,e9,f9,fs9,g9,gs9,a9,as9,b9, c10};

int VOLUME = 0; 
boolean state = false;
long prevMicros = 0;
  
void setup()
{ 
Serial.begin(9600);
clearLCD();

/************************** PWM audio configuration ****************************/
// Configures PWM on pins 3 and 11 to run at maximum speed, rather than the default

pinMode(3,OUTPUT); //Speaker on pin 3

cli(); //disable interrupts while registers are configured

bitSet(TCCR2A, WGM20);
bitSet(TCCR2A, WGM21); //set Timer2 to fast PWM mode (doubles PWM frequency)

bitSet(TCCR2B, CS20);
bitClear(TCCR2B, CS21);
bitClear(TCCR2B, CS22);

sei(); //enable interrupts now that registers have been set
}

void loop()
{
    if(state == false) // Ramp Up Note (Attack)
    {
    VOLUME++;
    VOLUME++;
    VOLUME++;
    VOLUME++;
    VOLUME++;
    VOLUME++;
    VOLUME++;
    VOLUME++;
    playTone(melody[note], 10); 
    }
  
    if(state == true) // Ramp Down Note (Decay)
    {
    VOLUME--;
    VOLUME--;
    VOLUME--;
    VOLUME--;
    VOLUME--;
    VOLUME--;
    VOLUME--;
    VOLUME--;
    playTone(melody[note], 10);  
    }
    
    if(VOLUME >= 255) // If fully ramped up - begin ramp down
    {          
    state = true;
    } 
  
    if(VOLUME <= 0) // If fully ramped down - change to next note and ramp up
    {   
    note++;  
    state = false;
    } 
    
    if (note >= 120) // If last note in sequence is reached then reset to the begining
    {
    note = 0;  
    clearLCD();
    Serial.print("Reset Note Sequence");
    delay(2000);
    clearLCD();
    }
}

  
void playTone(long tone, int duration) 
{
[glow]prevMicros = micros();

  if (micros() - prevMicros <= duration) 
  {
    analogWrite(3, VOLUME);
    delayMicroseconds(tone);
    analogWrite(3, 0);
    delayMicroseconds(tone);
  }[/glow]
}


void clearLCD()
{
   Serial.print(0xFE, BYTE);   //command flag
   Serial.print(0x01, BYTE);   //clear command.
}
while (micros() - prevMicros < duration)
  {
    analogWrite(3, VOLUME);
    delayMicroseconds(tone);
    analogWrite(3, 0);
    delayMicroseconds(tone);
  }

?

Cheers - Okay, I’ve put the While loop in and changed the <=, it hasn’t remedied any of the issues…is there a reason why I should change the code to this, not quite sure I understand your suggestion?

void playTone(long tone, int duration)
{
 [glow] prevMicros = micros();[/glow]

  while (micros() - prevMicros < duration)
  {
    analogWrite(3, VOLUME);
    delayMicroseconds(tone);
    analogWrite(3, 0);
    delayMicroseconds(tone);
  } 
}

Did you keep the highlighted line?
The idea with the while loop is to keep playing for as long as the duration specifies.

Also try a fixed number instead of ‘tone’ as an argument to delayMicroseconds.

Yeah I kept the prevMicros = micros(); line, I can’t really have a fixed value for the tone as it would not allow me to adjust the frequency of the oscillation / the pitch of the note. What I’d like to do is fix the duration the notes / tones that are played.

So your right…I do need a constant in there - I’d just prefer it to be the tone length rather than the tone frequency itself.

Thanks for your comments and assistance.

I can't really have a fixed value for the tone as it would not allow me to adjust the frequency of the oscillation / the pitch of the note

Oh... I assumed you controlled the frequency of the tone by adjusting OCR2A.

If I understand the code correctly, instead of a variable for each note in every octave, just include the first octave's variables. You can get other octaves by doubling or halving those numbers, depending on how your code works. One octave interval=twice the frequency. Just an idea to cut down on memory usage.

@ SCIGUY - I thought about implementing that - but an issue is the fact the all the intervals/frequencies are integer numbers…so they are just an estimate of the actual interval/frequency used for equal tempered western musical notes - which are normally floats. The reason for writing out all 9 octaves was to give a greater degree of frequency accuracy.

Thanks for the tip tho.

@ DRHEX - I see, so… OCR2A is just the Arduino’s hardware timer?

So - would it be easier to adjust OCR2A to change the freq? I take it that it works differently to using a delay() ?

Tx

I think I know why it still gets faster and faster…the duration of the tone is often much less than the length of the period divided by 2. So playing the tone once is often longer than what i want the duration to be (in order to get a smooth amplitude ramp)

I’ve increased the duration time and it’s helped with the speeding up issue, although it’s still not perfect. I might look at adjusting the freq of the hardware timer, but I’m not familiar with it so i’ll probably need to do a bit of learning and testing first.

However - I am still at a total loss as to why the notes don’t play in order :-? It’s very weird, I thought the note++ would just go through the melody[] one step at a time…but I’m obviously still missing something important??

code update -

const unsigned int c1 = 61156;   // Notes (values equal to half the wavelength in micro seconds)
const unsigned int cs1 = 57724;
const unsigned int d1 = 54484;
const unsigned int ds1 = 51426;
const unsigned int e1 = 48540;
const unsigned int f1 = 45815;
const unsigned int fs1 = 43244;
const unsigned int g1 = 40817;
const unsigned int gs1 = 38526;
const unsigned int a1 = 36364;
const unsigned int as1 = 34323;
const unsigned int b1 = 32396;

const unsigned int c2 = 30578;
const unsigned int cs2 = 28862;
const unsigned int d2 = 27242;
const unsigned int ds2 = 25713;
const unsigned int e2 = 24270;
const unsigned int f2 = 22908;
const unsigned int fs2 = 21622;
const unsigned int g2 = 20408;
const unsigned int gs2 = 19263;
const unsigned int a2 = 18182;
const unsigned int as2 = 17161;
const unsigned int b2= 16198;

const unsigned int c3 = 15289;
const unsigned int cs3 = 14431;
const unsigned int d3 = 13621;
const unsigned int ds3 = 12856;
const unsigned int e3 = 12135;
const unsigned int f3 = 11454;
const unsigned int fs3 = 10811;
const unsigned int g3 = 10204;
const unsigned int gs3 = 9631;
const unsigned int a3 = 9091;
const unsigned int as3 = 8581;
const unsigned int b3 = 8099;

const unsigned int c4 = 7644;
const unsigned int cs4 = 7215;
const unsigned int d4 = 6810;
const unsigned int ds4 = 6428;
const unsigned int e4 = 6067;
const unsigned int f4 = 5727;
const unsigned int fs4 = 5405;
const unsigned int g4 = 5102;
const unsigned int gs4 = 4816;
const unsigned int a4 = 4545;
const unsigned int as4 = 4290;
const unsigned int b4 = 4049;

const unsigned int c5 = 3822;
const unsigned int cs5 = 3608;
const unsigned int d5 = 3405;
const unsigned int ds5 = 3214;
const unsigned int e5 = 3034;
const unsigned int f5 = 2863;
const unsigned int fs5 = 2703;
const unsigned int g5 = 2551;
const unsigned int gs5 = 2408;
const unsigned int a5 = 2273;
const unsigned int as5 = 2145;
const unsigned int b5 = 2025;

const unsigned int c6 = 1911;
const unsigned int cs6 = 1804;
const unsigned int d6 = 1703;
const unsigned int ds6 = 1607;
const unsigned int e6 = 1517;
const unsigned int f6 = 1432;
const unsigned int fs6 = 1351;
const unsigned int g6 = 1275;
const unsigned int gs6 = 1204;
const unsigned int a6 = 1136;
const unsigned int as6 = 1073;
const unsigned int b6 = 1012;

const unsigned int c7 = 956;
const unsigned int cs7 = 902;
const unsigned int d7 = 851;
const unsigned int ds7 = 803;
const unsigned int e7 = 758;
const unsigned int f7 = 716;
const unsigned int fs7 = 676;
const unsigned int g7 = 638;
const unsigned int gs7 = 602;
const unsigned int a7 = 568;
const unsigned int as7 = 536;
const unsigned int b7 = 506;

const unsigned int c8 = 478;
const unsigned int cs8 = 451;
const unsigned int d8 = 426;
const unsigned int ds8 = 402;
const unsigned int e8 = 379;
const unsigned int f8 = 358;
const unsigned int fs8 = 338;
const unsigned int g8 = 319;
const unsigned int gs8 = 301;
const unsigned int a8 = 284;
const unsigned int as8 = 268;
const unsigned int b8 = 253;

const unsigned int c9 = 239;
const unsigned int cs9 = 225;
const unsigned int d9 = 213;
const unsigned int ds9 = 201;
const unsigned int e9 = 190;
const unsigned int f9 = 179;
const unsigned int fs9 = 169;
const unsigned int g9 = 159;
const unsigned int gs9 = 150;
const unsigned int a9 = 142;
const unsigned int as9 = 134;
const unsigned int b9 = 126;

const unsigned int c10 = 119;

unsigned int note = 0; // current note

unsigned int melody[] = {c1,cs1,d1,ds1,e1,f1,fs1,g1,gs1,a1,as1,b1, c2,cs2,d2,ds2,e2,f2,fs2,g2,gs2,a2,as2,b2, c3,cs3,d3,ds3,e3,f3,fs3,g3,gs3,a3,as3,b3, c4,cs4,d4,ds4,e4,f4,fs4,g4,gs4,a4,as4,b4, c5,cs5,d5,ds5,e5,f5,fs5,g5,gs5,a5,as5,b5, c6,cs6,d6,ds6,e6,f6,fs6,g6,gs6,a6,as6,b6, c7,cs7,d7,ds7,e7,f7,fs7,g7,gs7,a7,as7,b7, c8,cs8,d8,ds8,e8,f8,fs8,g8,gs8,a8,as8,b8, c9,cs9,d9,ds9,e9,f9,fs9,g9,gs9,a9,as9,b9, c10};

int VOLUME = 0; 
int mult = 20;
boolean state = false;
long prevMicros = 0;
  
void setup()
{ 
/************************** PWM audio configuration ****************************/
// Configures PWM on pins 3 and 11 to run at maximum speed, rather than the default

pinMode(3,OUTPUT); //Speaker on pin 3

cli(); //disable interrupts while registers are configured

bitSet(TCCR2A, WGM20);
bitSet(TCCR2A, WGM21); //set Timer2 to fast PWM mode (doubles PWM frequency)

bitSet(TCCR2B, CS20);
bitClear(TCCR2B, CS21);
bitClear(TCCR2B, CS22);

sei(); //enable interrupts now that registers have been set

Serial.begin(9600);
clearLCD();
}

void loop()
{
    if(state == false) // Ramp Up Note (Attack)
    {
    VOLUME+= mult;
    playTone(melody[note], 8000); 
    }
  
    if(state == true) // Ramp Down Note (Decay)
    {
    VOLUME-= mult;
    playTone(melody[note], 8000);  
    }
    
    if(VOLUME >= 255) // If fully ramped up - begin ramp down
    {          
    state = true;
    } 
  
    if(VOLUME <= 0) // If fully ramped down - change to next note and ramp up
    {   
    note++;  
    state = false;
    } 
    
    if (note >= 120) // If last note in sequence is reached then reset to the begining
    {
    note = 0;  
    clearLCD();
    Serial.print("Reset Note Sequence");
    delay(2000);
    clearLCD();
    }
}

  
void playTone(long tone, int duration) 
{
prevMicros = micros();

  while (micros() - prevMicros < duration) 
  {
    analogWrite(3, VOLUME);
    delayMicroseconds(tone);
    analogWrite(3, 0);
    delayMicroseconds(tone);
  }
}


void clearLCD()
{
   Serial.print(0xFE, BYTE);   //command flag
   Serial.print(0x01, BYTE);   //clear command.
}

Which version of the Arduino IDE are you using? With some versions, there is a tone library. With later versions, the tone functions are incorporated.

It looks like your method of playing the note is the source of the problem. Use the tone function, instead, to actually play the note, and see if that doesn't give better results.

Thanks PaulS - I’m on Arduino Alpha 0017.

I’ve looked at the tone library but I was unsure about it…could I use it and control amplitude too, maybe implement attack or decay envelopes?

Also…I was a bit worried by the notes used in tone() as they didn’t seem correct? The numbers don’t match up with frequency of standard musical notes - for example lower C on a piano (midi value 36) is 65.406 Hz - half that wave length in microseconds is 7215.459 ← okay so it doesn’t need to be that accurate and even rounding a few integers here and there wont make that much of a difference…but none of the numbers are close, the tone library is confusing! (to me)

Basically all the octaves are marked backwards in tone() converse to how octaves are marked in MIDI and musical notation, the notes also look wrong…the intervals may sound ok but **is tone() in tune overall? **

Sorry to lay a can of worms out like that - but I used a digital tuner to test if my notes were right and they checked out fine, I then looked at tone() to compare and all the numbers were totally different? So I tried to use the tone Library to test with a tuner and i couldn’t get it to work -

I tried this example http://www.arduino.cc/en/Tutorial/Tone and it wouldn’t work :-[ it kept saying →

In function 'void setup()':
error: 'tone' was not declared in this scope

With version 17, the Tone library is separate. You'll need to download it. http://code.google.com/p/rogue-code/wiki/ToneLibraryDocumentation

At the very least, you can see how the library plays the note, compared to how you are doing it, to verify that you are doing it right.

It's integrated in the latest download....ah i'll probably just get the new one then, thanks for the pointer. Think I'll do some quick tests to see if tone() is in tune....then I'll check back in on this thread.

Cheers.

I've downloaded the latest version of the Arduino IDE and I've been looking at tone(), yeah it works and it's in tune! but it doesn't have any control over amplitude, I had a look in Tone.cpp and I couldn't work out how it was generating the frequencies let alone how to add an amplitude parameter?

My program is a bit bonkers, it's totally out of tune in the low freq end - but it's okay above that and it will let you set the volume too.

Not sure if I should try to fix my program, or alter the tone library to suit? (eek - looks daunting!)