Using PWM for Digital to analog output

Wrenow

Senior Member
OK, I have seen several threads about using PWM for DA output, but have been pondering. A couple of questions have popped into my mind, and haven't yet seen answers.

1) If you are simulating DA with PWM and a capacitor(s), what range of capacitor(s) do you want?

2) If you are reading the faux analog signal with a microprocessor, is this going to give strange fluctuations/artifacts, etc. on the reading?

The reason I ask. I have considered replacing the 5K pots in a hobby RC transmitter with a Picaxe circuit to automate/improve some things (basically think of adding a mixer or end-point adjustment or other feature to a radio not already so equipped. Luckily the TX I am hacking is based on a 5v board system, as it uses a couple of PICs already.

Any thoughts?

Cheers,

Wreno
 

moxhamj

New Member
The formulas for caps and resistors are a bit complicated but I find the simplest solution is to look up the timing diagram for a monostable 555 eg http://www.national.com/ds/LM/LM555.pdf and scroll down to page 7. The 555 goes between 1/3 and 2/3 of the supply voltage so the values are roughly in the right ballpark. So if you want a filter with a 1 second time constant then choose 10uF and 100K or 100uF and 10k.

It depends on how quickly you want to change the value and how much you want to smooth it. If you make the RC time constant too small it won't work as a filter any more. If it is too large then it takes too long to readjust.

Another trick is to get it working at values you can see change - eg over 10 seconds and then say you wanted it working over 0.1 seconds, divide the capacitor value by 100.

If it is radio control then a time constant of maybe 1/10th of a second would be ballpark.
 

Wrenow

Senior Member
Hmmm... Looking at the chart, and considering the radio updates the output every 20ms, it looks like a pretty small cap is needed - maybe in the.01 uF - .001 uF range.

Guess I need to start pluggin' and playin' (after I bring myself up-to-date on the PWM command).

Thanks,

Wreno
 

moxhamj

New Member
What are you trying to do? The update frequency on the radio may not be the limiting factor - if it is radio control then the speed is really dictated by the fastest reaction time (which needs to be pretty fast for helicopters).

One simple test is to set up a 10 second time constant and then send a pwm with a value of 0 till the output is definitely at 0 and then send a value of 255 and watch the voltage rise on a multimeter. It will take forever to completely stabilise as there is an exponential rise but once it is say to 98% of the value for 255 then you know the time constant for 98%. Then say you want a speed with 20 updates a second (faster than human reaction times) and it is 10 seconds then divide the cap by 200.

Even at 20 filtered changes from 0 to 255 per second a second picaxe sampling this at 1000 samples a second could still get 50 stable samples for every change.

Obviously it helps to have the PMW frequency at least 10x greater than the sample change frequency but PWM runs fast anyway.


Then there is the issue of output impendence and 10k is probably a good value (certainly 10M isn't) so if you went for say 10ms and 10k then that suggests 1uF. And to test at 10 seconds than that is 1000 times longer so test with a 1000uF and 10k and see what happens when values change.

Or use a CRO if you have one.
 
Last edited:

BCJKiwi

Senior Member
Have been interested in this concept for some time as a simple way to transfer a wide range of values between PICAXES on a single wire.

Have just carried out some tests on a 28X1 at 8Mhz with
Code:
pwmout 2,249,512
Main: 
ReadADC 0,b0     ' read ambient light intensity
let w1=b0*4      ' *4 to suit pwm Duty of 249
change output Duty.
pwmduty 2,w1
goto main
This is as slow a PWM as you can get with standard commands and up to 16MHz clock.
Set up with a 1uF electrolytic cap and variable resistors.
Found that at anything below around 2k5R there is virtually no smoothing happening but from there up to around 25k the ripple reduces from around .15v to .03 volt. Even at 25k the CRO trace is moving up and down constantly as the LDR supplying the readadc input is drifting slightly. The CRO voltage tracks the DMM voltage showing at the pwm output.

pwm out--------/\/\/\/\/\------+---| |----- 0V

ReadADc connected to '+'

I would have thought if the PWM frequency was as high as possible for the clock speed while keeping the pwmduty a byte value (to make setting the duty from a variable simpler) then the smooting task would be minimised and response maximised. e.g with period of 62, duty is always < 255 for any clock speed.

So changed code to pwmout 2,62,b0 and reduced Capacitance to 0.5uF. Found that the ripple is barely detectable above around 4K and the change is noticeably more responsive.
Also tested 2uF and found with around 2k the output was the same as with .5uF and 4K

So it seems the higher frequency is smoother and more responsive and has a bit of leeway in the setup.

Also if using the X1 parts, then there is the option of pwmduty which only changes the duty and does not reset the internal timer as does the full period,duty form of the command. PWMDUTY is still undocumented but was advised by Technical recently and does work fine.

"The problem with constantly re-issuing pwmout commands is that each pwmout command resets the internal timer, which effectively disrupts the current cycle. If you do this very often you may notice some flicker.

One way to overcome this on X1 parts is to use the new 'pwmduty pin,value' command. This pokes the 'duty' register with the new value without affecting the timer, and so can help in this type of situation. Naturally you still have to use pwmout once to start the function.

'pwmduty' command is at beta at the moment, but you can try it out if you have the latest version editor (5.1.5)
__________________
PICAXE Technical Support "

PWMDUTY is noted in the changes file for programmer V5.1.7
 
Last edited:

Wrenow

Senior Member
Okie Dokie. What I am trying to do is simulate the center pole of a 5k pot with the outer legs being 0 and 5v. The response should be as quick as possible, of course.

So, it is not a case of just putting a capacitor between the given pin and 0v. Interestingly, in the manual, it says for the 08M the command to use is PWM rather than PWMOUT, but it looks less promising.

Cheers,

Wreno
 

BCJKiwi

Senior Member
The 08 has pwm only, the 08M has pwmout.

Without the surrounding circuit for the existing pot this is to emulate, it's a little difficult to sort out how to suggest a working alternative.
 

BCJKiwi

Senior Member
Wrenow,

The pwmout is generating the output that would otherwise be coming from the pot wiper but it is a square wave. The Resistor and Capacitor combo are simply smoothing that to an analog voltage that responds rapidly to the changes of the input.
So the question is, is this relevant to the circuits you have ?

The application I have considered is different - its a way of passing multiple signals from one PICAXE to another.
For example, if you have a number of different inputs to one chip - say switches, infrain from a remote, etc, then these could all be passed over a single pwmout ---> ADC connection between two PICAXEs by allocating different pwm output levels to each different input, or combination of inputs, and decoding them in the second PICAXE with Readadc.
 

wapo54001

Senior Member
Wilf_NV showed me how to do this with great accuracy using an integrator circuit and avoiding pwm altogether. His description, including a URL to a circuit and a code sample are in the archive. Do a search to find the thread "driving low impedance with pwm." If the URL doesn't work anymore, I can upload a schematic, I think I still have it.

Uploaded 08M schematic and text file of software
 
Last edited:

BCJKiwi

Senior Member
Low pass RC filter

Just to follow up on my previous posts re using an RC filter for this task.

Have run a few more tests and found the circuit;
Code:
                                2K7
    28x1 pwmout/pwmduty  ------/\/\/\-----+------  28x1 ReadADC
                                          |
                                  0.25uF  =
                                          |
                                         0 V
The simple test code is as follows;
Code:
#PICAXE 28X1
setfreq em16
#terminal 19200
'
INIT:
' setup pwm ( for pwmduty mode of operation on 28X1
pwmout 2,62,125 ' establish pwm pin, frequency
settimer 65330
 
Main:
for w4=0 to 100
let w0=timer  'seed random function
random w0   'randomise
pwmduty 2,b0  'limit output to readadc range of 0 to 255
pause 25   '-1 +1 0.25uF, 2k7 low pass filter
ReadADC 1,b2  'read smoothed pwm as analogue
next
sertxd (#b0," ",#b2,cr,lf)
GOTO MAIN
The pause 25 is at 16MHz clock so represents only around 6ms delay. Without some delay between PWMDuty and ReadADC, the level did not have time to shift before being read. once this pause was reduced below 20 occasional errors of -2 were observed. Depending on the working application, there may be no need to add this delay as sufficient other activity may effectively introduce this delay.

Larger Capacitor values lengthened the response whereas R values made very little difference (once above approx 2K4).
The response error with larger capacitor values were most noticeable when making a large change from say 255 to 0 whereas a progressive change was always more stable.
The error rate observed with the above setup and test code ( +-1) was no worse than what was observed with a pwmout value that did not change.
 
Last edited:

moxhamj

New Member
BCJKiwi, the filters would still be needed for your application. You could experiment with the low pass frequency - it might be possible to get it quite fast so you are even sampling a hundred times a second or more. The experiment to do would be to determine the repeatability of signals. I'm sure you could get 16 different voltages consistently and you might get up to 256 with readadc10.

PWM is great for simulating pots that have one end on 5V, one end on 0V and the wiper giving a variable output. Where it won't work is where the pot has the wiper and one end connected together, and the sampling circuit is measuring resistance, not voltage. That is where digital pots would be the solution. But all the radio control things I have pulled to bits seem to sample voltage.
 

Wrenow

Senior Member
My application, by the way, is just what you describe - simulating a 5k or 10k (depending on radio) linear pot with one end on 5vm one end on 0v, and the wiper giving a variable output. When I have the radio open, next time, I will do a little 'sperimenting.

Luckily for those of us in the US, you can pick up a Vex Robotics transmitter (75Mhz, US sruface frequencies) for dirt cheap right now - $29.95 + $7 shipping from All Electronics (sometimes cheaper on Ebay). Great for parts and wexperiments, though the enclosed transmitter is an RF stage only, not a decoder. So, If I let the magic smoke out, it is not like I have blown a $300 radio.

Cheers,

Wreno
 

BCJKiwi

Senior Member
@ the Dr.

This test code does measure fast and proves the repeatability - that's what it was all about.
Ran for extended periods of time and checked the differences between the pwm sent, and the adc received. There was only a +-1 error which is the same as you get without changing the pwmout.

The actual functional read rate of the output change to an accurate read is only the pause of 6 ms plus the readadc command - i.e. around 150 times per sec so you could get up to 100 values but certainly 50.

I do not understand your comment,
"the filters would still be needed for your application".
These tests were done with only the RC filter shown in the diagram above, PWM and ADC on the same chip.

I'm not sure that ReadADC10 would help much in this instance as the issues seem to centre around 2 factors;
How fast the change in pwm can be tracked, and,
How fast/effectively the square wave can be flattend into a near analogue.
Both these depend on the RC so I suspect if you used ReadADC10 you would just see correspondingly larger fluctuations in the value returned.
 
Last edited:
Top