My previous post looked at all the theory of using PWM on an Arduino and finished with an example showing how to use Timer 1 to generate a PWM output on pin 9.
This post provides an alternative set of PWM routines that allows you to generate an audio signal on pin 3 using Timer 2.
Warning! I strongly recommend using old or second hand equipment for your experiments. I am not responsible for any damage to expensive instruments!
These are the key Arduino tutorials for the main concepts used in this project:
- Arduino Foundations PWM
- Sparkfun What is Pulse-width Modulation
- Secrets of Arduino PWM
- PWM DAC
- Working with Atmel AVR Microcontroller Basic Pulse Width Modulation (PWM) Peripheral
If you are new to Arduino, see the Getting Started pages.
Parts list
- Arduino Uno
- 10k potentiometer
- 1x 220Ω resistor and 8 ohm speaker or old headphone speaker
- Optional Arduino PWM Output Filter Circuit
- Breadboard and jumper wires
- Optional oscilloscope to observe the outputs
The Circuit

This is the same circuit as before, but now the audio output will be happening on pin 3, so that pin needs to be connected to your output device (speaker and resistor, or output circuit), then connect the return or GND signal to GND on the Arduino.
Once again I’ve used my Arduino PWM Output Filter Circuit and connected it to a small portable amplifier and speaker.
The Code
For all the background theory for this code, see Arduino PWM Sound Output.
In this example, I’ve attempted to replicate the Timer 1 settings on Timer 2, but there is an issue. Timer 2 is an 8-bit timer, so it can only support counter values up to 255. This means that it isn’t possible to use FastPWM with a counter value of 487 as used previously. This leaves two options:
- Double the PWM frequency to 65536Hz, allowing the use of 243 as a counter value.
- Use PWM Phase Correct mode, which if you recall will count twice – once up and then back down – so we get a 32768Hz PWM frequency with a counter value of 244.
My initial try used PWM Phase Correct mode, but there was a curious issue. The output waveform has a weird “null” point part way through the wave. I don’t know why this is the case, debugging through the code “in slow motion” it seems to be counting through the accumulator fine and pulling appropriate values out of the wavetable ok.
In Phase Correct PWM mode the interrupt gets triggered at the bottom of the cycle rather than the top as for FastPWM, so I don’t know if that accounts for something. I did try building it to trigger an interrupt on OC2A compare instead, which happens at the top, but that didn’t make any difference.
When the PWM frequency is the same as the sample rate, I wonder if there are times when there is some kind of odd phasing effect going on – could that account for some weirdness?
In the end I decided to go back to FastPWM mode with a frequency of 65536Hz, but rather than change the sample rate, only write a sample out on every other “tick” of the interrupt. I figured this would mean that even if there was some odd phasing effect, there should be at least one cycle of PWM for every sample change as the PWM cycles are now running twice as fast as the sample rate.
So these are the settings I’ve now used:
- Using a sample frequency of 32768Hz.
- Using a PWM frequency of 65536Hz.
- Using Timer 2 in Fast PWM mode, no pre-scaler, using OCR2A as the “TOP” value set to 243.
- Using the Timer 2 overflow interrupt to trigger the “sample output” routine.
- Using OCR2B as the compare value, so using OC2B is the PWM output which is pin 3 on the Uno.
- Using a wavetable of 256 values, pre-calculated in the setup() routine.
- Using a potentiometer on A0 to choose a frequency from 220 (pot reads 0) to 1243 (pot reads 1023).
This has the following audio properties:
- Sample rate of 32768Hz.
- PWM peak to peak of 0 to 244.
- DC offset bias of 122.
- Wavetable values in the range 0 to 255.
This seems to do the trick.
In the photo below you can see the initial “test” 25% PWM signal at 63536Hz, followed by a 220Hz sine wave after filtering.
The code has now been updated to provide the option of building it to support Timer 2 with output on pin 3.
Closing Thoughts
It would be really nice to be able to create some kind of “audio PWM on any pin that supports it” library at some point. I don’t know if such a thing exists? I’ve not come across one on my travels so far.
Do let me know if you spot any mistakes or misunderstandings in any of the above or the previous article, and do feel free to point me in the direction of any more generic audio code for PWM on the Uno!
Kevin

