Introduction: Practical DACs
If you've done much work with microcontroller projects, you have probably found yourself needing to interface some analog component with a digital component, or vice versa. In order for digital components and circuits to communicate with the analog world, there must be some conversion between the discrete digital values and continuous analog ones. This instructable will give you the background to understand Digital-to-Analog Converters (DACs) and by the end of this tutorial you will have the knowledge and skills to build your own high-resolution custom DAC.
This instructable is part of my "Practical" series of DIY guides. You may also like Practical Power Supplies, Practical OpAmps, Practical Voltage Dividers, Practical Electronic Formulas, or any of my other instructables. I will link them all together when I have completed the practical series of DIY guides.
Keeping with the format of the "Practical" series, each section is prefaced with an "At a Glance"-style bulleted objective list that helps set expectations and prepare the reader for that part of the instructable. I've tried to write in a clear, concise, and easily accessible manner while handling sometimes complex or complicated subject matter. The end of each series is capped off with a "final remarks/conclusion" section sometimes with ideas for further research but always with ways you may contact me if you have questions or comments about my instructable. I am always open to hear your thoughts on improving this or any of my Instructables.
Now, let's get started learning how to interface the digital world to the analog world!
Step 1: DAC Basics
- identify when you would need to use a DAC
- describe the primary characteristics of all DACs
- estimate accuracy in small-bit DACs
- assess DAC designs
DAC BasicsHere you will learn or refresh your memory on DAC basics.
Digital values are discrete, stepped values that have clear boundaries delineating them from other digital values. For instance, the values 1 and 2 are discrete values (although they could also be analog ones, but more on this later) which means that there are no values in between the value 1 and the value 2. They can be thought of as bins similar to FFT. Look at the figure below to see how discrete values are used in a histogram. Note the analog line that bounds the histogram frequencies.
Some examples of digital values might be age (assuming year boundaries), eye color, school grade, or categorical height (ie short, medium, tall vs. 5'9" or 6'2").
Analog values are continuous, on a line and include all the intermediate values between any two sample points. Notice on the histogram below that the analog line is smooth while the digital line is boxy. Some examples of continuous values includes voltage and height.
A DAC is a device that takes digital values, often in binary, and converts that number into an equivalent analog value. For example, the RGB value in VGA monitors expects an analog value from around 0 to 1V for each color channel, but most GPUs and graphic cards operate on digital values (ie binary bits), so the video RAMDAC converts from a binary pixel representation, say, 01100011 to a voltage that represents that value to the VGA monitor.
Another common use of a DAC in electronics and microcontrollers is when you want to take stored digital samples and convert that to an equivalent sine wave. This can often be useful for showing things like AC voltage or current over time in a meaningful way.
Most DAC ICs are multiplying DACs, meaning the DAC produces an output signal that is proportional to the product of a varying input reference level multiplied times the digital input code. Some DACs have a fixed internal reference input that is used to set the analog output range while others support external analog input. DACs are capable of producing unipolar output, that is, a single-polarity analog signal or bipolar (positive and negative values). Many unipolar DACs take binary code as its digital input with bipolar DACs taking either a binary offset or a two's compliment value.
Primary CharacteristicsWhen choosing or building a DAC you should look for a couple of primary characeristics of the DAC to get an idea of how the DAC will perform in your environment (or what you have to do if you're building one by hand). The first step is to determine the resolution. This is easy. Resolution, σ, is the number of bits in the digital input. If your DAC has four binary inputs, then the DAC resolution would be 4bits. Second, work out your maximum output voltage by calculating 2σ • LSB where LSB is the least significant bits.
The next parameter to look at is probably the biggest and most important. It is called integral nonlinearity, or INL for short. The INL of a DAC describes its deviation between the ideal output and the actual output. That is, the deviation of the DAC's transfer frunction from a straight line, typically measured at each analog step. The straight line can be approximated to the actual transfer function. Two most common types of lines are called best fit line and the endpoint line. In any case, the INL is the maximum distance between the ideal line and the actual transfer function. Low-to-mid range DACs may specify an INL upwards of 16 while the quite good ones (and inherently more expensive) can offer an INL of around 1. INL is formally specified like this:
INL = | [(Vc - V0/(VLSB-IDEAL)] - c |
⇒ 0 < c < 2N - 1
⇒ Vc is analog value represented by digital input code c
⇒ N is DAC resolution in bits
⇒ V0 is minimum output corresponding to all 0 input
⇒ VLSB-IDEAL is the ideal spacing for 2 adjacent input codes
Further, to determine the slope of the line through the end points, you can use:
m = (Vc-max - V0)/cmax
The offset error is the output voltage when the digital input is zero and remains constant for all input values. The offset error can often be mitigated by fine tuning the DAC circuit. Gain error is the difference between the ideal maximum output voltage and the actual maximum value of the transfer function after subtracting the offset error. Gain error changes the slope of the function.
For the most part, the characteristics of a DAC are defined by its reference voltage. The DAC's reference voltage, Vref, sets the DAC's maximum output voltage and also defines the voltage step by which the output changes in response to a 1LSB transition at the input. Simply put, one step equals Vref/2N.
Estimating DAC AccuracyAs you can see from the graph, DACs with low number bit input are unable to produce an analog signal with the resolution to make the signal appear continuous. Assuming a 5V reference and taking a 4-bit binary input, the analog output would be converted into 24 = 16 steps of 0.3125V (313mV) each (5V/16 steps). To get a finer grained control on the analog output you would need to use higher-order binary input like, say, 8-bits or 16-bits or even 18-bit numbers. However, you can't really predict the accuracy of a DAC by looking at its resolution on its own because other sources of error (mentioned above) must be taken into account.
If our converter has a resolution of 8 bits, we have 28 = 256 binary numbers to work with, along with 256 analog steps. If the DAC is configured to generate 0V at 00000000 and 5V at 11111111 then each analog step is only 0.0195V high (1/256 * 5V). As you can probably realize, increasing resolution can be tricky when building custom DACs.
Step 2: Binary Weighted DAC
Objectives at a Glance...
- discuss, construct, and modify a binary-weighted DAC
- identify the components of a binary weighted DAC
- critique and assess the shortcomings of this design
The Binary Weighted DAC
The figure included below in this section shows a simple binary-weighted DAC constructed from digital switches (could be from a 4066 IC or separate individual switches) and a set of weighted resistors connected to an operational amplifier. The op amp creates an inverting amplifier that sums input resistance Rin through a feedback loop of R3. The switches and resistors act together as a digitally controlled resistor that can take on one of 16 different values of resistance. This essentially provides a digitally controlled current source. Each new binary code applied to the inputs generates a new discrete current level that is summed by R3 to provide a new discrete output voltage level.
Here, the values of resistors are R, R/2, R/4, and R/8 where R = 10K ohm and R3 = 10K ohm. The equivalent circuit of the op amp generates Vout = -Vin(R3/Rin) = -5V(10K/Rin) with a 5V input. To find all possible values of Rin we can use the standard "resistors in parallel" formula of:
1/Rin = A 1/8R + B 1/4R + C 1/2R + D 1/R
Here the A through D act as a binary coefficient modifying the resistor in the appropriate binary place. To find the analog output voltage, you simply use the formula I already included above:
Vout = -Vin(R3/Rin)
Assuming Vin of 5V and R3 of 10K, we come up with the table included below.
This binary-weighted DAC is limited to 4-bit input generating 16 analog output steps. To double the resolution, you might think to add in four more resistors at 1/16R, 1/32R, 1/64R, and 1/128R and you would be correct...but only partially. This is where implementation falls short of theory. The problem with this approach is that when you get to the 1/128R resistor, you would have to find a 78.125 ohm resistor and even if you found one, or built one up from separate resistors, you would still be plagued with the resistor's tolerance level. A 10% tolerance means the actual value of the 78.125 ohm resistor may fluctuate within +/- 10%. You can do better with a 1% tolerance resistor but how do you get out to 3 significant figures of resolution?
This weighted binary/scaled approach fails us when we need more than just a few bits of resolution. What are we to do? Junk this design and turn the page!
Step 3: R/2R DAC
- identify and discuss the components of an R/2R DAC
- create, construct, and modify an R/2R DAC
- critique and assess the value and shortcomings of this design
The R/2R Ladder DACThe major benefit of moving to this type of custom-build DAC is its ability to overcome the required precision shortcomings you found in the scaled, binary-weighted DAC of the previous section. Plus, it reduces the different values of resistors needed to only three: R, 2R, and Rf. The term R/2R means a resitor of value R and a resistor of value 2R, or twice the value of R. Check out the figure I included below.
As expected, here are the relevant or important formulas when working with this type of DAC.
I = Vref/R
Isum = I (S3/2 + S2/4 + S1/8 + S0/16)
Vout = -Isum * Rf
Where Vref is 5V, S0 through S3 are the switches in the illustration with S3 on top and S0 on bottom. Isum is the sum of the currents entering the inverting input of the op amp and Rf is the feedback resistor of the summing amplifier.
The key to understanding how this DAC works is twofold.
First, you must realize that the current drawn through any one switch is always the same regardless of whether it is connected to GND or Vref. If the switch is connected to GND, then Isum will flow to GND but if the switch is thrown up, then Isum will enter the inverting input of the op amp as the op amp creates a virtual ground at it's inverting input (remember that setting an op amp's non-inverting input to GND will make the inverting input = 0V via negative feedback...if you need a refresher please check out my Practical Operation Amplifiers DIY guide).
When you understand that the current flowing through any one switch is always constant, it makes solving for the variables of the equations much easier as the total current I supplied by Vref will be constant, as well. Once you've grok'd that, you can figure out what fractions of the total current passes through each of the branches within the R/2R network using some simple circuit analysis.
It is key to understand how the resistance (and hence, current) is calculated and can be done by performing a simple circuit reduction. Please refer to my Practical Voltage Dividers for details on how this is done. Once you have done this, you will have a consistent means to generate fractions of 1/2I, 1/4I, 1/8I, and 1/16I which get summed together by the op amp. For example, if switches S3, S2, and S1 (1101) are thrown, we get 1/2I, 1/4I, and 1/16I current combining in Isum. To derive I itself, we can simply use Ohm's law of V = IR or, solving for I, I = V/R. So, assuming Vref of 5V , R of 10K ohm, and Rf of 20K we get I = 5V/10K = 500 uA. Using this, Isum = 1/2(500uA) + 1/4(500uA) + 1/16(500uA) = 406.25 uA. The final output voltage, Vout is then Vout = -Isum*Rf = -500uA * 20K = -8.125V for a digital input value of 1101.
To create an R/2R DAC with higher resolution you only have to add more voltage dividers and take some care when selecting your resistors.
Now you're ready to put what you've learned to use and build an R/2R DAC. Turn the page and let's go!
Step 4: Build It
- Design or modify an existing schematic
- Test resistors with a multimeter to assess tolerances
- Fabricate your own custom PCB
- Solder surface mount components to a PCB
- Test and verify DAC output
Fire up the soldering iron, locate your multimeter, and steel yourself for some rough SMD on SMD action. The R/2R DAC you will be building has a few new features that I didn't cover in the previous sections. Some new functionality was added to enable it to be used on pin-constrained AVRs like the ATtiny series while the choice of an inverting op amp was based on price, availability, and input impedance.
Before you BeginYour first step should be to gather up a good amount of the required resistors and assess their tolerances. Keep in mind, that while you do want to use resistor values as close to the ones specified, it is definitely more important that all the resistors used have exactly the same values. That is, the standard deviation of the mean of your resistor values should not be significant. In other words, if the schematic specifies 2.2k but you only have 2k then fine, but what you really want to ensure is that all of those 2k resistors you use have exactly the same values. You do this by testing them with the ohm/resistance setting on your multimeter. If you measure them all and have a bunch that are 1999 ohms or maybe 2005 ohms then use that grouping. Deviations from the mean values will have more of an impact on the DAC transfer function than the original specified resistor value within its tolerance.
To make things a little easier, I've included a Bill of Material (BOM) below so you can get organized and setup your mis en place workbench.
|IC1||74HC164N||74HC164N||DIL14||8-bit parallel out SHIFT REGISTER|
|IC2||74HC164N||74HC164N||DIL14||8-bit parallel out SHIFT REGISTER|
|R1||20K||R-US_R0805||R0805||RESISTOR, American symbol|
|R2||20K||R-US_R0805||R0805||RESISTOR, American symbol|
|R3||20K||R-US_R0805||R0805||RESISTOR, American symbol|
|R4||20K||R-US_R0805||R0805||RESISTOR, American symbol|
|R5||20K||R-US_R0805||R0805||RESISTOR, American symbol|
|R6||20K||R-US_R0805||R0805||RESISTOR, American symbol|
|R7||20K||R-US_R0805||R0805||RESISTOR, American symbol|
|R8||20K||R-US_R0805||R0805||RESISTOR, American symbol|
|R9||20K||R-US_R0805||R0805||RESISTOR, American symbol|
|R10||20K||R-US_R0805||R0805||RESISTOR, American symbol|
|R11||20K||R-US_R0805||R0805||RESISTOR, American symbol|
|R12||20K||R-US_R0805||R0805||RESISTOR, American symbol|
|R13||20K||R-US_R0805||R0805||RESISTOR, American symbol|
|R14||10K||R-US_R0805||R0805||RESISTOR, American symbol|
|R15||10K||R-US_R0805||R0805||RESISTOR, American symbol|
|R16||10K||R-US_R0805||R0805||RESISTOR, American symbol|
|R17||10K||R-US_R0805||R0805||RESISTOR, American symbol|
|R18||10K||R-US_R0805||R0805||RESISTOR, American symbol|
|R19||10K||R-US_R0805||R0805||RESISTOR, American symbol|
|R20||10K||R-US_R0805||R0805||RESISTOR, American symbol|
|R21||10K||R-US_R0805||R0805||RESISTOR, American symbol|
|R22||10K||R-US_R0805||R0805||RESISTOR, American symbol|
|R23||10K||R-US_R0805||R0805||RESISTOR, American symbol|
|R24||10K||R-US_R0805||R0805||RESISTOR, American symbol|
|R25||20K||R-US_R0805||R0805||RESISTOR, American symbol|
Notice that this R/2R DAC sports a resolution of 12 bits, which is 212 possible binary input code values. Recall from the theory discussion previously that the higher resolution the DAC, the smaller the analog steps between each output value, which means the device reading the analog output should be able to sample and convert with at least that much precision.
You will also notice that instead of those clunky manual switches I used in previous demonstrations, this DAC takes a serial input into two chained serial-in/parallel-out shift registers. This keeps us from having to supply 12 dedicated I/O pins for the digital code inputs. The op amp at the end is of the JFET variety so it gives us a high input impedance. If you need to know why this is important, please refer to my practical operational amplifiers DIY guide.
This board breaks out six signals consisting of SIGNAL_IN[DIGITAL], CLOCK/STROBE, !RESET, SIGNAL_OUT[ANALOG] and two power signals: VCC and GND. A brief definition of what each signal is meant for follows.
This signal is the digital serial-data input into the shift registers of the DAC.
For every shift down of values, you strobe the CLOCK line and the shift registers will shift all values down one flip-flop location.
This is an active LOW signal that resets the shift registers to zero values.
This is the analog signal from the conversion process and transfer function based on the inputs.
VCC and GND
VCC should at least be 5V but could be upwards of ≈15V. Remember, the greater the potential difference between VCC and the virtual ground of the op amp, the wider the analog steps and easier it will be for an ADC of a microcontroller to discern each value from the others.
Fabricate the PCBHere you have the option of either taking my offered design and fabricating a PCB from it or you may modify it however you wish beforehand. There are some great instructables that cover PCB fabrication in the home, so I won't repeat any of that here. When you are done with this step, you should have a small double-sided PCB with bright and shiny copper traces that are just waiting for you to tin and solder chips onto.
Solder ComponentsYou can see from the BOM, that the three ICs are all PTH package (ie through-hole) while all the resistors used in the ladder are 0805 SMD. If you haven't entered the foray into SMD soldering now is your chance. The 0805 package SMDs are small but quite easy to work with if you use some tweezers and take your time. It helps if the copper traces are lightly tinned as then most all it takes is to place one side of the resistor onto a hot pad, then push down from the top with your tweezers while you solder the other side. You should get a nice satisfying "click" as it seats onto the pad. Of course, resistors are not polarized so it doesn't matter what direction you solder them in.
I inserted all ICs into their own sockets, but don't feel you have to do this. I just did it so I could pull out the ICs and use them again later. If you prefer, just socket them straight onto the PCB. Also, I ran all the signal and power traces out to a pretty non-standard PTH footprint. I'm not sure why I did this, but in the newest revision of the schematic and board file, I ran the traces out to a header. So, if you see a discrepancy between the images here and the schematic, that's why.
Experiment and Play
Now that you have finished building your R/2R DAC it's time to put it to some use and analyze its accuracy. If you're using a multimeter to read the analog output value then it's probably easiest to do this by having your microcontroller change the digital input but very slowly so the analog signal gets some settling time to be read by your multimeter.
Congratulations, you now have a working, high-resolution custom-build DAC!