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