While the standard Arduino UNO R3 only had analog-to-digital converters the new UNO R4 has at least one real digital-to-analog converter (DAC) that is not emulated by pulse-width modulation. The analog output is fixed to the pin A0 (which obviously can not be used as an input while DAC is performed).. The data sheet claims the DAC has a resolution of 12 bits. What exactly does that mean? Well, the digital value of zero becomes zero volts. And the maximum value of 4095 should give somthing near 5 volts, in reality somewhat less. So one step would be 5/4096 volts, just a little more than 1 millivolt.
Part 1: SawtoothDAC to ADC the short wayWith a short wire, I connected A0 (used as DAC) and A1 (being an ADC). When I set both to their maximum resolution the values of the ADC should be four time the values of the DAC. To check both converters I have to divide the readings by 4. The difference then should be exactly zero.
void setup() {
Serial.begin(9600);
Serial.println(__FILE__);
analogWriteResolution(12);
analogReadResolution(14);
}
int u;
void loop() {
// DAC: 12 bit
analogWrite(DAC, u);
delay(10);
// ADC: 14 bit
int v = analogRead(A1);
/*
Serial.print(u);
Serial.print(" ");
Serial.println(v / 4);
*/
Serial.println(u - v / 4);
u++;
if (u >= 0x1000) u = 0;
}
And this is what the Serial Plotter shows.
Results: the difference is about two bits with some peaks in between.
Check with the ScopeNow I used a scope to check the output of the DAC:
(By the way: 1 conversion takes about 9.5 µs.)
/*
Simple Sawtooth Waveform generator with Arduino UNO R4 Minima
*/
void setup() {
// set the analog output resolution to whatever you want
analogWriteResolution(12);
}
void loop() {
for (int y = 0; y < 10; y++) {
analogWrite(DAC, y);
delayMicroseconds(100);
}
analogWrite(DAC, 0);
delayMicroseconds(200);
}
And here the result on my old scope:
The scope was adjusted to 0.2 ms/cm horizontal and 5mV/cm vertical. Let's do the math: nine steps of 5/4096 volts equal 0.01098 volts. The scope shows a line at a height of 2 cm giving 2 x 5 mV = 10 mV which is approximately the same.
This adjustment was kept for all the follwing pictures. Now the resolution was set to 11 bits:
analogWriteResolution(11);
And this is how it looks like:
Let us continue with 10 bits:
analogWriteResolution(10);
And the picture
Continue with 9 bits:
analogWriteResolution(9);
And the picture:
Now let's see 8 bits
analogWriteResolution(8);
And the picture:
The last one is 7 bits:
analogWriteResolution(7);
And the picture:
To continue further does not make any sense.
Part 2: Sine FunctionTo reduce the math overhead, the sine values are calculated and stored in an array during setup. In order to ease handling of the periodic function only 256 values are being stored and the index variable is of type byte that wraps around after 255.
#include <TimerOne.h>
const int N = 256;
const int amp = 2047;
// minimum value for T: 12
// with digitalWrite: 13 --> 300 Hz
// reducing analogWriteResolution does not help
const int T = 20; // 1E6 / (N * T) = 195 Hz
int sineTab[N];
volatile byte index = 0; // automatic wrap around after 255
void setup() {
Serial.begin(9600);
Timer1.initialize(T);
Timer1.attachInterrupt(doIt);
analogWriteResolution(12); // set the analog output resolution to 12 bit (4096 levels)
for (int i = 0; i < N; i++)
sineTab[i] = amp * (sin(TWO_PI * i / N) + 1);
pinMode(8, OUTPUT);
}
void loop() {}
void doIt() {
int v = sineTab[index++];
analogWrite(DAC, v);
digitalWrite(8, v > amp);
}
The maximum frequency that can be achieved is 300 Hertz.
Comments
Please log in or sign up to comment.