The video below should be viewed in conjunction with this article as it contains many details not present below.
What are DAC’s?
DAC’s (Digital to Analogue Converters) unlike ADC’s are not on many MCU’s. The rather excellent ESP32 has two as standard but if your using another type of MCU (i.e. Arduino variant) then you can be out of luck. If your not sure what they do then very simply they convert a digital value (i.e. a number) to a corresponding voltage on an output pin..
Resolution
This is basically the range of numbers that you can send to your DAC and they start at 0 to a maximum value. The maximum value depends on the individual DAC and it’s usually quoted in bits, i.e. 8 bit, 10 bit and 12 bit, these are common values. If it’s 8 bit then the max is 255 (i.e. 0 to 255, 256 values), if 10 bit then 1023 (1024 values), if 12 bit then 4095. The higher the value then them more finite control you have over the voltage.
So if we had an 8 bit DAC and a max voltage of 4V then sending “0” to the DAC would give 0V, 127 would give 2V (approx) and 255 would give 4V. With obviously every value in between being available. You could work out how much the voltage will increase for every value by dividing the max voltage by the resolution, so for the above it would be 4v/256 which equals 0.015625 volts per value.
Uses
Wherever you need to control a voltage precisely you could use a DAC. Remember though that the MCU itself cannot drive much current at all and you should always have some sort of driver for whatever is you are using. This might take the form of a simple transistor or more complex buffer circuitry.
However by far and away the most common use of a DAC is for audio. We store sounds as numbers in our digital equipment no matter what it is but at some point we want to listen to that and at this point we can use a DAC to translate it to a voltage that then can be amplified and sent to a speaker. That is what I will be using the DAC for.
The Circuit
The Code
Below is the code shown in the video. Just copy and paste into the Arduino IDE.
Sine Wave
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
// Create a sine wave on an oscilloscope using a 8 bit DAC // (C) XTronical 2019 // Use in any way you wish! // // As we're using an 8 bit value for the DAC 0-255 (256 parts) that means for us // there are 256 'bits' to a complete circle not 360 (as in degrees) or even 2PI Radians // (There are 2*PI Radians in a circle and computers love to work in Radians!) // The computer works in radians for SIN, COSINE etc. so we must convert our 0 -255 value // to radians, the comments in the code show this. #include <Wire.h> #include <Adafruit_MCP4725.h> Adafruit_MCP4725 dac; int SineValues[256]; // an array to store our values for sine void setup() { float ConversionFactor=(2*PI)/256; // convert my 0-255 bits in a circle to radians // there are 2 x PI radians in a circle hence the 2*PI // Then divide by 256 to get the value in radians // for one of my 0-255 bits. float RadAngle; // Angle in Radians // calculate sine values for(int MyAngle=0;MyAngle<256;MyAngle++) { RadAngle=MyAngle*ConversionFactor; // 8 bit angle converted to radians SineValues[MyAngle]=((sin(RadAngle)*127)+128)*16; // get the sine of this angle and 'shift' up so // there are no negative values in the data // as the DAC does not understand them and would // convert to positive values. } dac.begin(0x62); // I2C address of DAC } void loop() { for(int i=0;i<256;i+=16){ dac.setVoltage(SineValues[i], false); } } |
Saw-Tooth
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
// Create a saw-tooth wave on an oscilloscope using a 8 bit DAC // (C) XTronical 2019 // Use in any way you wish! // #include <Wire.h> #include <Adafruit_MCP4725.h> Adafruit_MCP4725 dac; void setup() { dac.begin(0x62); } void loop() { for(int i=0;i<4095;i+=64) dac.setVoltage(i,false); } |
Triangle Wave
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
// Create a triangle wave on an oscilloscope using a 8 bit DAC // (C) XTronical 2019 // Use in any way you wish! // #include <Wire.h> #include <Adafruit_MCP4725.h> Adafruit_MCP4725 dac; void setup() { dac.begin(0x62); } void loop() { for(int i=0;i<4095;i+=256) dac.setVoltage(i,false); for(int i=4095;i>0;i-=256) dac.setVoltage(i,false); } |
Advanced Triangle Wave
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
// Create a advanced triangle wave on an oscilloscope using a 8 bit DAC // (C) XTronical 2019 // Use in any way you wish! #include <Wire.h> #include <Adafruit_MCP4725.h> Adafruit_MCP4725 dac; void setup() { dac.begin(0x62); } void loop() { for(int i=0;i<4095;i+=256) dac.setVoltage(i, false); for(int i=4095;i>=0;i-=256) dac.setVoltage(i, false); for(int i=1;i<750;i+=256) dac.setVoltage(i, false); for(int i=750;i>0;i-=256) dac.setVoltage(i, false); } |
That’s if for this post, look out for more articles on this series as I will be developing some software similar to the ESP32 DacAudio software and I will be looking at other DAC’s as well that are SPI rather than I2C which should mean an increase in speed.