I teach a high school STEM class. This project is teaching basic sound. I show them a speaker playing a low tone and they can see and feel the cone going out and in. We talk about pressure waves, etc.
In the project I created for them, they can play simple songs by coding in tones, octaves, and times (beats).
Everything seems to work except octave 0. I look at the pulses with an oscilloscope and everything looks right but when I listen to it, octave 0 is messed up. The tones are way wrong. I could probably attach a sound file if you would like but it's quite easy to build if someone is willing. Circuit description is in the beginning remarks of the sketch.
I am really puzzled!
/* 0093 Play Seven Notes
Simple Circuit:
Use an NPN transistor to control the current through the speaker.
Use a separate battery pack for powering the speaker. 2 AA (3 volts) work with most speakers.
D4 to a resistor to the base of the transistor. Anything 300 to 10K works.
Ground from Arduino to battery pack negative to emitter of the transistor.
Collector of the transistor either directly to one lead of the speaker or go through a 10 ohm resistor to the speaker.
Positive voltage from the battery pack to the other lead of the speaker.
*/
int spkrPin = 4;
int Tempo = 1250; // multiplier for time for 1 count. If a 1/4 note gets 2 counts then time is 2 * Tempo to get milliseconds
float C[] = {16.4 , 32.7 , 65.4 , 130.8, 261.6, 523.3 , 1046.5 , 2093.0 , 4186.0 }; // Frequencies of notes by octave. C[4] is middle C 261.6 Hz
float Cs[] = {17.3 , 34.7 , 69.3 , 138.6 , 277.2 , 554.4 , 1108.7 , 2217.5 , 4434.9 };
float D [] = { 18.4 , 36.7 , 73.4 , 146.8 , 293.7 , 587.3 , 1174.7 , 2349.3 , 4698.6};
float Ds [] = { 19.5 , 38.9 , 77.8 , 155.6 , 311.1 , 622.3 , 1244.5 , 2489.0 , 4978.0};
float Ef [] = { 19.5 , 38.9 , 77.8 , 155.6 , 311.1 , 622.3 , 1244.5 , 2489.0 , 4978.0};
float E [] = { 20.6 , 41.2 , 82.4 , 164.8 , 329.6 , 659.3 , 1318.5 , 2637.0 , 5274.0 };
float F [] = { 21.8 , 43.7 , 87.3 , 174.6 , 349.2 , 698.5 , 1396.9 , 2793.8 , 5587.7 };
float Fs [] = { 23.1 , 46.3 , 92.5 , 185.0 , 370.0 , 740.0 , 1480.0 , 2960.0 , 5919.9};
float Gf [] = { 23.1 , 46.3 , 92.5 , 185.0 , 370.0 , 740.0 , 1480.0 , 2960.0 , 5919.9};
float G [] = { 24.5 , 49.0 , 98.0 , 196.0 , 392.0 , 784.0 , 1568.0 , 3136.0 , 6271.9 };
float Gs [] = {26.0 , 51.9 , 103.8 , 207.7 , 415.3 , 830.6 , 1661.2 , 3322.4 , 6644.9 };
float Af [] = {26.0 , 51.9 , 103.8 , 207.7 , 415.3 , 830.6 , 1661.2 , 3322.4 , 6644.9 };
float A [] = { 27.5 , 55.0 , 110.0 , 220.0 , 440.0 , 880.0 , 1760.0 , 3520.0 , 7040.0 };
float As [] = { 29.1 , 58.3 , 116.5 , 233.1 , 466.2 , 932.3 , 1864.7 , 3729.3 , 7458.6 };
float Bf [] = { 29.1 , 58.3 , 116.5 , 233.1 , 466.2 , 932.3 , 1864.7 , 3729.3 , 7458.6 };
float B [] = { 30.9 , 61.7 , 123.5 , 246.9 , 493.9 , 987.8 , 1975.5 , 3951.1 , 7902.1 };
int rest = 0; // rest pause
unsigned long endTime = 0;
long nTime = 0; // time to play this note
void setup()
{
pinMode(spkrPin, OUTPUT);
Serial.begin(9600);
}
void playNote(int Beats, float Note) // This is function "playNote". Two parameters are passed to this function. (Beats and Note)
{
// first calculate the length of time in microseconds of each pulse at a given frequency
// middle C is 262 Hz. 1 / 262 = .003822 seconds .001911 for a half cycle which equals 1911 microseconds
long pTime = 1 / Note / 2 * 1000000; // This is the time in microseconds to hold one pulse high or low
Serial.print(Note);
Serial.print(" ");
Serial.println(pTime);
nTime = Beats * Tempo; // This is the time to keep playing one note. Tempo allows an easy way to speed up or slow down a song.
endTime = millis() + nTime;
while (millis() < endTime)
{
digitalWrite (spkrPin, HIGH);
delayMicroseconds (pTime);
digitalWrite (spkrPin, LOW);
delayMicroseconds (pTime);
}
delay(15); // a tiny pause between notes to hear each one
}
void loop()
{
// Octave 0 (frequencies 16.4 to 30.9) don't play well. After that, they play fine.
playNote(3, 27.5); // ( time to play the note, frequency of the note ) could use A[0]
playNote(3, 29.1); // could use As[0] A sharp A#
playNote(3, 30.9);
playNote(3, 32.7);
playNote(3, Cs[1]);
playNote(3, D[1]);
playNote(3, Ds[1]);
delay(3000);
/*
// The following will play all the notes in the array in order from low to high
for (int octave = 0; octave <= 8; octave ++)
{
playNote(1, C[octave]);
playNote(1, Cs[octave]); // Cs is C sharp
playNote(1, D[octave]);
playNote(1, Ds[octave]);
playNote(1, E[octave]);
playNote(1, F[octave]);
playNote(1, Fs[octave]);
playNote(1, G[octave]);
playNote(1, Gs[octave]);
playNote(1, A[octave]);
playNote(1, As[octave]);
playNote(1, B[octave]);
}
delay(2000); // delay between runs
Tempo *= .8; // speed it up
if (Tempo <= 50)
{
Tempo = 250;
}
*/
}