Arduino PWM Sound Output

Up to this point I’ve been using a range of audio output options, of varying fidelity, including outputting “PWM” using the Mozzi synthesis library, but I haven’t actually experimented with PWM, or Pulse Width Modulation, itself directly so thought it was time I looked into it a bit more.

  • In Part 2 there is an alternative version using a different pin for the Arduino.
  • There is a design for an output shield in this post here.
IMG_5336

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:

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

Arduino PWM_bb

The audio output will be happening on pin 9, 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.

I’ve used my Arduino PWM Output Filter Circuit and connected it to a small portable amplifier and speaker.

The Discussion

The Arduino, or more specifically the ATmega328 on which it is based, has several options for creating pulse-width modulation (PWM) signals.  As described in “Secrets of Arduino PWM” it can even be generated “by hand” by turning IO pins on and off at the right moment, but the real strength of a microcontroller is having this kind of facility built right into the hardware.

In one sentence, think of pulse-width modulation as a square wave with a variable relative “width” of the HIGH and LOW portions of the wave but keeping the width of the combined wave-shape the same.

Why is this useful?  Well if the signal is continually on (HIGH) 25% of the time and off (LOW) 75% of the time repeatedly, and HIGH is a 5V level and LOW is a 0V level, then on average the output will be 25% of the HIGH value.  For 5V that is around 1.25V.  Using this basic principle, any voltage (on average) can be created between 0 and 5V – so a digital output can be made to “look like” an analog output to a first approximation.

It is a bit more complicated than that, and the signal isn’t very “clean”, but this principle can be used to control LEDS, servos, and in our case, to generate a “pretend” analog output that can be modulated to produce audio.

PWM Pins and analogWrite

If you don’t mind what base frequency you are using for your PWM signal, you can use the Arduino analogWrite() function to create your “pseudo analog output” signals, as described on the main analogWrite reference page.

For the Arduino Uno, you can create PWM signals on pins 3, 5, 6, 9, 10, 11 using a base frequency of either 490Hz or 980Hz depending on the pin.  These are linked to the various outputs of the ATmega328’s three timers.  But if you are wanting to create audio waveforms, then the simple analogWrite() option isn’t good enough, so you have to do it yourself.

Whilst you can create PWM signals with the 328’s Timer 0, I’m not going into that here as this timer is used by the Arduino environment for the delay() and millis() functions.

So that leaves Timer 1 and Timer 2:

  • Timer 1 is a 16-bit timer with PWM outputs on pins D9 (OC1A) and D10 (OC1B).
  • Timer 2 is a 8-bit timer with PWM outputs on pins D11 (OC2A) and D3 (OC2B).

The general idea is that you set your timer counting from 0 to a “TOP” value (which may be fixed or configurable, depending on the mode), then set up a “compare” value typically via a register called something like OCR1A or OCR2B.  As the timer reaches, and then passes, the compare value it will change the state of the associated pin (OCR1A controls OC1A which is on pin D9, and so on) and then carry on counting up to the TOP value.  What happens next depends on the mode.

PWM Modes of Operation

There are many modes and options, all specified in the ATmega328 datasheet, and talked about in the various tutorials above, but to summarise, some of the options include:

  • Choosing if you want a fixed or configurable TOP value.
  • Choosing which of the outputs (and so which compare registers) are active – both timers have an A and B output and you can have one or both active.
  • Setting the basic counting frequency and how it relates to the main MCU clock (which is 16MHz for the Arduino Uno).
  • Deciding what happens when the counter gets to the TOP value – will it reset straight back to zero again, or will it start counting back down again?
  • Choosing if any of the associated interrupts are enabled (e.g. overflow, “compare A”, “compare B”).

So as you can see, there are many options and the whole system is very configurable, but setting up the different modes and understanding the different options and what they mean can be quite confusing.

When it comes to PWM there are three main “modes” to consider:

  • Fast PWM.
  • Phase correct PWM.
  • Phase and frequency correct PWM.

Deciding which to use isn’t particularly obvious, but the best (and detailed) description I’ve found is in the “Working with the Atmel PWM Peripheral” post, but as I understand it, the key points are as follows:

  • Fast PWM – only requires the counter to count from BOTTOM to TOP and then reset immediately, so it can run at twice the frequency as other modes that rely on counting both up and down.  The downside is that the phase of the waveform changes each time the compare value changes.  In  particular if you are using both A and B outputs the they will both start their cycle at the same time as shown below.
FastPWM

  • Phase correct PWM – this requires the counter to count from BOTTOM to TOP and back to BOTTOM again, so it runs at half the frequency of Fast PWM as it is counting twice.  But the advantage is that the output changes on the way up and back on the way down again, meaning that the signals are kept “in phase” as the compare frequencies change.  If you are using both outputs, this means they will maintain the same “centre” of each pulse as shown below.
PCPWM

  • Phase and frequency correct PWM – this is basically the same as phase correct mode, but the compare values become significant at the BOTTOM of the count rather than the top.  This has the effect that the generated waveform is always symmetrical about the count.  This is only significant if you are regularly changing the basic PWM frequency – i.e. you want to be changing the TOP value all the time.  If you are keeping a constant TOP value, then this is basically the same as phase correct PWM as I understand things.

You can see another illustration of the difference between Fast PWM and the two phase correct modes, including seeing why the frequency halves, below.

IMG_5327

PWM for Audio

Now that the basic modes have been discussed, we need to think about how we can use PWM for the creation of audio.  The basic idea is to have a wavetable of samples and output a sample at a specific sample rate to the PWM hardware.  In practice this means there are several timers and frequencies at play, namely:

  • The basic PWM rate, determined by the clock source for the timer, the TOP value it counts too, and the mode – remember Fast PWM counts twice as fast as the two phase correct modes.
  • The sample rate, determined by the speed at which samples are “sent” to the PWM hardware for “playing”.
  • The resulting audio frequencies from playing the samples via PWM.  This is largely an “emergent property” of sending a series of waveform samples to the PWM hardware at the sample rate and depends on the number of samples in one cycle of the waveform.

There is one other variable that we need to consider too – the PWM resolution.  This is the range of samples that the PWM hardware “understands”.  If the basic PWM rate involves a counter counting from 0 to 255 to generate a “full sweep” then setting the PWM compare value to 0 corresponds (simplistically) to an output of 0; setting the PWM compare value to 255 corresponds to “HIGH all the time”, so is the full HIGH output, which is 5V in the case of the Uno.  Using a value of 128 means the output is HIGH for half the time and LOW for the other half, so on average that corresponds to a value of 2.5V.  The percentage of time the signal is HIGH is called the duty cycle (see the above tutorials), so half and half is a 50% duty cycle.

So the PWM resolution in this example is 256, as there are 256 levels we can choose from nothing to “full volume” (0 through up to 255) and it is directly related to the counter value used for the TOP.  Note that what TOP means in terms of output voltage is always the same – “full range” or “HIGH all the time” – which for the Arduino Uno means a steady 5V – we are just talking about the number of “steps” that can be used to get there.

Audio Frequencies

Working backwards from a specific audio signal, we can get an idea of what sorts of timings and counter values we are talking about to generate audio frequencies.

Consider that we want to play a 440Hz note, which is “concert A”, from a wave (sine, triangle, saw, it doesn’t matter) defined by 256 values in a wave table.  This means we have to be able to output all 256 values for a single cycle of the wave and then we have to do that 440 times a second to play the wave at 440Hz.  This means we need a sample playing rate of 440 * 256 or 112,640 numbers sent out every second – i.e. 112.64 kHz. That means playing one sample every 1/112640 seconds or approx once every 8 microseconds.

For an Arduino running at 16MHz, configuring a timer to operate at that kind of timescale is definitely feasible.  But already we can see that if we only output every other value in the table, we only need to push out 128 samples at 440Hz, so then only need a sample rate of around 56kHz (one every 16uS), so we can start to appreciate how the number of samples and the rate at which they are read from the table changes things.

When choosing the configuration to use for PWM audio though, we tend to think about things the other way round.  We need to:

  • Select a useful basic PWM rate.
  • Select a useful sample playback rate.
  • Select an appropriately sized wavetable.

PWM Rates

The most useful PWM rates are those that tend to be specific ratios of the main system frequency.  The timers include settings for defining the “prescaler” which allows us to scale how the timer is keyed from the main clock.  “No prescaler” (or “prescaler = 1”) means the timer runs at the system clock speed, which is 16MHz for the Arduino Uno.  Having a “prescaler” of 8, means the timer runs at system/8 or 16MHz/8 = 2MHz.

This is the speed that the timer will count.  So the basic PWM frequency will depend on this, but also the TOP value the timer needs to count to.  Here are some examples:

  • No prescaler, TOP=255 – the base PWM frequency = 16MHz / 256 = 62.5kHz
  • Prescaler=8, TOP=255 – the base PWM frequency = (16MHz / 8) / 256 = 7.8125kHz
  • No prescaler, TOP=1023 – the base PWM frequency = 16MHz / 1024 = 15.625kHz

And so on.

But this isn’t the whole picture.  In Fast PWM mode, the above frequencies are correct.  However in either of the phase correct PWM modes, the counter has to count up and down, so the actual PWM frequency is half as much again.

So for no prescaler, TOP=255, the base PWM frequency for phase correct PWM is actually (16MHz / 256) / 2 = 31.25kHz.

In the above three examples, the PWM resolution is 256, 256 and 1024 respectively.  This means that in the first two cases the compare values will be in the range 0 to 255 to give the full 0 to 5V output.  For the last case, the full range is actually 0 to 1023 to get the full 0V to 5V, so there is a higher resolution and the potential for a more precise output.

One other consideration – the PWM signal is fundamentally an underlying pulse/square wave signal at the PWM frequency.  This means that there will be harmonics in the output at that frequency.  Running 62.5kHz or even 31.25kHz means you are hardly likely to be able to notice them (although there is the possibility of aliasing issues, but that is out of scope for this discussion).  But a PWM frequency of 7.8kHz, or half of that in phase correct mode, is very definitely in the audible spectrum and will be noticed as a high pitched overtone.

This means that the PWM base frequency needs to be chosen carefully and some kind of output filtering is highly advantageous.

Sample Rate

I’ve already touched on some of the issues around sample rate – we saw that we need a sample rate of 112kHz to output all 256 values from a wavetable at 440Hz.  The most basic consideration is to ensure a sample rate that allows us to output the wavetable at a rate of at least twice the highest audio frequency you want to produce, but we have to take into account the number of samples too.

The frequency at which a wavetable is read and outputted doesn’t have to be the same as the sample rate.   As already discussed, if we skip every other sample, we can instantly double the output frequency which corresponds to running an octave higher than before.

Similarly if we output each value twice,  then we automatically half the frequency of the audio signal being produced so it drops an octave.

It is a common technique to have a fixed sample rate, and a fixed wavetable size, but to vary the increment for the index into that table to adjust playback for different frequencies.  This would usually allow for both fractional updates, resulting in playing samples more than once, for slower frequencies and skipping entries too for the higher frequencies.

For more on the basics of how this works, see the discussion about “direct digital synthesis” in Arduino R2R Digital Audio – Part 3.  Here are some more detailed references:

Choosing PWM and Sample Rates

It is quite possible to use a single timer to generate the PWM signal using a basic frequency as calculated above, and configure an interrupt to fire on the timer overflow (i.e. when it gets to the TOP) to generate the next sample to be played.  In fact this makes great use of the resources available to you, but there are a couple of constraints:

  • If you want a known resolution (say 8-bits), then you are limited to sample frequencies that can be specified as multiples of your system clock – i.e. that can be set by the pre-scaler, giving a TOP counter value of 255.
  • However if you want “calculation friendly” sample rates, which for microcontrollers generally means powers of two to gain the maximum performance, then rates such as 16384 or 32768 Hz are best.  But these can only be obtained by using combinations of pre-scaler settings and different counter TOP values.  This means your sample resolution isn’t an exact figure anymore.

We already have an example of the first – we’ve seen how to get a frequency of 31.25kHz by using a 0-255 resolution PWM “phase correct” configuration.  But to work out the playback index to play out a wavetable at an accurate audio frequency, we now need to perform calculations involving 31.25kHz. In general for performance reasons it would probably be necessary to pre-calculate some of the numbers required for different frequencies associated with pitches of interest.

For example, going back to our “concert A” at 440Hz, in order to index the table at the correct speed, assuming a sample rate of 31.25kHz, we need to do the following calculation:

  • Required frequency of sample outputs = required audio frequency * wavetable size
  • So required period of sample outputs = 1/(required audio frequency * wavetable size)
  • So required increment in the wavetable on every “tick” at the sample rate = sample period / required period of sample outputs

So, plugging in the numbers:

  • Required frequency of sample outputs = 440 * 256 = 112.64 kHz
  • Period of sample output = 1/112640 = 8.878uS
  • Period of each “tick” at our sample rate = 1/31250 = 32uS
  • Increment step for each “tick” = 32 / 8.878 = 3.604

To summarise the calculation:

Increment step = (1/Sample Rate) / (1 / (freq * wavetable size))

Or simplifying:

Increment step = Required Frequency * wavetable size / Sample rate

So we can pre-calculate a range of increments for different frequencies and store these in a table ready for use:

  • A4 = 440 * 256 / 31250 = 3.60448
  • C4 = 261.6 * 256 / 31250 = 2.1430272
  • C5 = 523.25 * 256 / 31250 = 4.286464

… and so on.  Notice how we would like to retain the fractional parts of these increments to maintain accuracy.  I’ll talk a bit more about how we can do that later.

If we go the other way, and start with a more calculating friendly frequency, here is an example of how we can configure PWM operation for 32768Hz (which is 2 to the power 15):

  • Set no prescaler, so the timer counts at 16MHz.
  • To produce our desired frequency of 32768Hz, we need the timer to reset at a specific numeric value, which can be calculated as follows: 16MHz / 32768 = 488.
  • So for Fast PWM mode, set the counter TOP value to 488 (actually it is one less, see below).
  • Or for one of the phase correct PWM modes, set the counter TOP value to 488 / 2 (as it has to count up then back down) = 244.

Actually, from the ATmega328 datasheet (section 19.9.3), the frequency in Fast PWM mode is defined by the following equation (N = pre-scaler, which is 1 for “no pre-scaler”):

FreqPWM = Freq clock / (N . (1 + TOP))

So turning this around, we can see that:

TOP = Freq clock / (N * FreqPWM) – 1

So in this case, TOP = 16MHz / (1 * 32768) – 1 = 487.

The equivalent for phase correct PWM (section 19.9.4 or 19.9.5) is:

FreqPWM = Freq clock / (2 . N . TOP)

So:

TOP = Freq clock / (2 * N * FreqPWM)

Or TOP = 16 MHz / (2 * 1 * 32768) = 244.

But you can notice we now no longer have an exact 8-bit resolution.

We either go with 244 in phase correct mode and “lose” some of the resolution – it would made sense to generate a waveform with values in the range 0 to 244 only. If it goes over 244 up to the full 8-bit 255, there will be clipping of the output without any scaling back into range.

Or we have an “almost 9-bits” resolution in fast PWM mode.  This would either require samples that are larger than 8-bits – so with 16-bits being the next data size up from 8-bits in microcontrollers, that doubles the storage requirement for the wave table instantly; or we accept 8-bit resolution and will only ever be able to output a signal between 0V and 255/488 of the maximum which for 5V is around 2.6V.

The only way around this would be to use two different timers, one to generate the PWM signal itself and one to trigger an interrupt to service the required sample rate.  This is quite possible on the Arduino Uno and would be fine if you aren’t needing the timers for anything else. It also means you can use your sample-rate generating timer in a simpler non-PWM counter mode (e.g. “CTC”).

In general terms, it is better to have the PWM rate higher than the required sample rate anyway – it generates a much cleaner waveform when a filter is applied for example.  So if we are sticking with a single timer, then one trick is to set the PWM to be twice the required sample rate and then only output a sample on every other interrupt.

Bias in Signals

In all of the discussion so far, it has been assumed that output values are always in the range 0 to the PWM resolution – e.g. 255 for 8-bit signals.  However we are talking about audio waveforms that have positive and negative values normally.  We generally have two choices here:

  • Treat “maximum / 2” as the “zero point” – so for a 0 to 255 signal, 128 is “reference zero” and anything above 128 is the positive cycle of the wave and anything below is the negative cycle.
  • Use signed values – so for an 8-bit signal that means -128 to 127 – and add the bias when it comes to actually outputting the value to the PWM hardware – in this case “add 128”.

As the PWM signal is alternating between 0V and 5V in various fractions, the actual audio output is always “positive DC biased” anyway and ideally should be sent through a capacitor to remove the DC bias and return it to a true +/- signal.

Maintaining Accuracy

As may be apparent by now, just keeping to integer sequences between 0 and 255 doesn’t give you much scope for accuracy of output, especially when it comes to calculating the increment index into our wavetable, so we often see synthesis code using what is called “fixed point arithmetic”.  I won’t go into the details particularly here (there is some discussion here), but in general it means working at a higher multiple of your basic value.

A common example is using a 16-bit value with the top 8-bits being the 8-bit value you are interested in, and the bottom 8-bits effectively being “8-bits worth of decimal point” for your calculations.  Basically when working in 8.8 fixed point arithmetic like this, everything is 256 times bigger than you will eventually need it to be, but it allows you to maintain accuracy in calculations.

You just need to remember that when the time comes to use your final value, you have to divide by 256 to return the 8.8 value back to a normal 8-bit value.  Thankfully this is a relatively computationally friendly operation, being a simple bit shift right by 8 bits:

Final 8-bit value = 8.8 fixed point value >> 8

This is particularly useful for the accumulator – the value used for indexing into the wave table. Often it will be calculated using 8.8 fixed point arithmetic and then the top 8-bit are used as an index into a 256-value wavetable when it comes to calculating the next sample to output.

The Code

In this example, I’ve gone for the following:

  • Using a sample and PWM frequency of 32768Hz.
  • Using Timer 1 in Fast PWM mode, no pre-scaler, using ICR1 as the “TOP” value set to 487.
  • Using the Timer 1 overflow interrupt to trigger the “sample output” routine.
  • Using OCR1A as the compare value, so using OC1A is the PWM output which is pin 9 on the Uno.
  • Using a 8-bit wavetable of 256 values, pre-calculated in the setup() routine, with values in the range 0 to 255.
  • Using a potentiometer on A0 to choose a frequency from 220 (pot reads 0) to 1243 (pot reads 1023).

This is largely the type of digital synthesis I used in Arduino R2R Digital Audio – Part 3 and uses the timer and PWM configuration that I believe is used by the Mozzi “standard plus” mode.

There is another example, using Timer 2 and Pin 3 in Arduino PWM Sound Output – Part 2.

This has the following properties:

  • Sample rate of 32768Hz.
  • PWM peak to peak of 0 to 488.
  • DC offset bias of 244.
  • Wavetable values in the range 0 to 255.

There are four possible waveforms to choose from using the at the top of the file:

  • 0 = sin wave
  • 1 = sawtooth
  • 2 = triangle
  • 3 = square

Although it is a little inefficient creating a square wave like this, as you could just output it directly on the IO pin using the Arduino tone() function, but it is there for completeness.

For testing purposes, there are three “test outputs” produced by the code:

  1. On startup the wavetable is printed to the serial port in a manner suitable for use with the Arduino Serial Plotter.
  2. The PWM is allowed to run for 5 seconds at 25% duty cycle before the waveform generation starts, so the core PWM frequency, etc, can be checked.
  3. The waveform is played at 440Hz (“concert A”) for a further five seconds for testing and checking the output frequency either by measurement or by “ear”.

Then it switches over to outputting a waveform based on a frequency derived from the potentiometer.

Here you can see the test 25% PWM output at 32768Hz (pre-filter) and then the 440Hz test tone (post-filter).  Note, my cheap digital oscilloscope isn’t very good at deriving the frequency of a PWM filtered signal, in fact it doesn’t really like it at all to be honest, but you can see the general shape of the sine wave at 440Hz.  Take it from me that it sounds “in tune” with my tuning fork!

Find it on GitHub here.

Closing Thoughts

There is a lot here, but to be honest, I wanted to get into the “nitty gritty” to really understand it myself.

If you want to read more about it, or perhaps would like a more “practiced hand” explaining it, I can recommend the following:

  • “Arduino for Musicians” (Brent Edstrom) – Chapter 9 – “Audio output and sound synthesis”.
  • “Auduino Music and Audio Projects” (Mike Cook) – Chapters 10 to 12 – “The Anatomy of a Sound”, “Square Waves”, “Other Wave Shapes”.

And of course any of the tutorial articles linked to at the top of this post.

Kevin

One thought on “Arduino PWM Sound Output

Leave a comment