Become a subscriber (Free)

Join 29,000 other subscribers to receive subscriber sale discounts and other free resources.
:
:
Don't worry -- youre-mail address is totally secure. I promise to use it only to send you MicroZine.

Arduino Analog Output


Arduino Analog Output pins do not generate a true analog output in the sense that the microcontroller does not have a resistive diver to create the voltage (The exception is the Arduino Due). Instead it uses a digital PWM signal that can be smoothed to create an average voltage, which does result in an analog output.

arduino PWM sine generation 20Hz

The difference between a true analog output voltage and a PWM voltage is that the latter is created using varying mark to space ratio within the digital output signal. In the waveform above you can see the M:S ratio changing as the sine wave is generated.

The PWM signal is repeated at a constant frequency (the start of each PWM signal is separated from the next start pulse by the same period). Since a frequency is involved there will be some feedthrough of the fundamental frequency to the output (after smoothing).

So if you are looking for absolute accuracy you should use a dedicated DAC that does have a complete set of resistive dividers inside e.g. MCP4725. If you need a fairly good voltage then the PWM outputs are very useful.

For the standard Arduino Uno there are six analog output pins you can use. The really useful thing about these outputs is that they use internal hardware modules attached to the timers to automatically output the chosen M:S ratio without further programming. So your program only writes them once and they keep generating the PWM signal allowing your program to do other useful tasks.

How Arduino Analog Output PWM works

Varying the Mark to Space (M:S) ratio alters the average voltage at the output which can be smoothed into a steady D.C. voltage to create the Arduino analog output. It is a simple way of generating a continuously varying output voltage using only digital signals.

The following diagram shows the difference in average voltage for low, middle and high M:S ratios:

PWM and averages produced by smoothing

PWM Output Smoothing

There are several ways to smooth a PWM signal:

  • Capacitive Resistive pair.
  • Inductive Resistive pair.
  • Persistence of vision.

Capacitive Resistive pair

To make the output signal a true D.C. output all noise and frequency have to be filtered out and the easiest way is to create a low pass filter formed from a resistance and a capacitance.

Inductive Resistive Pair

PWM signals are often used to drive motors (a large inductance with winding resistance). The inductance and resistance filter the PWM signal to give power control of the motor. It does not really matter that the signal is a square wave. All that matters is the amount of current fed to the motor winding.

Persistence of vision

This is all about fading an LED. If you want to do it just connect an LED and current limit resistor to a PWM pin. Your eye will see a smoothly fading LED output (in reality the light is pulsing on and off) - if you adjust the PWM from 1 to 255 and back again over a set period of time.

Your eye cannot react faster than 20ms (the 490Hz signal has period 2ms), and therefore sees a continuous output light level.

Arduino PWM Frequency

There are two main frequencies used in Arduino boards:
  • 490Hz (The default frequency).
  • 980Hz (Used when pin is also shared with Timer 0).
The reason for the different frequencies is that Timer 0 is shared with functions delay() and millis(). These, on the Uno, are on pins 5 and 6.

The following Arduino boards follow this scheme:

    Uno, Nano, Mini, Mega, Leonardo, Micro, Yun, 101 - actual pins used vary.

    Uno, Nano, Mini - use the same pins as here.

Other Arduino chips all use PWM frequencies from 700Hz to 1000Hz.

Arduno Analog Output Pins for PWM

Arduino Nano PWM pins (these are also Arduino Uno PWM pins):

    3, 5, 6, 9, 10 and 11.

Arduino analog output pins 5 and 6 use 980Hz  (Timer 0 shared).

Arduino analog output pins 3, 9, 10 and 11 use 490Hz (the default frequency).

Arduino Pins, Timers and ATMega labels

Arduino
PWM Pins
Timer used
328P label
328P chip pin
PWM Frequency
  3
Timer 2
OC2B
1
490Hz
  5
Timer 0
OC0B
9
980Hz 
  6
Timer 0
OC0A
10
980Hz 
  9
Timer 1
OC1A
13
490Hz
  10
Timer 1 OC1B
14
490Hz
  11 Timer 2
OC2A
15
490Hz

Pins 5 and 6 use Timer 0.
Pins 9 and 10 use Timer 1.
Pins 3 and 11 use Timer 2.

Arduino AnalogWrite

The function to set any of the PWM pins to a specific mark to space ratio is:

    analogWrite(pin,msvalue);

The argument  pin is any of the valid PWM pins.
The argument v can  take a value from 0 to 255.

Setting the Mark to Space ratio


M:S ratio
Arduino PWM value
0%0
25%64
50%128
75%191
100%255

A PWM value of 0 means the output is fully off.
A PWM value of 255 means the output is fully on.

Capacitive smoothing Example

Lets design a filter for the PWM Arduino analog output.

For a single pole filter the centre frequency is given by:

    fc = 1.0/(2 * PI * R * C)

We know that the frequency of the PWM signal is 490Hz so lets choose a filter centre frequency 10 times lower as a 1st estimate.

Lets also choose a resistance of 10k. Then the capacitance is:

    FC = 49

    C  = 1.0/( 2 * 3.14159 * 10e3 * 49) = 3.24e-7 = 324nF

I don't have that exact value to hand so lets choose a 1uF capacitor giving a centre frequency of:

    FC = 1.0/( 2 * 3.14159 * 10e3 * 1e-6)= 15.9Hz

Warning: For these values 10k, 1uF smoothing may not be enough.

Now lets see the resulting output:

Smoothing R=10k C=1uF

The time constant is 10ms.

You can see that the ripple left on the Arduino analog output is large at 253mV. The average D.C. level is where it should be at half the supply at 2.428V (~4.8V on this Arduino Uno USB power connection).

Arduino analog output filtered wihth 10k and 1uF

So if you want a more stable DC Arduing analog output, extra filtering is needed. You can either

  • Use a higher pole filter (requires opamp).
  • Increase R or C or both.
  • Or increase the PWM frequency - program the PWM registers directly.

If you increase the capacitance you will get a smaller ripple but the response to a step input will be slower (the capacitor has to charge to the final voltage).

Smoothing R=100k C=1uF

Time constant is 100ms.

Here the ripple is reduced from 253mV to 25mV. The average voltage is 2.38V (half the supply voltage ~4.8V).

The top waveform is a scope stored waveform at the same voltage per division as in the previous image (for comparison 500mV/Div). The lower waveform is a zoomed in 50mV/Div view of the same waveform in scope A.C. mode to show the ripple in detail.

arduino pwm smoothing r=100k C=1uF

Smoothing R=20k C=220nF

Time constant is 4.4ms (using two 10ks in series and a 220nF).

This is show as an example of more typical values that you might use or find online. It is a compromise in smoothing and speed of response.

Here the ripple is 496mV. The average voltage is again 2.38V (half the supply voltage ~4.8V).

arduino PWM smoothing two 10k 220nF

Arduino Analog Output Resolution

The resolution of the PWM signal is 8 bit. So there are 256 distinct output values of mark to space ratio, and when averaged results in 256 different voltage levels.

  • The PWM value 0 results in zero output.
  • The PWM value 255 results in the output turning fully on.

There are three timers in the Arduino Uno and Nano chips (ATmega328P) and in general each timer is capable of supporting 2 PWM outputs hence why there are 6 PWM outputs.

In fact Timer 1 is capable of being used as a 16 bit PWM but is limited in software to a 8 bit output to keep consistency with other PWM outputs.

PWM Resolution Waveforms

The following waveform show the operation of both 490Hz and 980Hz PWM signals. The higher speed output has a bit period half the lower speed but the higher speed one also has a different output for the 1st bit period.

PWM frequency 490Hz (default)

This frequency is the "normal" frequency of PWM signals i.e. ones not associated with Timer 0.

You can see the bit period id 8.1us. Zero output is at the top followed by incrementing M:S values from 1 to 4 with each waveform incrementing by 8.1us.

Arduino analog output PWM 480Hz

PWM frequency 980Hz

This frequency is the PWM frequency associated Timer 0 shared outputs.

To make it work the first bit period is extended to 8.1us, while all the others are 4.05us long.

The Zero output is at the top followed by incrementing M:S values from 1 to 4 with each waveform incrementing by 4.5us except the 1st. You can also see the last value (254) is correctly positioned at the end of the waveform (before the starting pulse.

Arduino Analog Output PMW associated with timer 0 980Hz

In the Arduino documentation it states that the PWM signal on pins 5 and 6 may not go fully off. This looks to have been corrected by extending the 1st bit output. You can see that waveform 0 is fully off and the 254 output (yellow) is correct.

Example Sketch Sine Generation

The following example uses a PMW output (pin 5) with smoothing capacitor 220nF and resistor 20k to generate the arduino analog output. This is not the best way to create a sine wave output as the output frequency is too low (It also depends on the loop time of the code - here ~185us plus the 1ms delay added on).

Warning: The PWM sine wave output is low frequency.

You need a small time delay to allow the smoothing RC pair to reach the output so its a trade off between frequency, amplitude and resolution.

// Generate (slow) sine using PWM.

int PWMpin = 5;

void setup()
{
   Serial.begin(115200);
   Serial.println("PWM Sine...");
}

void loop()
{
static int pwm;
static float x = 0;

   x+=15;

// Let one period take 100 iterations.  if (x > 100 * 2 * 3.141) x = 0; // Position in middle of PWM with a peak of half the max. op. pwm = int( 128 + 127 * sin(x / 100) ); analogWrite(PWMpin, pwm); delay(1); // When x += 15 - f = 20Hz, Vpp = 1.5V // delayMicroseconds(200); // When x += 15 - f = 61Hz, Vpp = 500MmV // delayMicroseconds(500); // When x += 15 - f = 34Hz, Vpp = 898mV }

Loop delay 1ms Output

You can't really generate a fast Arduino analog output unless you program the PWM hardware directly. Using the standard PWM frequencies and smoothing results in an output frequency of 20Hz ~ 60Hz.

Note that x is skipped along by 15 to increase the frequency but the output waveform resolution is reduced.

Here is the case when using a delay of 1ms:

arduino PWM sine generation 20Hz

Changing the 'x' increment to 1 in the program will increase the resolution but slow the output down further.

Loop delay 185us Output

The loop delay (185us) was measured previously. This is the time to repeat the loop function excluding the delay(1) time.

With no delay the output is not generated long enough for it to update so the amplitude reduces and distorts (all delays commented out). The advantage is increased output frequency (135Hz):

Arduino PWM smoothing min delay 134 Hz

The comments at the end of the code shows these results:

   delay(1);                  // When x += 15 - f = 20Hz, Vpp = 1.5V
//   delayMicroseconds(200);  // When x += 15 - f = 61Hz, Vpp = 500MmV
//   delayMicroseconds(500);  // When x += 15 - f = 34Hz, Vpp = 898mV

To make a better output use program the PWM directly for a higher output frequency and use smaller RC pair

Note: It should be possible for better output by programming the PWM.

Frequently asked questions

Can you write an analog output to A0~A7?

The short answer is no. The only extra internal hardware attached to these pins is the AC.  These pins are either:
  • An analog input (multiplexed to the ADC).
  • A digital input.
  • A digital output.

Can you use Analog pins for digital I/O?

Yes : See above.

Remember to set the pinMode for each pin as INPUT or OUTPUT or INPUT_PULLUP when using them as digital I/O.

How to output a true Arduino Analog Output voltage.

See above page using the Arduino PWM or use an MCP4725.

What's the difference between analogWrite and DigtialWrite.

AnalogWrite, used here, creates a digital PMW signal that when smoothed, results in an analog output voltage.

DigitalWrite outputs either 5V (logic 1) or 0V (logic zero) and nothing in between.



New! Comments

Have your say about what you just read! Leave me a comment in the box below.




Privacy Policy | Contact | About Me

Site Map | Terms of Use



Visit our Facebook Page:
To Visit Click Here


Recent Articles

  1. Digispark Attiny85 Easy IDE install and setup

    Digispark ATtiny85: Essential information on setting up and using this tiny, but powerful, chip

    Read more

  2. Magnetometer tilt compensation

    How to make magnetometer tilt compensation work for a magnetometer such as a QMC5883L using an ADXl345 accelerometer.

    Read more

  3. How the HMC5883L 3-axis digital magentomter works

    HMC5883L - How make a digital compass, Find out the differences between the HMC5883L and the QMC5883L and whether they are compatible.

    Read more

  4. Arduino absolute value - abs() - secrets revealed...

    Secrets of Arduino absolute value abs() - Why it might fail, Why it may cause problems...and how to fix it.

    Read more

  5. Arduino Analog Output...Easy analog output generation

    Arduino Analog Output: How to create the most accurate PWM analog ouput and how to create analog PWM sine waves.

    Read more

  6. ACS758 secrets...

    Using the ACS758 to measure very high current

    Read more

Readers Comments

"I wanted to thank
you so so so much
for all the information
you have provided in
your site it's

SUPERB and FANTASTIC."

- Ranish Pottath

"This site really is
the best and my favorite.
I find here many useful
projects and tips."

- Milan

bursach<at>gmail.com<

"Awesome site,
very, very easy and nice
to navigate!"


- Matt
matt_tr<at>
wolf359.cjb.net


Learn Microcontrollers

"Interested in
Microcontrollers?"

Sign up for The
Free 7 day guide:

FREE GUIDE : CLICK HERE


"I am a newbie to PIC
and I wanted to say
 how great your
site has been for me."


- Dave

de_scott<at>bellsouth.net

"Your site is a great
and perfect work.
congratulations."


- Suresh

integratredinfosys<at>
yahoo.com

"I couldn't find the correct
words to define
yourweb site.

Very useful, uncovered,
honest and clear.

Thanks so much for
your time and works.
Regards."


- Anon

Back to Top