Quantcast
Viewing all articles
Browse latest Browse all 328

JeeLabs: From PWM to voltage

The Arduino library has always had an “analogWrite()” function, even though the ATmega doesn’t have any way to generate a varying voltage. So why the name?

Well, what most microcontrollers can do is generate a pulse-width modulated signal, also known as PWM. That’s just a fancy way of saying that the microcontroller periodically generates a pulse, of which the width can be varied under software control.

Here’s a diagram from the Arduino PWM tutorial page:

Image may be NSFW.
Clik here to view.
pwm

It’s very easy to generate an approximate voltage between 0 and VCC by simply adding a resistor and capacitor to act as low-pass filter:

Image may be NSFW.
Clik here to view.
CRLowPass1

That image came from an excellent article by Scott Daniels about this same topic on the ProvideYourOwn.com website. Check it out for much more background information.

So how do these two little components turn PWM into a voltage?

To see what’s going on, we can tie the resistor to a PWM pin, call “analogWrite(N,128)” to set a 50% duty cycle, i.e. halfway, and then watch the result on the oscilloscope:

Image may be NSFW.
Clik here to view.
SCR79

(the above was generated with a 10 kΩ resistor and 0.1 µF capacitor – see this calculator)

What you’d want to see, is a 1.65 V output. As you can see, the real thing is indeed centered around that value, but with a lot of “ripple” (yellow = PWM, blue = Vout).

The reason for this is that the PWM is charging and discharging the capacitor. The average value will be the ratio of on-to-off time against the digital voltage, i.e. 3.3V, so a 50% duty cycle will lead to half VCC, i.e. 1.65V. But it’s still charging & discharging.

Can we get a cleaner signal out, without that up-and-down wavering? Yes: by increasing the repetition rate, i.e. the PWM frequency (while keeping the on-off ratio the same). There’s a page on the Arduino site about this. Here’s the result, with a 64x higher rate:

Image may be NSFW.
Clik here to view.
SCR80

The purple line is a third probe on the same output signal, but set to AC coupling and much higher sensitivity, to show that the ripple is still there, but much much lower.

Now I can get to the point of this post: my intention was to see if I could generate a clean sawtooth wave, to use as supply voltage (after amplification) for testing circuits at various VCC levels – as used a few times in recent posts. Here’s the code I came up with:

void setup () {}

void loop () {
  for (int i = 0; i < 256; ++i) {
    analogWrite(5, i);
    delay(10);
  }
}

The result is this:

Image may be NSFW.
Clik here to view.
SCR81

And now there’s indeed a sawtooth, but as you can see, sudden changes like the down edge take some time to pass through the RC filter, somewhat messing up the signal.

No problem, if we increase the delay time in the above loop by a factor of 50:

Image may be NSFW.
Clik here to view.
SCR84

Voilá – things are fine now. A pretty smooth voltage ramp from 0 to VCC every 2 seconds, all from a single digital output pin on the ATmega – we’ve created a DAC!


Viewing all articles
Browse latest Browse all 328

Trending Articles