Note: added some more photos for clarification.
https://hackaday.com/2022/12/11/a-straightforward-old-fashioned-dac/
1. Schematic
The assembly consists of two CD4007UBE, working as inverters/switches (switches are one inherent feature of R-2R ladder DACs).
CD4007A is given in my book source, which has lower max voltage but is the faster version (30ns vs 20ns; one has to be aware of the general rule not using a faster logic family than necessary because of noise problems). 2R = 100k +/- 1%.
2. Programming
MicroPython program for an ad-hoc test, generating digital output on a Pi Pico (ought to generate 2.5V):
from machine import Pin lsb = Pin(7, Pin.OUT) # bit0, least significant bit bit1 = Pin(8, Pin.OUT) bit2 = Pin(9, Pin.OUT) bit3 = Pin(10, Pin.OUT) bit4 = Pin(11, Pin.OUT) msb = Pin(12, Pin.OUT) # bit5, most significant bit (2^5 = 32) lsb.high() bit1.high() bit2.high() bit3.high() bit4.low() msb.low()
For more sophisticated applications one can deploy the RP2040 Single-cycle IO block (SIO).
C program would look something like (also ought to generate 2.5V, 001111 is 15d):
(...)
void setOutput(int DAC)
{
*(SIO + 0x014 / 4) = DAC << 7; // we start on GP7
}
(...)
setOutput(15ul);
(...)
3. Using an I2C bus I/O expansion
Expending six Pico GPs (or more) may be rather impractical for some projects.
The I2C bus would need only two connections, so one can go with an additional I2C IC, such as the MCP23016 I/O expansion.
A code example for a simple sawtooth generator is uploaded to my github repo.
4. Applications
SAR ADC, function generator, sound generator, etc.
5. Costs
I paid 50 Cents for each IC, and a few Cents for the resistors. MCP23016 was about 2€.
If you load in the mA range the output voltage driving the resistors will droop depending on the MCU (and which pins and whether you have configured for "high drive" mode).
I already contributed a DAC project which avoids the resistors by using the transconductance of CMOS gates.