Making Better Noises With Dual PWM


Although it’s technically possible to get 16 bits of resolution on a ATMega328, most implementations of PWM on everyone’s favorite ‘mega – including just about every Arduino sketch – are limited to 8 bit PWM. This means the pins can only output 256 different values, so if you’re playing around with music made on an Arduino don’t expect very high fidelity.

There is a clever way around this: use two PWMs, and use one pin for high bytes and another for low bytes. That’s what Open Music Labs did when working on a synthesizer project that needed very high quality audio.

The basic idea behind the build is that PWM pins can be used to create audio frequencies. Using two PWM pins and adding them together means it’s possible to add extra bits of resolution. This requires using different values of resistors on each pin. For example, using the same value of resistors on two PWM pins increases the resolution by one bit. Two pins with a resistor value ratio of 1:4 increases the resolution by four bits, and so on.

There’s a great tutorial for setting up these higher resolution, dual PWM outputs on an ATMega or Arduino, as well as a distortion analysis for this dual PWM setup.

20 thoughts on “Making Better Noises With Dual PWM

  1. The article is very good as theory explanation.
    I’ve tried this once, going for an expansio to 12 bits. I’ve found the sound of a R2R rrsisot dac with 10bits resolution better than the 12b pwm generated.
    In then end i decided to go for a low cost audio dac with a serial interface, like the CS4344 for less than 2 eur. There are others and its easiyer to solder an 8 pin ic compared to what it take to build the dac out of more pwm channels. Its probably also cheaper.
    But, if 8bit pwm is sifficoent, theres no easier way.

  2. That’s clever but when I need custom made PWMs, I prefer to code them myself.
    It’s not difficult at all and you learn how to use Timers and Interrupts (every micro has a 16 bits timer in it today).

  3. Dont forget tha a 16bit timer used with a 20MHz clock will get you 300Hz max frequency. This leaves you bandwith inusable for audio.
    This is the advantage of having 2 8bit pwm, the each can run at higher frequency.

    1. Only if you start the timer at 0 and wait for it to fill up and overflow.

      In every micro I’ve seen you can load the timer with any value you want whenever you want. Load that 16-bit timer with 65,535 (and reload that value in your ISR) and it’ll overflow with every clock tick.

      Of course your ISR will take some time to run, but ~305 Hz is most assuredly *not* the upper frequency limit with a 20 MHz clock and 16-bit timer.

      1. If you want to have 2^16 discrete PWM steps, this means a maximum frequency of 20M/2^16. If you limit what you fill with to a number lower than 2^16, you are reducing the bits of precision. If you preload the counter with 61440, you have 4096 discrete values, and can operate up to 4.9kHz but you only get 12 bits of precision….

        305Hz *IS* the limit if you want 16 bits of dynamic range on your DAC for what Bogdan is talking about.

    1. It says in the article. The output resistance of the inverter is inconsistent, so it affects the accuracy of the 1:256 ratio. To minimieze the effect they use 3 inverters in parallel to mimimize what adds to the 3.9k

    1. This is a very neat hack! I was already pretty satisfied with the audio coming out of the Attiny85’s high speed PWM (8 bits at 250khz). I’m very interested to see how much this can be improved using this technique. I’m not too crazy about throwing an inverter IC into the mix, because I’d just as simply add a cheap DAC IC. But still very cool !

      Charles read Bogdan’s comment above regarding 16-bits, it won’t work out.

      1. Thanks, just remembered that we’re kind of NOT that fast on avr.
        Still, you can set the top value to limit it at about 11-12 bit. That will still give reasonable quality.
        For anything better – a cheap STM32F1X with 8k flash looks like a better solution with cheaper BOM and fewer external components.

Leave a Reply

Please be kind and respectful to help make the comments section excellent. (Comment Policy)

This site uses Akismet to reduce spam. Learn how your comment data is processed.