Once again, a thread from the Arduino forum, this time the 2-cent DAC thread from forum user “raalst” inspired me to follow up on a thought I got – to utilize the high-Z state of the digital outputs for an increased resolution of a resistor ladder / network type DAC.
To figure this out, it quickly became apparent that the pen-and-paper method was a bit too cumbersome. Hence I made a little program to help me determine this – RL-DAC.
Basically it is a simple program to test different resistor values with a few different resistor topologies.
In the slim, off-beat chance you would like to test it too, there is a download link at the bottom of this post. Just keep in mind this program has a very narrow use, and was mostly made for my “theoretical experimentation”.
Btw since making this, I got a new found admiration of Mr. Thevenin’s method!
Because of the resistor input method used (logarithmic sliders), I couldn’t hit the exact value used for the resistors, but the difference is not really that much.
Also, it doesn’t take other effects like capacitive loading into account – not that I think there are much of that in my simple tests. It’s just a pure resistive calculator.
The solution found was (almost embarrassingly) simple, but it doesn’t come without cost in the form of being pretty slow, and also requiring more and more precise resistances with more bits, more so than binary ladders with the same nr of bits.
My proof-of-concept code for the Arduino is not optimized at all (it is really slow), I know I could have used timer interrupts and direct port access, but I wanted to keep it simple.
Atmega output resistance
I also found that using an output resistance from the Arduino of about 25 ohms seemed to fit best when overlaying screenshots from RL-DAC with photos from the scope.
This seems to agree with the datasheets for the Atmega 328, which states an almost 0.5V drop for an output sink or source current of 20mA, equalling almost 25 ohms. I use a little larger current, so this seems to fit well. (page 412, “Pin driver strength”, of the datasheet for atmega 48/88/168/328).
Ok, enough about that. On with the tristate DAC.
A resistor ladder DAC is a cheap and easy way of getting a digital signal converted to an analog one. But the required accuracy for the resistors quickly raises with more bits. Using 5% resistors won’t get you many bits, for example. In fact I think 4 bits for a binary ladder is about the limit for that example (2^4 = 16 steps, and LSB is 1/16th or 6.25% of the total, hence the MSB resistor tolerance should be quite a bit better than this really).
Also see the Wikipedia article about resistor ladders.
To compare with the trinary resistor ladder further below, there are two main types of binary resistor ladders (that I know of anyway).
First the well-known R-2R type ladder:
Where there are only 2 values used for the resistances, R and 2R. Also, the output resistance is constant, at R ohms.
Then there is another type, the binary weighted “ladder”:
Where each resistor increases two-fold compared to the one before it (or rather after it, as it starts from the MSB bit). Output resistance is also constant (equal to all resistors in parallel).
Also, there is a subtle difference between the two: An R-2R ladder output is never fully equal to Vcc, but a binary weighted ladder can be. Both have the same nr. of steps, and both begins at 0 volts for the lowest value.
The trinary resistor ladder:
Utilizing the high-Z state individually on each output, one would get 3^n values instead of the usual binary of 2^n for an n-bit output:
n outputs : 1, 2, 3, 4, 5…
Binary : 2, 4, 8, 16, 32…
Trinary : 3, 9, 27, 81, 243…
So the resolution quickly increases compared to binary.
I’ve come to realise that a trinary weighted ladder would look something like this:
Where each resistor increases three times to the one after it
Ri = R * 3^(n-i-1)
R is some baseline resistance.
n is the number of bits in the DAC (or inputs).
i is the index, thus n-i-1 is counting from MSB (0), to LSB (n-1), in an n-bit digital output. IE its counted backwards.
However, a tristate digital output does not have a trinary-type output, even though I use a trinary counting. As for counting, I decided on using:
- 0 – same as binary 0 – 0 volt
- 1 – the high-Z state
- 2 – same as binary 1 – IE Vcc.
Now to the really simple solution:
In (an almost) perfect analogy to the binary weighted resistor ladder above, I found that by adding a resistor divider on each input, effectively converting the high-Z state to the intermediary (Vcc/2) state and thus effectively making a (almost) trinary output, one can still make a trinary weighted resistor ladder:
But, the outputs have a limited max current they can be loaded with, and resistors for the resistor dividers on each digital output cannot be too low (unless some buffer stage is implemented – see below note).
For my quick tests, up to 3 bits are fairly easy (linear), with 4 bits there is a noticeable jump at 1/3 and 2/3, unless carefully adjusting the MSB resistor dividers (Also, I just used 5% resistors for the two MSB bits) This improved when I swapped those to a lower value. But I dare not go too low to not over-stress the digital output of my dear Arduino clone. I used 180 ohm resistor dividers for most outputs, and went to 165 ohms (two 330 ohm in parallel) for the MSB. Even though the lowest MSB output resistor (not to be confused with the resistor dividers) was an order of magnitude larger, at 3.33 k ohm (three 10k in parallel).
As stated the increase in resistance quickly builds up with more bits. So this ladder is even more troubled with requiring smaller and smaller required resistor tolerances as the bit-depth increases, than the binary counterpart (for an equal nr. of bits).
For lack of a digital storage oscilloscope, the combo of a digital camera and old analogue scope is quite handy!
A test with the scope pretty much confirms the theory (Ok, admittedly, it could be the other way around since I also used the scope to debug RL-DAC… A sort of an anti-catch-22(?)-kind of statement As it sort of has to be consistent then. But I’m pretty confident the calculations are correct nevertheless (no guarantees though)).
Anyway, here are some shots of my oscilloscope, mostly overlaid with screen shots of RL-DAC’s prediction, of course scaled to fit the scope’s scale.
Same with no overlay. The “jumps” at 1/3rd and 2/3rd position is very visible, as well as the ones at n/9th parts. Lowering the resistor dividers would help, but as stated I dared not have these any smaller to not over-stress the digital outputs. A buffer of some kind would probably help. As well as raising the output (or DAC input) resistors, but they quickly become very high with more bits anyway..
Also, as can be seen, the output is fairly noisy from the state and pinmode shifting of the DAC.
Then a couple of sine wave tests, also with an RC-filter on channel 2 to smooth and filter away the high-frequency noise from the tri-state DAC shifting states.
There are other resistor ladders to be found (I’m sure), which I also have done, but they are not as linear as this simple one.
The R-2R ternary-test
While the ternary weighted resistors was easy enough, I initially thought an R-2R type ladder was not useful for other than to test (and debug ) RL-DACs calculations. I was wrong. Some later web searches revealed that an R2-R type ladder indeed is feasible with a ternary output (and RL-DAC can also calculate this). The Trouble was finding the right proportions of the resistors.
In fact there is a paper made in 1979, by Takeo Miyata, Katsuyoshi Tamagawa and Takeshi Watahiki, describing such a circuit (so I’m only, what, 32-ish year too late ).
I found it here: Ternary-to-analog converters using resistor ladders
Instead of R-2R, the proportions have three values at R, 4/3 * R, and 2R. Another way to put it is maybe a 3R-4R-6R ladder.
As an example see the below schematics. The highlighted red resistors are just my input dividers, the quick’n'dirty way of clamping the high-Z state to Vcc/2. In a practical test, do not have them this low! No scope overlay is shown as I write this about a year later, and don’t have it set up atm.
Anyway, on with my original useless R-2R-ish tests. Note: this is an ordinary binary type R-2R ladder fed with a ternary output (so not very useful, other than for debugging really). If I had used the aforementioned 3R-4R-6R ladder, the output would again be linear.
Addendum – DAC output buffer
This is a quick sketch of a possible output buffer for the digital outputs, basically made after a little discussion on the Arduino forum (not testet atm). I have briefly touched the possibility of using a buffer stage earlier, but it would also add to the complexity of the circuit. Which may or may not be needed.
Btw I think it would be better to have the voltage divider resistors more than 1k, like 10k or so. Also, the DAC output should be buffered as well (not shown).
The Arduino proof-of-concept code:
RL DAC test 0.08
Note: this is nothing special, and not optimized at all. I don’t have any schematics as of now, but here is a short explanation:
It can do 2 modes; binary or trinary, toggled by the active-low button at Arduino digital pin 3.
The generator also have 2 modes: sine wave or ramp-up, toggled by the active-low button at Arduino pin 2
For output pins I have pin 4 (MSB), 7, 8 and 12 (LSB).
To use the binary mode, a different resistor schematics (for a binary output, of course) should be used.
Note: The sine wave from this version is slightly different from the one shown (less detailed, I think).
Lastly, my RL-DAC software. Intended to be used from within the processing environment (but it also contains Windows executables, as well as for Linux and Mac).
As stated, this program have a very narrow use. Mostly made for my “theoretical experimentation” of the resistor ladders, but it’s there if you want to take a look at it.
An alternate download link can be found on my google code page, as well as a brief description.
Processing can be downloaded from here: http://www.processing.org/
Ok. I guess that’s it.
Until next time,
2012, October 17th: Updated images from new version of RL-DAC, changed text a bit
2012, April 15-17th: Fixed some errors (Thanks to TomF’s comment below), removed reference to fractals, (hopefully) improved the text a bit.