Digital to Analogue Converting (DAC) is an extremely handy tool for some projects, and is always a good thing to keep on the back on your mind. Sadly the PIC 18F range of micro's do not have DAC, however, there are many DAC chips out there ready to interface with to get the job done. But why should you when there's a much cheaper and easy solution.
Pulse Width Modulation (PWM) is covered in other areas on this site, and I'm about to show you how you can use PWM to perform DAC's with excellent results. There are many concepts out there for DAC, most people will recommend you use a Resistor/Capacitor Low Pass Filter to "average out" the PWM signal to a constant DC potential. The problem with *most* of these designs is noise. Consider the most popular 1K & 4.7uF combination running a 50% duty cycle at many Khz;
The RC Filter, if doing its job correctly, should be demodulating the PWM signal to provide a constant DC potential. But is it?? It got the better of me one day, so I borrowed a CRO from work and made some real life tests, the results were fairly staggering... The image below is the typical "filtered" output from the above circuit with a 50% duty cycle;
As you can see, the error rate is about +/- 500mV. Yes it is very filtered compared to a raw PWM signal, but no this is not acceptable by my books. I needed a "high'ish" accuracy DAC for a project I was working on for a friend, and with no DAC chips available, I began researching how to make a filter circuit specifically for this task.
For superior performance, the low-pass filter was designed as a twopole, providing an attenuation of 40 db / decade past its cut-off frequency. The higher PWM frequencies are filtered out by the low-pass filter, thereby reducing the noise in the DAC output. I could ramble on all day with the findings, or simply provide you, the end user, a method that simply works, so lets get started..
Want to see real life results, look no further as this is a video of the CRO in action. Note the Yellow channel is the raw PWM signal, and the Blue channel is the filtered DAC output;
There are other aspects to take into account, such as the time it takes for the signal to rise from 0% duty, to 100% instantly. Here's a real life result of my circuit (the PWM signal is changing between 0% and 100% instantly);
Although the above makes the changes appear instant, the time scale is set to 400mS, rather slow for an accurate reading, so here is a closer look at the result with a 400uS time scale (note that the Yellow channel is the raw PWM signal, and the Blue channel is the filtered DAC output);
As you can see above, it takes 1200uS (1.2mS) to ramp from 0V to 5V. This is a fall back of the RC circuit as the capacitive time constant needs to be taken into account. Considering this is worst case scenario (0% to 100% duty), it's extremely quick and completely within my realm of usability.
Finally, I want to examine any noise on the output DAC signal. Almost no circuit can escape it, its inherent of any design involving switching/fast signals and is incredibly hard to eliminate at times.
Square waves, such as PWM signals, are by far the noisiest wave forms to deal with. They are made up from millions of sinusoidal wave forms and are inherent of "ringing". This is noise found at the end of rise/fall, where instead of being a flush 90 degree bend, the signal rings for a short moment of time. This ringing operates at a much higher frequency then what my RC circuit is designed to filter, and below you can see the signal in a snap shot from the CRO;
To give you and idea of how minimal the noise is, the above time scale is 100nS (0.0000001 seconds per square). Either side of the signal is perfectly flush and noise free (unlike the original design at the top of the page). With this in mind, I'm more then happy to confidently use this circuit for all of my everyday type DAC requirements.
Here's some source code that switches between two different tests for assessing the circuit design;
Device = 18F252Clock = 20Include "PWM2.bas" // Include the PWM library// * note, this can be downloaded// from www.digital-diy.netDim Cnt asWord// Couple of variables for useDim X asByte// later in the program.// start of main program...PWM.SetFreq(36000) // Setup the default PWM Frequency.PWM.Start1 // Initialise CCP1.PWM.SetDuty1percent(50) // The initial duty %WhileTrue// Create an infinite loop.For X = 1 to 5 // First test, repeated 5 times.For Cnt = 0 To 555 // These two 'For' loops cycle PWM.SetDuty1(Cnt) // through the 'SetDuty1' operativeDelaymS(5) // which depending on the PWM Next// frequency, can be up to 10bitFor Cnt = 555 To 0 step -1 // resolution. PWM.SetDuty1(Cnt) //DelaymS(5) //Next//Next//For X = 1 to 5 // Second test, repeated 5 times. PWM.SetDuty1Percent(0) // Instantly change to 0% duty.DelaymS(2000) // Wait for 2 seconds. PWM.SetDuty1Percent(100) // Instantly change to 100% duty.DelaymS(2000) // Wait for 2 seconds.NextWend// Loop forever.
Two important concepts here;
Duty can be defined from 0% to 100% via the SetDuty1Percent command,
The duty cycle can also be defined with SetDuty1, a 10Bit register whose maximum resolution is dependent on the frequency of the PWM cycle and the clock speed (20Mhz in this case) selected for the micro controller.
As setting a percentage only allows 101 steps of resolution (0-100), I prefer to use the SetDuty1 command for anything requiring accuracy.
To calculate the number of degrees of resolution for any specific PWM frequency/Clock speed, download the PWM Steps Calculator. Once done, simply enter in your desired clock speed and the table of data to the right will populate with every possible frequency combination and list the number of steps for each. It has a couple of other functions, but that is covered in the Swordfish PWM article. Here's an example for our use of the program;
Note it says 556 steps @ 35.97Khz with a 20Mhz oscillator, that means you can control the duty cycle from 0 to 555 via SetDuty1Percent.
For optimal results with this circuit, use a frequency as close to 36Khz as possible (within a few Hz). There are several design considerations involved in the selection of the cut-off frequency of the low-pass filter. Primarily, the filter cut-off frequency must be much lower than the PWM frequency to reduce the noise generated by PWM switching. Further more, you shouldn't have any issues with 36Khz in any design as it is well out of the audible frequency range.
Final Note: Single-supply operational amplifiers with low offset voltage and input bias current specifications are preferred for driving loads. For cost-effective solutions, however, the operational amplifier can be eliminated, with the precaution that the load is at least 20 times the combined value of the filter resistors R1 + R2 (in this case, 20*2K = 20K).
Gamers ought to know link:http://www.buyazugagold.com [azuga gold[/u...]
Graham, Thanks for fixing the spacing on the array. This is how i...
Thanks Graham, It is a problem with Flowcode because the demo wa...
Looks like you've pretty much solved every minor issue that was enc...
The low-cost servo does have one other feature. The origina...
I am not familiar with flowcode, though did you try powering the bo...
Hello there, I am still trying to get the LCD to work but I am pro...
Hi Hop, I've finally got some time this weekend to delve into the ...