Contents[Hide]

Create a faster DAC with the FastPWMdac library

For the fast ADC see HERE.
The Arduino has no integrated DAC; to create analog output values, we have to use the standard Arduino function analogWrite(). This creates a so called PWM DAC, a PWM signal which has to be filtered with a low-pass filter. However, the standard analogWrite() function is very slow, don't use it anymore. The FastPWMdac library is much faster; these are the advantages:

  • The PWM frequency is 31250Hz for 8-bit instead of 490Hz for the standard analogWrite().
  • The resolution is 8-bit or 10-bit.
  • The low pass filter uses a much smaller capacitor; no elco required anymore
  • The settling time is reduced which has great benefits when the DAC is used in a control loop.

Fast 8/10-bit PWM DAC for the Arduino

Fast 8/10-bit PWM DAC for the Arduino - Fast 8/10-bit PWM DAC for the Arduino
Fast 8/10-bit PWM DAC for the Arduino
Fast 8/10-bit PWM DAC for the Arduino - Fast 8/10-bit PWM DAC for the Arduino

TimerOne library

The library <TimerOne.h> has to be installed too. Paul Stoffregen has further improved the TimerOne library: it support many Arduino boards and is faster, download the TimerOne library HERE
Copy the entire folder TimerOne-master to C:\Program Files\Arduino\libraries.

Using the PWM DAC

Output voltage

For a 5V supply voltage, the output voltage is:
Resolution 8bit: U = value * 5 / 255
Resolution 10bit: U = value * 5 / 1023

Resolution

The resolution can be set to 8bit or 10bit.

void init(byte _timer1PWMpin, byte resolution);

  • For 8bit the PWM period is 32us / 31.25KHz.
  • For 10bit the PWM period is 130us / 7.8Khz. 

Output pins

For the Arduino Uno / ATmega328p, only the pins 9 or 10 can be used. For other Arduino boards see: TimerOne & TimerThree Libraries at www.pjrc.com.

Characteristics

With a resolution of 8 bit and a 10k / 100nF low pass filter, these are the characteristics:

  • PWM frequency 31250Hz
  • Max ripple voltage 40mV
  • Cut-off frequency 160Hz
  • Settling time 0% ... 90% 2.3ms

Fast PWM DAC example program

The example program creates a sawtooth at pin 9:   

#include <FastPWMdac.h>
const byte dacPin = 9; 
FastPWMdac fastPWMdac;
void setup() 
{ //analogWrite(dacPin1, 127); // period = 490Hz
}
void loop()
{ fastPWMdac.init(dacPin, 8); // initialization for 8 bit resolution
  for(int i=0; i<256; i++) // use byte because of 8 bit resolution
  { fastPWMdac.analogWrite8bit(i); // sawtooth output, period = 31.25Khz
    delay(1);
  }
  fastPWMdac.init(dacPin, 10); // initialization for 10 bit resolution
  for(int i=1023; i>=0; i--)
  { fastPWMdac.analogWrite10bit(i); // sawtooth output, period = 7.8Khz
    delay(1);
  }
}

Fast PWM DAC library

cpp file  

/* 
FastPWMdac
For the output pins that can be used see: http://www.pjrc.com/teensy/td_libs_TimerOne.html
The library <TimerOne.h> has to be installed too.
Copyright (C) 2015  Albert van Dalen http://www.avdweb.nl
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License
as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License at http://www.gnu.org/licenses .
Version 19-12-2015
*/
#include <TimerOne.h> // this library has to be installed
#include "FastPWMdac.h"
void FastPWMdac::init(byte _timer1PWMpin, byte resolution)
{ timer1PWMpin = _timer1PWMpin;
  if(resolution == 8) Timer1.initialize(32); 
  if(resolution == 10) Timer1.initialize(128); 
  Timer1.pwm(timer1PWMpin, 0); // dummy, required before setPwmDuty()
}
void FastPWMdac::analogWrite8bit(byte value8bit)
{ Timer1.setPwmDuty(timer1PWMpin, value8bit*4); // faster than pwm() 
}
void FastPWMdac::analogWrite10bit(int value10bit)
{ Timer1.setPwmDuty(timer1PWMpin, value10bit); // faster than pwm() 
}

header file 

/* 
FastPWMdac
For the output pins that can be used see: http://www.pjrc.com/teensy/td_libs_TimerOne.html
The library <TimerOne.h> has to be installed too.
Copyright (C) 2015  Albert van Dalen http://www.avdweb.nl
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License
as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License at http://www.gnu.org/licenses .
Version 19-12-2015
*/
#ifndef FastPWMdac_H
#define FastPWMdac_H
class FastPWMdac
{ 
public:
  void init(byte _timer1PWMpin, byte resolution);
  void analogWrite8bit(byte value8bit);
  void analogWrite10bit(int value10bit);
private:
  byte timer1PWMpin; 
};
#endif

Do you have any comments? Please let me know.
Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.