Interfacing 15 Bit DAC With Arduino

by Lithium-ion in Circuits > Arduino

220 Views, 2 Favorites, 0 Comments

Interfacing 15 Bit DAC With Arduino

mini_IMG_4410.jpg

New GP8211S series high resolution DAC with Arduino Kills the competition.

Supplies

Screenshot_2024_06_28-1.png

Components Required:

GP8211S DAC from DF robot

Arduino UNO

Python Compiler

Arduino IDE

Story:

My Video2.gif

In the previous tutorial I had covered how PWM of Arduino can be utilised as DAC. Arduino Nano/Uno boards do not have any internal or onboard DAC units. But with serial, I2C or UART these microcontrollers can be interfaced with an external DAC unit. You would wonder why we need a DAC in a microcontroller, sometimes to get the processed data in audio or in continuous wave format out of a microcontroller we need this digital to analog conversion unit. Nowadays a lot of microcontrollers are working on ML and DSP structures, the best way to get the processed output is in the analog format so that it can be fed into any preamplifier or amplifier after the processing stage. In Digital signal processing(DSPs) all the processing is done on discrete data, on arrays of data. But in actual discrete it has no meaning. In the real world we can only understand a signal coming in analog form.

Digital structures are used in the microcontroller because it is easy to process the data digitally. With a simple mathematical equation coded in C++ or python can change the structure of data as per requirement. The string operations can be easily performed on a set of data, thus manipulating its values easily. There are some basic operations of time shifting and subtracting the value which can be easily performed on a discrete sampled data set. In this way ADCs and DACs are the fundamental need of a signal processing unit. This project is sponsored by PCBWAY. Get your custom PCB prototypes at an affordable price of $5 for 10 PCS from PCBWAY.

GP8211S 15 Bit DAC Units:

DFR1071-GP8211S-FUN.png

This is a 1-channel DAC module with I2C communication, a resolution of 15-bit, and an accuracy of 0.01%, capable of generating analog voltage outputs of 0-10V or 0-5V. The 0-10V or 0-5V voltage output is a standard driving method. It can be widely used in automation control scenarios such as lighting adjustment, frequency converters, valve regulation, and pump control, etc. This product can drive a variety of 0-10V or 0-5V controlled devices available in the market through Arduino programming.

The high precision and resolution of this module make it suitable for control scenarios that require higher signal accuracy, such as fine speed control or angle control.

DAC series modules are a range of products that can be controlled through I2C signals to generate voltage output signals. This series of DAC products not only offers a variety of output signal ranges, but also provides three selectable resolutions: 8-bit, 12-bit, and 15-bit. It allows for the choice of either single-channel or dual-channel configurations, and multiple modules can be cascaded to form a multi-channel output. This DAC modules have applications in:

Automatic light adjustment

Variable frequency drive (VFD)

Automatic valve regulation

Automatic water pump control

Specifications:

6.jpg
  • Operating voltage: 3.3V to 5V
  • Communication Method: I2C
  • Chip Type: GP8211S
  • Resolution: 15-bit
  • Output Voltage: 0-5V or 0-10V
  • Number of channels: 1 channels
  • Value Range: 0 - 32767 corresponding to 0-5V or 0-10V
  • Output voltage: 0.01%
  • Output voltage linearity error: 0.01%


Interfacing With Arduino:

DFR1071-GP8211S-CON.png
mini_IMG_4404.jpg

Here I have an I2C variant of this DAC module, Arduino I2C has a limited bandwidth and speed, that’s why a limited frequency signal can be generated using this module. To generate any waveform first we have to make an array according to the number of values DAC is going to cover with respect to time. These types of waves are easy to generate; a few examples are shown in the tutorial below. This array of values is known as a lookup table. Which is basically a list of numbers stacked up in a specified format such that values are taken one by one from that list and respective analog signals are generated.

Connect the Arduino with the DAC module as shown in the figure above. Run the serial monitor, plot or get the output on an oscilloscope to see working. Include the <DFRobot_GP8XXX.h> library in the Arduino IDE before uploading the sketch. Download the library files from here.

Generation of an Arbitrary Signal Out of DAC:

mini_IMG_4405.jpg
My Video.gif

No need to do hard mathematic calculations, if a signal with some DC value is required at output, some predefined functions are given in the library which makes the work easy and eliminates the need of writing any firmware for this 15 bit DAC module.

1) GP8211S.setDACOutRange(GP8211S.eOutputRange5V); // set reference to 5V

2) GP8211S.setDACOutRange(GP8211S.eOutputRange10V); // set reference to 10V

3) GP8211S.setDACOutVoltage(13106); // to write an analog value just give data in 15 bit format, here 13,106 is the amplitude value with respect to 15 bit(32,768) data. If the 5V reference is taken then the output value of the analog signal is given by: (5/32,768)*13106 = 1.999V ~ 2V analog DC value.


Downloads

Main Sketch of Arbitrary Wave:

mini_IMG_4409.jpg
#include <DFRobot_GP8XXX.h>    // https://github.com/DFRobot/DFRobot_GP8XXX 
DFRobot_GP8211S GP8211S;
void setup() {
Serial.begin(9600);
while(GP8211S.begin()!=0){
Serial.println("Connection Failed!");
delay(1000);
}
GP8211S.setDACOutRange(GP8211S.eOutputRange5V);
//GP8211S.setDACOutRange(GP8211S.eOutputRange10V);
delay(100);
//Save the set voltage in the chip's internal memory for power loss recovery.
//GP8211S.store();
}
void loop() { // 15 BIT RES give total steps of 32767 and A Voltage resolution of 152uV at 5 volts Vref.
GP8211S.setDACOutVoltage(6553); // 1V
delay(1000);
GP8211S.setDACOutVoltage(13106); // 2V
delay(1000);
GP8211S.setDACOutVoltage(19660); // 3V
delay(1000);
GP8211S.setDACOutVoltage(26213); // 4V
delay(1000);
GP8211S.setDACOutVoltage(32767); // 5V
delay(1000);
}

Downloads

Sinusoidal Wave Generation:

mini_IMG_4411.jpg
My Video1.gif

To make this look table, every signal has some properties and a mathematical function is attached to every wave. This mathematical function is used to generate the waveform, by inserting one by one values in it or we can use a python script and an online compiler to do the same. Here is an example of a sine wave generated from the mathematical function given below.

The wave can be generated as per requirement of samples, this is a 9 bit wave having a total of 512(2^9) sample points. The amplitude values here range from 0 to 4,096 which is a 12 bit amplitude number. The DAC we are using is 15 bit so the maximum value of amplitude and time which this DAC can see is 32,768(2^15). In this way, the below given look up table is a hybrid 9 bit wave. Which can be easily interpreted using a 15 bit DAC. Any combination of waves can be generated the same 9 bit wave can also be generated using 0 to 32,768 values. Which makes it a 15 bit amplitude wave and 9 bit time wave.

#include <DFRobot_GP8XXX.h>
DFRobot_GP8211S GP8211S;
const PROGMEM uint16_t DACLookup_FullSine_9Bit[512] =
{
2048, 2073, 2098, 2123, 2148, 2174, 2199, 2224,
2249, 2274, 2299, 2324, 2349, 2373, 2398, 2423,
2448, 2472, 2497, 2521, 2546, 2570, 2594, 2618,
2643, 2667, 2690, 2714, 2738, 2762, 2785, 2808,
2832, 2855, 2878, 2901, 2924, 2946, 2969, 2991,
3013, 3036, 3057, 3079, 3101, 3122, 3144, 3165,
3186, 3207, 3227, 3248, 3268, 3288, 3308, 3328,
3347, 3367, 3386, 3405, 3423, 3442, 3460, 3478,
3496, 3514, 3531, 3548, 3565, 3582, 3599, 3615,
3631, 3647, 3663, 3678, 3693, 3708, 3722, 3737,
3751, 3765, 3778, 3792, 3805, 3817, 3830, 3842,
3854, 3866, 3877, 3888, 3899, 3910, 3920, 3930,
3940, 3950, 3959, 3968, 3976, 3985, 3993, 4000,
4008, 4015, 4022, 4028, 4035, 4041, 4046, 4052,
4057, 4061, 4066, 4070, 4074, 4077, 4081, 4084,
4086, 4088, 4090, 4092, 4094, 4095, 4095, 4095,
4095, 4095, 4095, 4095, 4094, 4092, 4090, 4088,
4086, 4084, 4081, 4077, 4074, 4070, 4066, 4061,
4057, 4052, 4046, 4041, 4035, 4028, 4022, 4015,
4008, 4000, 3993, 3985, 3976, 3968, 3959, 3950,
3940, 3930, 3920, 3910, 3899, 3888, 3877, 3866,
3854, 3842, 3830, 3817, 3805, 3792, 3778, 3765,
3751, 3737, 3722, 3708, 3693, 3678, 3663, 3647,
3631, 3615, 3599, 3582, 3565, 3548, 3531, 3514,
3496, 3478, 3460, 3442, 3423, 3405, 3386, 3367,
3347, 3328, 3308, 3288, 3268, 3248, 3227, 3207,
3186, 3165, 3144, 3122, 3101, 3079, 3057, 3036,
3013, 2991, 2969, 2946, 2924, 2901, 2878, 2855,
2832, 2808, 2785, 2762, 2738, 2714, 2690, 2667,
2643, 2618, 2594, 2570, 2546, 2521, 2497, 2472,
2448, 2423, 2398, 2373, 2349, 2324, 2299, 2274,
2249, 2224, 2199, 2174, 2148, 2123, 2098, 2073,
2048, 2023, 1998, 1973, 1948, 1922, 1897, 1872,
1847, 1822, 1797, 1772, 1747, 1723, 1698, 1673,
1648, 1624, 1599, 1575, 1550, 1526, 1502, 1478,
1453, 1429, 1406, 1382, 1358, 1334, 1311, 1288,
1264, 1241, 1218, 1195, 1172, 1150, 1127, 1105,
1083, 1060, 1039, 1017, 995, 974, 952, 931,
910, 889, 869, 848, 828, 808, 788, 768,
749, 729, 710, 691, 673, 654, 636, 618,
600, 582, 565, 548, 531, 514, 497, 481,
465, 449, 433, 418, 403, 388, 374, 359,
345, 331, 318, 304, 291, 279, 266, 254,
242, 230, 219, 208, 197, 186, 176, 166,
156, 146, 137, 128, 120, 111, 103, 96,
88, 81, 74, 68, 61, 55, 50, 44,
39, 35, 30, 26, 22, 19, 15, 12,
10, 8, 6, 4, 2, 1, 1, 0,
0, 0, 1, 1, 2, 4, 6, 8,
10, 12, 15, 19, 22, 26, 30, 35,
39, 44, 50, 55, 61, 68, 74, 81,
88, 96, 103, 111, 120, 128, 137, 146,
156, 166, 176, 186, 197, 208, 219, 230,
242, 254, 266, 279, 291, 304, 318, 331,
345, 359, 374, 388, 403, 418, 433, 449,
465, 481, 497, 514, 531, 548, 565, 582,
600, 618, 636, 654, 673, 691, 710, 729,
749, 768, 788, 808, 828, 848, 869, 889,
910, 931, 952, 974, 995, 1017, 1039, 1060,
1083, 1105, 1127, 1150, 1172, 1195, 1218, 1241,
1264, 1288, 1311, 1334, 1358, 1382, 1406, 1429,
1453, 1478, 1502, 1526, 1550, 1575, 1599, 1624,
1648, 1673, 1698, 1723, 1747, 1772, 1797, 1822,
1847, 1872, 1897, 1922, 1948, 1973, 1998, 2023
};
void setup() {
Serial.begin(9600);
while(GP8211S.begin()!=0){
Serial.println("Error in Connection ! ");
delay(1000);
}
GP8211S.setDACOutRange(GP8211S.eOutputRange10V);
delay(500);
}
void loop() {
uint16_t i;
for (i = 0; i < 512; i++)
{
GP8211S.setDACOutVoltage(pgm_read_word(&(DACLookup_FullSine_9Bit[i])), false);
}
}

Usually the time axis sample points (512) are enough here, because we have to transmit these 512 values over I2C over and over again to generate a sine wave. Higher the number of time axis points lowered will be the transmission rate over I2C which means lower will be the frequency of signal. To generate a high frequency signal the time sample points to be optimized well.

Python Script to Generate Sine Wave:

mini_IMG_4408.jpg
import math
# Fill the number of samples
num_points = 1000
# Calculate the step size
step_size = 2 * math.pi / num_points
# Initialize the lookup table
sine_lookup_table = []
# Generate the sine wave values and fill the lookup table
for i in range(num_points):
# Calculate the sine value
sine_value = math.sin(i * step_size)
# Scale the sine value to fit within the 12-bit range (0 to 4095)
# for 10bit replace with 511.5
# for 12 bit replace with 2147.5
# for 15 bit 16383.5
scaled_value = int((sine_value + 1) * 16383.5)
# Append the scaled value to the lookup table
sine_lookup_table.append(scaled_value)
# Print the sine wave lookup table
print(sine_lookup_table)

See an example of a hybrid 1000 sample 15 bit amplitude wave. Download the sketch from here, values generated by this python script. The values for generating different amplitude waves are stated in the comments in the program itself.

Arduino Clone With Onboard DAC:

Screenshot_2024_07_28-2.png
Screenshot_2024_07_28-1.png

I have interfaced the same module on my Clone made Arduino Uno, check the Arduino board made by me using the PCBWAY PCB assembly services. Get your Assembled or PCB prototypes at an affordable price of $5 for 10 PCS from PCBWAY.

PCBWAY is celebrating its 10th anniversary, marking a decade of providing PCB manufacturing and assembly services. They typically run special promotions, contests, and offer discounts to celebrate milestones like this. Which includes:

Special discount coupons for PCB orders, assembly services, or other related products. Offers for free or heavily discounted PCBs for a limited number of orders. Opportunities to win electronic gadgets, tools, or PCB-related equipment through participation in contests or giveaways. Additional benefits for returning customers, such as extra loyalty points or exclusive discounts. Bundled offers that might include a combination of PCBs, components, and assembly services at a reduced price. Sign-up now and get free coupons.