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.
}