I'm trying to think of the best way to convert a PWM signal into an analog signal. I could use an RC filter, but that requires a very high PWM frequency to create a faithful reproduction of the signal. In my case I'm dealing with audio frequencies for the analog signal - up to 20 kHz. So, what other options are there?
The simple answer is that you can't. There are several things going against you:
would be that for good audio quality you'd need to be very precise in your PWM generation. This is fairly difficult, as your master clock frequency (the freq that the logic used to generate the PWM from) would have to be around 100 MHz just to get the equivalent of an 11-Bit DAC. There are ways to generate PWM that good without that, but then you'd be starting with an analog signal and thus wouldn't have this problem.
as noted you would need a super steep rolloff of a filter. Just to match your 11-bit DAC equivalent you'd need something like 60 dB/octave-- which is unreasonable even for the pro's. There is a lot of difficultly in doing this kind of filter which is why everyone went to Delta-Sigma DAC's for their audio, which require about a 6 db/octave filter.
If your filter is not 60 db/octave then you'll need the PWM frequency to be super high. If you have 60 db/octave then you could have a PWM freq of 40KHz. At 54 db/octave then maybe 80 KHz will work. 48 db/octave = 160 KHz. Etc. Very quickly you get into the high MHz range-- and then your master clock frequency would have to be into the GHz.
All is not lost, however. Do you really need to filter out the high frequency stuff? In many applications (not all) you can either not filter it or use a simple RC filter at 1-5 MHz. There will still be high frequency stuff getting though but either the speaker or your ear will filter it all out. But the audio will still sound bad. AM Radio on a bad day quality. That's just the way it is.
Update: My numbers for #3, above, are somewhat wrong. But before I get to that, let me explain where I got all the numbers from.
Let's say that you are generating the PWM using digital logic (FPGA, Microcontroller, etc.). And then let's say that your audio sample rate and thus your PWM frequency is 48 KHz. And you want 8-bit resolution. That means that your master clock frequency should be 12.288 MHz. I calculated that this way: Master_Clk_Freq = Sample_Rate * 2^n_bits. Doing that again for an 11 bit resolution is 98.304 MHz.
The theoretical best noise level of an ideal DAC is about -6dB/Bit. So a 24-bit DAC has no better than -144 db noise. (Note: I'm playing a little loose with the terms here, lumping SNR, THD+N, and dynamic range all together.) Of course, no real 24-bit DAC can do this, but we're talking theoretical here. What this means is that an 11-bit DAC has about a -66 db noise level, so there is little point in making a filter that works better than this. AM Radio has approximately 60-ish dB signal to noise ratio, for comparison.
Ok, here's where I royally messed up the numbers. Assume that the PWM Rate = 48 KHz, and filter Cutoff=24 KHz (to make the math easy). With a -60dB/Oct filter we'll be -63dB @ 48KHz. If our filter were changed to -54dB/Oct then we'd be -57dB @ 48 KHz and -62.4dB @ 50.4KHz. What this means is that by changing our filter from -60db/oct -54db/oct we would have to change the PWM rate from 48 KHz to 50.4KHz to achieve the same filter blocking performance. Not a doubling of PWM frequency as I mentioned before. In the same way, if the filter were changed to -18dB/Oct (which is a manageable design) then the PWM frequency would have to be 104 KHz to still have -63dB filter attenuation at the PWM frequency. I calculated this by making a small spreadsheet and playing with the numbers.
The RC Low-pass filter would be the natural solution, but you can also use a microcontroller to measure the duty cycle and use that value to control a DAC. To measure duty cycle you need a timer with input-capture capability. The higher your timer clock, the more accurate your measurement. If the microcontroller doesn't have on on-chip DAC you can use an external one.
I'm integrating the PWM ramp up, capturing the voltage with a sample and hold circuit and then resetting the ramp. This seems to get a relatively faithful representation of the signal, but it still has some issues, like PWM noise on the peaks, and it's slightly nonlinear. But, it does work fairly well, and it allows me to use a 100kHz PWM signal.
Simulate it here.
One issue not yet mentioned is knowing how the PWM signal was generated, in particular whether the leading edge, center, or trailing edge occurs at a uniform rate, and whether the PWM signal represents uniformly-spaced samples, or whether the PWM signal represents the samples taken at uniform intervals, or whether they represent the value of the input signal at the time of the rising edge, falling edge, or both. Knowing how a PWM is generated, it should be possible to do a good job of recovering the original signal (as well as it could be recovered from a signal sampled at the PWM rate). Attempting to reconstruct a signal which was sampled via some means other than what was expected is apt to cause phase distortion.