Combining multiple PWM outputs is a great way of getting lower noise floor and higher accuracy from your DAC, but there are a few things to watch out for. Here we will go into detail on how to build Dual and Triple PWM circuits, and explain the limitations of these designs. But first, here is the basic topology:
The theory behind these circuits is pretty simple: Multiple PWM outputs can create multiple audio signals. All we are doing is adding up these signals to get higher resolution. The basic circuit for implementing this is just as straightforward – a couple of resistors connected to a summing junction. We can mix the PWM outputs in any ratio we need by choosing the correct resistor values. Equal valued resistors will give equal mixing, and an increase of 1 bit to our resolution. A resistor ratio of 1:2 will make one signal 1/2 the value of the other, and give 2 extra bits of resolution. This can be taken to the limit of whatever bit depth you are generating. For example, if you have 2 – 6 bit generators, you can go as far as 1:2^6 = 1:64, and get the top 6 bits from one generator plus the bottom 6 bits from another generator, for a total of 12 bit resolution.
This all sounds wonderful, and it mostly is, but an important thing to remember is that increasing bit depth does NOT change distortion or unwanted PWM frequency interference. It only reduces the effective noise floor. For an explanation of this, see our PWM Distortion Analysis page. So, if you are mostly interested in low frequencies (ones very far away from your PWM frequency), then increasing the bit depth in this manner is extremely useful, as the distortion components become lower the further away you get from the PWM frequency.
Despite this apparent drawback, using multiple PWMs can be used to help reduce distortion in comparison to single PWMs of the same bit depth. A Single, 10 bit PWM needs to count to 1024 (2^10) before resetting, and its max frequency is therefore Fcpu/1024. By spreading these same 10 bits over 2 – 5 bit PWMs, each PWM need only count to 32 (2^5) for a max frequency of Fcpu/32, which is 32 times faster than the Single PWM method. This is a remarkable increase, but with the caveat that such high frequencies may not be practically attainable. You can only process and update your data so fast, and this usually limits reasonable PWM frequencies to the 30kHz to 80kHz range (for 16MHz processors).
The final limitation to any of these implementations, is that the mixing resistors must be matched to at least the bit depth desired. For example, if you want a 1:64 mixing ratio, the accuracy of the resistors must be at least 1/64 = 1.5% to get the full bit depth. This is readily achievable for small ratios, but by the time you get to 8 bit ratios (1:2^8 = 1:256), this accuracy becomes 1/256 = 0.4%. Although 0.01% tolerance resistors do exist, they are quite expensive and often do not hold that accuracy over time and temperature variations. Furthermore, in order to get these high resistor ratios, the absolute resistor value of one of the resistors must become larger, and the larger the value, the more difficult it is to make an accurate resistor. For this reason, getting much beyond 8 bit mixing ratios is fairly difficult. The following chart shows the accuracy needed for various resistor mixing combinations, to get the full bit depth.
As it can be seen, there are very few applications where Triple PWM topologies are practical. The high frequencies they enable are nice, but they are much too fast for any reasonable processing (a simple sine generator is about all you could accomplish). They also require extremely precise resistor matching, as R1 must match R3, which is 2^2*n times larger. Usually, the Dual 8 bit PWM is the sweet spot, especially if the data is being manipulated within an 8 bit processor.
An amazing example of this Dual PWM design was posted by Steve Woodward over at EDN. It’s a must read for any enthusiast, and we will analyse it here, as there is much to learn from it. The only thing that doesn’t make much sense in the original article, is that the author uses a 1:255 mixing ratio for 8 bits. But, we will just assume that is some sort of typo and move along. Here is the circuit:
The first thing to note, is the use of external digital switches (the 74HC14′s) to create the PWM waveforms. This is done for 2 reasons, but has a nice third side effect we will discuss later. In this implementation, the resistors are 3.9k and 1M. 1M is rather large, and larger resistors are noisier and less accurate, but the author couldn’t use a smaller value, without going to a resistor smaller than 3.9k for the other value (the ratio needs to stay fixed). The reason for this limitation, is that digital circuits have a finite output resistance. This output resistance is often handy for slew rate limitation or output short circuit protection, but in this case it adds with the output resistor values to change the effective resistance. Since the internal output resistance of the digital circuits is inconsistent, it creates a variation in our total resistor accuracy, which ruins the maximum bit depth which can be attained.
To read more about this problem, we highly recommend this TI App. Note on digital output stages, which shows exactly how much the resistance changes with current. They have different App. Notes for different voltage levels, and this one is the 5V version. The lowest, and most consistent output resistance is shown by the 74AC series (~15 ohms!), which is great for high current applications. For reference, the Arduino (ATmega) output resistance is around 40 ohms at 5V.
In this case, the author gangs up 3 of these output stages, to effectively divide this pesky resistance down by 3. The output resistance of the HC series is around 40 ohms, so this gives a total of ~13 ohms, or .3% error for the 3.9k resistor. To go to a smaller resistor would push the error rate beyond the 1/256 limit for the 8 bit ratio. Using these external stages also has the nice effect that you can power your DAC circuit from a separate power supply than the one used for your microcontroller. This means it can be quieter, and give a lower noise floor. Since the PWM output switches between power and ground, a noisy powersupply will add its noise whenever its connected. For this reason, lower PWM values will give lower noise (more time near ground than 5V), although this noise savings is generally small as the PWM noise floor is rarely below the power supply noise floor.
The Final advantage to using external digital logic, is that it gives both positive and negative values. In this case, the negative values are used to create an exact replica of the original circuit, except with an inverted signal. This inverted value is high-pass filtered, and then summed with the non-inverted signal. This means that at higher frequencies, the 2 signals will cancel out, helping to attenuate the PWM frequency. It basically adds a second pole to the low-pass filter, but is a clever way of doing so.
The last, unexplained part of this circuit, is the 1M resistor (R1) connecting the inverting and non-inverting stages. A schematic representation is shown below. This is the most ridiculous (in a good way) part of the whole DAC: it cancels out the error due to the finite output resistance (Rs) of the digital logic. Basically, this resistance error reduces the effective output voltage that the high byte contributes by a factor of Rs/3.9k (it also reduces the low byte contribution, but by a factor of Rs/1M, which is negligible). To compensate for this, an equal amount of the low byte is also subtracted out, by feeding in some of the inverted signal via R1 to the summing junction. The exact ratio of its mix is controlled by its connection at V1, which is approximately Rs/3.9k, the exact amount the high byte is being reduced by. To convince yourself of this, consider the effective addition if it were connected to the other side of Rs (none as it’s at a voltage source), or the other side of the 3.9k (full as it’s directly at the summing junction). Ultimately, this reduces the effective error resistance by the resistor mixing ratio (1/256 in this case).
All in all, this is a really creative circuit, especially given the space qualified nature of the design. And, for low frequency, and DC applications, it has a lot to offer. But, for most audio purposes, a lot of it is overkill. All of its advantages help reduce the noise floor, which is not the dominant nuisance for audio, as the distortion components will be far more noticeable on a 16 bit converter. Typical harmonic distortions are around -40dB, whereas the Arduino power supply is at -110dB (when disconnected from USB). But, on some ATmegas (AT90PWM’s for example) there are complementary outputs on the PWMs, so some of these tricks can be incorporated at no extra cost. And you never know, you might need to build a really accurate CV controller at some point, and all of this will come in handy (if you end up using external logic, you may be limited by jitter!). But, for now we recommend either Dual 8 bit PWMs or Dual 7 bit PWMS with a 3.9k resistor on the high byte, and a 1M resistor for the low byte on the 8 bit version, and 499k for the 7 bit version. These resistors should be at least 1% accuracy.