Create a faster DAC with the FastPWMdac library
For the fast ADC see HERE.
For the SAMD21 see this article: Fast PWM-DAC library for the SAM15x15 and Arduino Zero.
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.

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