Working With Microcontroller-Generated Audio Frequencies: (Adapted From The Machine Science Tutorial)
Working With Microcontroller-Generated Audio Frequencies: (Adapted From The Machine Science Tutorial)
Working With Microcontroller-Generated Audio Frequencies: (Adapted From The Machine Science Tutorial)
If we attach a speaker between a microcontroller output pin and ground, we can click the speaker in
the same way we blink an LED. When the pin goes high (5 volts at the output) the current creates an
electromagnetic field that causes the speaker to flex. When the pin goes low (zero volts at the
output) the speaker contracts back to its previous position. Constantly flexing the speaker back and
forth at the right speed will generate an audible tone.
The process of the pin going high for a duration and then going low for a duration is called a cycle,
and the total high-pin duration plus the low-pin duration is referred to as the period of the frequency.
frequency = 1 / period
frequency = 1 / (0.5 seconds)
frequency = 2 cycles / second
-or-
frequency = cycles / second
frequency = (3 cycles) / (1.5 seconds)
frequency = 2 cycles / second
The most common unit of frequency is the Hertz. One cycle per second is equal to one Hertz.
1 Hertz = 1 cycle / second
Therefore, in the example shown above, the frequency is 2 Hertz.
Now that you know how frequency and period are related, it is possible to determine the frequency of
the tone your speaker will produce, just by looking at your code. The period of the tone will be the sum
of the two delays in each cycle of your for... loop. Using the Machine Science compiler, we can make
use of two delay functions: delay_ms(); -delay in milliseconds and delay_us(); -delay in micro-
seconds (note use of letter u to stand for -the Greek letter Mu.)
For example, in the following code, the delays are 1,000 microseconds each:
digitalWrite(7, HIGH);
delayMicroseconds(1000); <------------ a 1000-microsecond delay
digitalWrite(7, LOW);
delayMicroseconds(1000); <------------ a 1000-microsecond delay
The note A has a frequency of 440 cycles per second; the note B has a frequency of 494 cycles per
second; and so on.
//--- "Speaker_Start" Plays a pitch thru a speaker and lights an LED ---
//--- Set up: > Attach a piezo speaker between ground and Digital pin 8
// > Wire an LED from Digital pin 7 thru a 330 ohm resistor to gnd
The delays in the above code use an integer of 1500 in the delay statement to generate delays of
1500 millionths of a second. Now, if we wanted to figure out how long the delays in our on/off states
(pulses) should be to produce a specific pitch (note), how would we calculate that?
Calculating Pulse Length from Frequency
Let's use note A (440 hz) as an example. It's accomplished in two steps:
Each period (cycle, in hertz) is the length of one second divided by the frequency. We are using a
delay measurement is in microseconds ( delay_us(); ) so a duration of one second is one million
microseconds (1000000). Therefore our period will be 1000000 / 440, or 2272.7272. once we know
the total period of one cycle is 2272.7272 millionths of a second, the last part is easy. The delay for
each pulse-on and pulse-off is half of that.
2. pulse = period / 2
2272.7272 divided by 2 is approximately 1136.3636. So the code in our main loop to generate a
frequency of A-440 for a duration of 200 clicks would be:
2. We use the variable cycles in our For Loop (instead of a hard-coded value like 200)
for(i=0; i<=cycles; i++)
3. In our main loop, when we call our play_pitch() function, we pass along frequency
and duration:
play_pitch(440, 100);
Now if you initialized variable names like: int A = 440; or int longNote=800; or
int shortNote=100;
Try different variations. Here's a version that generates random pitches in an infinite loop: