Arduino tone() just got 10-bit volume control!*
*with no extra components!
Ever needed a project to play a tone through a speaker or piezo that wasn't blisteringly loud? You can bring the volume down with a resistor, but what if you needed a loud alert beep at some point as well?
Now it's no longer an issue. :) Using ultra-fast PWM, the Volume library allows the speaker itself to act as an RC filter to produce smooth (10-bit) analog-like volume control.
- Installation
- Usage
- Functions
- Supported Pins
- Limitations
- Volume Library Comparison
- Contributing
- License and credits
With Arduino Library Manager:
- Open Sketch > Include Library > Manage Libraries in the Arduino IDE.
- Search for "Volume3", (look for "Connor Nishijima") and select the latest version.
- Click the Install button and Arduino will prepare the library and examples for you!
Manual Install:
- Click "Clone or Download" above to get an "arduino-volume3-master.zip" file.
- Extract it's contents to the libraries folder in your sketchbook.
- Rename the folder from "arduino-volume3-master" to "Volume3".
Using the volume-controlled vol.tone()
function is very similar to the Arduino tone()
:
Arduino:
- tone(unsigned int pin, unsigned int frequency);
Volume3:
- vol.tone(byte pin, unsigned int frequency, unsigned int volume);
Volume control is limited to certain pins. See Supported Pins.
Here is what you need to get started with the bare minimum:
#include "Volume3.h" // Include the Volume library
#define speakerPin 9
void setup() {
// Nothing here!
}
void loop() {
uint16_t volume = 1023;
uint16_t frequency = 440;
while(volume > 0){
vol.tone(speakerPin,frequency,volume);
volume--;
delay(10);
}
}
vol.tone(byte pin, unsigned int frequency, unsigned int volume);
This is where the magic happens. At the frequency you specify, your Arduino will analogWrite(volume) to the speaker with a PWM frequency of 100,000 Hz, for half the duration of a single period of the frequency before pulling it LOW
. This high-speed PWM is beyond your range of hearing, (and probably the functioning range of your speaker) so it will just sound like a quieter or louder version of the input frequency!
vol.noTone();
This is identical in function to the standard noTone()
function, this stops any currently playing tones.
Board | Pin1 | Pin2 | Tested |
---|---|---|---|
(Uno) ATmega168/328(pb) | 9 | 10 | YES |
(Mega) ATmega1280/2560 | 11 | 12 | NO |
(Leo/Micro) ATmega16u2/32u4 | 9 | 10 | NO |
Unfortunately, cheating the Arduino's normal functions in this way means we'll lose some of them. This is also still a proof-of-concept library at this point, so it may break more functionality than I'm aware of. Sorry!
ATmega Only:*
I don't know if I'll have this working on ATTiny*5 boards any time soon, though it's theoretically possible on any AVR supported by the TimerOne. For now, it's only confirmed working on Arduino Uno (ATMega168/328) and Mega. (ATMega1280/2560)
Volume is limited to certain pins:
This is because on AVRs with Timer1 - only 2 pins are in that timer's control. It also means that while you're using Volume3, normal analogWrite()
use probably won't work on these two pins.
Now that there are three separately-developed Volume libraries, here is a table delineating their abilities. One will be good for higher frequencies, one will do custom waves, one will have higher volume accuracy, and so forth. Eventually I'm looking to merge them, but for now each has it's strengths and weaknesses.
Library | Volume1 | Volume2 | Volume3 |
---|---|---|---|
Accuracy | 8-bit (255) | 8-bit (255) | 10-bit (1023) |
Frequency Range (Hz) | 120 - 5000 | 1 - 3400 | 1 - 4186 |
PWM Frequency (Hz) | 62,500 | 62,500 | 100,000 |
Polyphony | 1 | 1 | 1 |
Needs vol.begin() | YES | YES | NO |
Compiled Library Size (Bytes) | 2,501 | 2,542 | 1,054 |
Ram Usage (Bytes) | 39 | 457 | 24 |
Frequency Slide Quality | GREAT | BAD | GOOD |
Timer Usage | 0, 1 | 0, 1 | 1 |
Delay Issue (Timer0 Prescaler) | YES | YES | NO |
Square Wave | YES | YES | YES |
Sawtooth Wave | NO | YES | NO |
Triangle Wave | NO | YES | NO |
Sine Wave | NO | YES | NO |
Custom Wave | NO | YES | NO |
Any advice or pull requests are welcome. :)
Developed by Connor Nishijima (2016)
Released under the GPLv3 license.