The Arduino Volume library allows a user's Arduino to generate square waves with 256 volume levels, using nothing but a speaker/piezo and a digital pin!
Producing analog outputs with a digital pin might sound like voodoo, but it's simple if you use an RC Filter to smooth a PWM signal into a corresponding voltage. But that takes extra circuitry and time! Instead, we can trick the speaker itself into acting as the filter. By driving PWM faster than the speaker can physically respond (62,500Hz to be exact) a 5 volt PWM signal at 50% duty cycle will make the speaker act as if it was fed 2.5V. This is the technique used to produce sound at various volumes!
For generating a square wave at 440Hz, we'd normally do this loop:
- Set output to HIGH
- Wait for 1,136 microseconds
- Set output LOW
- Wait for 1,136 microseconds
But with this ultrasonic PWM trick, we can do 440Hz at half volume:
- analogWrite(output, 127);
- Wait for 1,136 microseconds
- analogWrite(output, 0);
- Wait for 1,136 microseconds
This way, the speaker responds like it would with a 2.5V square wave. To do this, the library utilizes two hardware timers, Timer 0 and Timer 1.
Timer 0:It first sets Timer 0 to produce PWM on pins 5 & 6 (Uno) at 62,500Hz. This way when we analogWrite() one of these pins, the speaker connected to it can't keep up with the PWM frequency and instead produces it's average for analog-like output.
Timer 1:Timer 1 is set to interrupt at double the desired frequency, to alternate the output pin between PWM output and 0 volts.
Now all you have to do is call vol.tone(434, 64); to produce a 434Hz square wave at 25% volume!
For full documentation of the library and some example code, download Volume through the Arduino Library Manager and visit the README on Github!
Comments