17  DAC and PWM Output

In 60 Seconds

DACs (Digital-to-Analog Converters) reverse the ADC process by converting digital numbers back into analog voltages, enabling microcontrollers to control motors, dim LEDs, and generate audio. Most microcontrollers lack true DACs and instead use PWM (Pulse Width Modulation) – rapidly toggling a pin on and off where the duty cycle determines the average output voltage. Choose a true DAC for precision applications like audio, and PWM for LED dimming and motor control where inherent filtering smooths the output.

Key Concepts
  • DAC (Digital-to-Analog Converter): Converts a digital number to a proportional analog voltage; output = (digital_value / 2^N) x Vref; used for audio output, analog reference generation, and variable voltage control in IoT systems
  • PWM as a Low-Cost DAC Alternative: A PWM signal filtered through an RC low-pass filter produces a smoothed analog voltage proportional to duty cycle; effectively a 1-bit DAC with the filter providing averaging; low cost but limited bandwidth and added ripple
  • PWM Ripple: The residual AC component on a PWM-derived analog voltage caused by incomplete filtering; ripple voltage = Vcc x (1 - duty_cycle) x e^(-T/(RC)); reduced by larger RC time constant but at the cost of slower response time
  • DAC Resolution: The smallest output voltage step = Vref / 2^N; a 12-bit DAC with 3.3 V reference resolves 0.8 mV per step; ESP32 has a built-in 8-bit DAC (GPIO 25, 26) providing 256 steps (12.9 mV per step at 3.3 V)
  • Voltage Reference: The reference voltage determining the DAC output range; a stable, low-noise voltage reference (LM4040, LM336) is essential for accurate DAC output; using the noisy MCU VCC as reference introduces supply noise into the DAC output
  • R-2R Ladder DAC: A passive resistor network implementing a DAC using only two resistor values (R and 2R); can be built from standard resistors to create a simple N-bit DAC from N GPIO pins; popular for low-cost audio and control applications
  • PWM Frequency vs. Ripple Trade-off: Higher PWM frequency with the same RC filter produces less ripple but the filter must still be designed for the application; typical trade-off: use 20-100 kHz PWM with a suitable RC filter to achieve smooth DC output with acceptable response time
  • Output Impedance: The DAC’s internal resistance seen from its output terminal; a high output impedance causes voltage drop when current is drawn by the load; buffer the DAC output with a unity-gain op-amp for low-impedance drive capability

17.1 Learning Objectives

By the end of this section, you will be able to:

  • Explain DAC Operation: Describe how digital-to-analog converters translate binary values into proportional voltages
  • Apply DAC Formulas: Calculate output voltage from digital input using the DAC transfer equation
  • Implement PWM Output: Generate pulse width modulation signals as pseudo-analog output for actuator control
  • Design RC Filters: Compute component values for low-pass filters that convert PWM to smooth analog voltage
  • Interface Actuators: Wire motors, LEDs, and other analog loads to DAC and PWM outputs
  • Evaluate DAC vs PWM Tradeoffs: Select the appropriate output method based on application requirements and constraints

While ADCs translate sensor signals into numbers a computer can read, DACs do the reverse – they turn digital numbers back into smooth voltages that can control things like speakers and motors. Most microcontrollers use a shortcut called PWM instead, which rapidly flickers power on and off. To a motor or LED, this flickering feels like a steady, adjustable voltage because it happens too fast for them to notice the individual pulses.

17.2 Prerequisites

Before diving into this chapter, you should be familiar with:


17.3 Digital-to-Analog Converters (DAC)

DAC = Device that converts digital numbers into analog voltage

Block diagram showing the DAC conversion pipeline: digital binary input passes through a DAC to produce a proportional analog voltage output
Figure 17.1: DAC Conversion Process: Digital Binary to Analog Voltage

17.3.1 DAC Formula

\[V_{out} = V_{ref} \times \frac{Digital\ Input}{2^n - 1}\]

Example (8-bit DAC, Vref = 5V):

Digital Input Calculation Voltage Output
0 5 x (0/255) 0.00 V
64 5 x (64/255) 1.25 V
128 5 x (128/255) 2.51 V
192 5 x (192/255) 3.76 V
255 5 x (255/255) 5.00 V

For an 8-bit DAC with \(V_{ref} = 5\) V, the step size (resolution) is \(V_{step} = V_{ref} / (2^n - 1) = 5 / 255 = 19.6\) mV. To output 3.0V, you need digital value \(D = \lfloor V_{out} \times (2^n - 1) / V_{ref} \rfloor = \lfloor 3.0 \times 255 / 5 \rfloor = 153\). Actual output is \(V_{actual} = 153 \times 5 / 255 = 3.0\) V exactly. With a 12-bit DAC (\(2^{12} - 1 = 4095\)), step size shrinks to \(5 / 4095 = 1.22\) mV – 16× finer than 8-bit, enabling smooth audio waveforms where 8-bit would sound grainy.

17.3.2 DAC Applications in IoT

Application Example DAC Type
Audio Output Music playback 12-16 bit, 44.1 kHz
Motor Speed Control PWM alternative 8-10 bit
LED Brightness Smooth dimming 8-12 bit
Analog Sensor Simulation Testing 12 bit
Waveform Generation Signal generator 12-16 bit

17.4 DAC Circuit Architecture

R-2R resistor ladder DAC circuit diagram showing binary-weighted resistor network with operational amplifier output stage converting digital input bits to proportional analog voltage
Figure 17.2: Digital-to-Analog Converter circuit diagram

R-2R Ladder Network:

  • Uses only two resistor values (R and 2R)
  • Each bit contributes proportional current
  • Binary-weighted output voltage
  • Low cost, moderate accuracy

17.5 Quantization Error in DAC

Problem: DAC output is not truly analog - it’s discrete steps

Quantization Error = Difference between ideal smooth output and actual stepped output

Reducing Error:

  1. Increase bit depth (8-bit → 12-bit → 16-bit)
  2. Increase update rate (faster DAC updates)
  3. Add filtering (low-pass filter smooths steps)

17.6 True DAC vs PWM Comparison

Tradeoff: True DAC Output vs PWM Pseudo-Analog

Option A (True DAC - ESP32 GPIO25/26, MCP4725):

  • Produces genuine smooth analog voltage with no ripple
  • Output impedance varies: <1 ohm for external DACs with op-amp output (e.g., MCP4725), ~10 kohm for ESP32 built-in DAC
  • External DACs can drive resistive loads directly; ESP32 built-in DAC needs a buffer op-amp for low-impedance loads
  • Ideal for audio (SNR >90 dB achievable with external 16-bit+ DACs; ESP32 8-bit DAC limited to ~50 dB theoretical max) and precision voltage reference
  • ESP32 DAC resolution 8-bit (256 levels), MCP4725 offers 12-bit (4096 levels)
  • Cost: $0 (ESP32 built-in) to $3-8 (external DAC)
  • Consumes 0.5-5mA continuous

Option B (PWM Pseudo-Analog - Any GPIO):

  • Digital square wave filtered to approximate DC
  • Requires external RC filter (adds latency = 5x RC time constant)
  • Output ripple typically 2-10% of amplitude
  • Suitable for LED dimming and motor speed control where high-frequency switching is acceptable
  • ESP32 offers 1-16 bit PWM resolution; max frequency depends on resolution (e.g., ~312 kHz at 8-bit, ~1.2 kHz at 16-bit)
  • Cost: $0.05 (RC filter components)
  • Consumes <0.1mA average for low duty cycles

Decision Factors: Choose true DAC when driving audio amplifiers, generating test signals, providing reference voltages, or interfacing with analog-input devices sensitive to ripple. Choose PWM when controlling inductive loads (motors inherently filter PWM), dimming LEDs (human eye cannot perceive >100Hz flicker), or when all DAC pins are already used. Note: ESP32 has only 2 DAC channels but 16+ PWM-capable GPIOs, making PWM more flexible for multi-channel applications.


17.7 Arduino DAC/PWM Implementation

17.7.1 Arduino Uno (No True DAC)

Solution: Use PWM (Pulse Width Modulation) to simulate analog output

PWM Pins: 3, 5, 6, 9, 10, 11

// Fade LED using PWM (simulated DAC)
const int ledPin = 9;  // PWM-capable pin
int brightness = 0;

void setup() {
    pinMode(ledPin, OUTPUT);
}

void loop() {
    analogWrite(ledPin, brightness);  // 0-255
    brightness = (brightness + 5) % 256;
    delay(30);
}

PWM Characteristics:

  • Resolution: 8-bit (0-255)
  • Frequency: ~490 Hz (pins 3,9,10,11) or ~980 Hz (pins 5,6)
  • Not true analog but works for LEDs, motors

17.7.2 ESP32 (True DAC)

DAC Pins: GPIO25, GPIO26

// True analog output on ESP32
void setup() {
    // No setup needed for DAC
}

void loop() {
    // Output ~1.66V on DAC channel 1 (GPIO25)
    dacWrite(25, 128);  // 0-255, Vref = 3.3V
    // 128/255 * 3.3V = 1.66V
}
Try It: ESP32 DAC Output Simulation

Experience true analog output with the ESP32 DAC in Wokwi:

Challenge: Generate a smooth voltage sweep from 0V to 3.3V

Steps:

  1. Add code in the loop: dacWrite(25, value) where value sweeps from 0 to 255
  2. Connect GPIO25 to an LED with 220Ω resistor (observe smooth brightness change)
  3. Verify the voltage formula: \(V_{out} = \frac{value}{255} \times 3.3V\)
  4. For value=128: \(V_{out} = \frac{128}{255} \times 3.3V \approx 1.66V\) (measure with multimeter in simulation)
  5. Compare this smooth DAC output to PWM’s rapid on/off switching

What to observe: True DAC provides genuine analog voltage with no high-frequency switching, ideal for audio and precision applications where PWM ripple would cause problems.


17.8 PWM as Pseudo-DAC

Most microcontrollers lack true DACs but use PWM (Pulse Width Modulation) to simulate analog output.

How PWM Works:

  • Rapidly toggle digital output between 0V and 5V
  • Duty cycle (% time HIGH) determines average voltage
  • Low-pass filter smooths PWM to quasi-analog signal

PWM Formula:

\[V_{average} = V_{high} \times \frac{\text{Duty Cycle}}{100\%}\]

Example: 50% Duty Cycle at 5V

\[V_{average} = 5V \times 0.5 = 2.5V\]

PWM Specifications:

Parameter Arduino Uno ESP32 Typical Use
Resolution 8-bit (0-255) 8-16 bit Motor speed, LED dimming
Frequency 490-980 Hz 1 Hz - 312 kHz (8-bit) Audio requires >20 kHz
Channels 6 16 Multiple motors/LEDs

17.8.1 Interactive: PWM & DAC Calculator

Use the sliders below to explore how duty cycle, supply voltage, and DAC input value affect output voltage.

PWM Duty Cycle & DAC Output Calculator

17.9 PWM to Analog Conversion (RC Filter)

For smooth analog output, add RC low-pass filter:

\[f_{cutoff} = \frac{1}{2\pi RC}\]

Example: Smoothing 1 kHz PWM for motor control

  • Choose \(f_c\) = 100 Hz (10x below PWM frequency)
  • Use R = 10k ohm, solve for C:

\[C = \frac{1}{2\pi \times 10000\Omega \times 100\text{Hz}} = 0.159\mu\text{F} \approx 0.22\mu\text{F}\]

Result: 0.22uF capacitor with 10k ohm resistor converts 1 kHz PWM to smooth analog voltage.

RC Filter Design Guidelines:

  • f_cutoff should be 10-20x below PWM frequency
  • Higher cutoff = faster response, more ripple
  • Lower cutoff = slower response, smoother output
  • Settling time = 5 x RC (to reach 99% of target)

17.9.1 Interactive: RC Filter Design Calculator

RC Low-Pass Filter Calculator for PWM Smoothing

17.10 Hands-On Labs

17.10.1 Lab 1: DAC Output with ESP32

Objective: Generate analog voltages using ESP32’s built-in DAC.

Materials:

  • ESP32 development board
  • LED with 220 ohm resistor
  • Multimeter
  • Jumper wires

Circuit:

  • DAC output: GPIO25 or GPIO26
  • LED anode → 220 ohm resistor → GPIO25
  • LED cathode → GND

ESP32 Code:

void setup() {
    // DAC channels: 25 and 26
    Serial.begin(115200);
}

void loop() {
    // Sweep from 0V to 3.3V
    for (int i = 0; i <= 255; i += 5) {
        dacWrite(25, i);  // 8-bit DAC (0-255)

        float voltage = (i / 255.0) * 3.3;
        Serial.print("DAC Value: ");
        Serial.print(i);
        Serial.print(" | Voltage: ");
        Serial.print(voltage);
        Serial.println("V");

        delay(100);
    }
}

Measurements:

  • Use multimeter to verify output voltage
  • Observe LED brightness changes smoothly
  • Calculate: V_out = (DAC_value / 255) x 3.3V

Expected Learning:

  • DAC converts digital to analog
  • 8-bit resolution (256 steps)
  • Smooth voltage transitions

17.10.2 Lab 2: PWM LED Dimming with Arduino

Objective: Use PWM to smoothly dim an LED and observe the relationship between duty cycle and perceived brightness.

Materials (or simulate in TinkerCAD / Wokwi): - Arduino Uno - 1x LED (any color) - 1x 220 ohm resistor - Jumper wires

Circuit:

  • LED anode → 220 ohm resistor → Pin 9 (PWM)
  • LED cathode → GND

Arduino Code:

const int ledPin = 9;  // PWM pin

void setup() {
    pinMode(ledPin, OUTPUT);
    Serial.begin(9600);
}

void loop() {
    // Sweep brightness up
    for (int duty = 0; duty <= 255; duty += 5) {
        analogWrite(ledPin, duty);

        float dutyCyclePct = (duty / 255.0) * 100.0;
        float avgVoltage = (duty / 255.0) * 5.0;

        Serial.print("PWM: ");
        Serial.print(duty);
        Serial.print(" | Duty: ");
        Serial.print(dutyCyclePct, 1);
        Serial.print("% | V_avg: ");
        Serial.print(avgVoltage, 2);
        Serial.println("V");

        delay(50);
    }

    // Sweep brightness down
    for (int duty = 255; duty >= 0; duty -= 5) {
        analogWrite(ledPin, duty);
        delay(50);
    }
}

Expected Learning:

  • PWM duty cycle controls average voltage and perceived brightness
  • 8-bit resolution gives 256 brightness levels
  • Human eye perceives brightness logarithmically, so linear PWM steps appear nonlinear

17.11 Common Pitfalls

Pitfall: Confusing DAC Resolution with Output Accuracy

The Mistake: Assuming an 8-bit DAC with a 3.3V reference produces exact voltages at every step (e.g., expecting exactly 1.650V for value 128).

Why It Happens: The formula \(V_{out} = V_{ref} \times D / (2^n - 1)\) gives the ideal voltage, but real DAC output is affected by integral nonlinearity (INL), differential nonlinearity (DNL), offset error, and gain error. An 8-bit DAC has 12.9 mV steps at 3.3V, but typical INL of +/-1 LSB means actual output can deviate by +/-12.9 mV from the ideal.

The Fix: Check the DAC IC datasheet for INL and DNL specifications. For precision applications, use a higher-resolution DAC (12-bit or 16-bit) and calibrate against a known reference voltage. ESP32 built-in DAC has approximately +/-1% accuracy without calibration.

Rule of Thumb: Usable accuracy is typically 2-3 bits fewer than advertised resolution once all error sources are combined.

Pitfall: PWM Frequency Too Low for the Application

The Mistake: Using the default Arduino PWM frequency (490 Hz on most pins) for motor control, resulting in audible motor whine, or for LED dimming causing visible flicker in video recordings.

Why It Happens: The default frequency is a compromise that works for basic demos but is too low for many real applications. Cameras recording at 30-60 fps can capture individual PWM cycles, and human hearing extends to ~20 kHz.

The Fix: Increase PWM frequency to match the application: - LED dimming: >200 Hz for flicker-free to human eye; >1 kHz for flicker-free on camera - DC motor control: >20 kHz (ultrasonic) to eliminate audible whine - Servo motors: Fixed at 50 Hz (industry standard), do not change

On ESP32, use ledcSetup(channel, freq, resolution) to set custom PWM frequency. On Arduino Uno, modify timer prescaler registers.

Rule of Thumb: Use the highest PWM frequency your hardware supports, keeping in mind that higher frequency reduces effective resolution.


DACs are like translators who speak the language of motors and lights!

17.11.1 The Sensor Squad Adventure: The Reverse Translator

Max the Microcontroller had a new challenge. “I know the motor needs to spin at 50% speed, and I can think in numbers like 128 out of 255. But the motor only understands smooth voltage, not step-numbers!”

Lila the LED agreed. “Same for me! I want to glow at half brightness, but I need a smooth amount of power, not a number!”

That is when DAC Danny showed up. “I am the opposite of ADC Andy! Andy translates smooth signals INTO numbers for Max. I translate numbers FROM Max back into smooth signals for motors and LEDs!”

Bella the Battery was impressed. “So you are a reverse translator!”

Danny smiled. “Exactly! When Max says 128, I convert that into 1.65 volts – just the right amount to make Lila glow at half brightness.”

But Sammy the Sensor noticed something. “Wait, Danny, you are not on every microcontroller. What happens when you are not around?”

Danny pointed to his friend PWM Pete. “Pete has a clever trick! He blinks the power ON and OFF really, really fast. If he is ON half the time and OFF half the time, the average power is 50% – and it happens so fast that Lila cannot even tell she is blinking!”

Lila blinked. “I had no idea! I thought I was glowing smoothly this whole time!”

17.11.2 Key Words for Kids

Word What It Means
DAC A reverse translator that turns numbers into smooth voltage
PWM Blinking power ON and OFF so fast it looks smooth
Duty Cycle How much of the time the power is ON (50% = half the time)
Motor Control Changing how fast a motor spins using voltage
LED Dimming Making a light brighter or dimmer

17.11.3 Try This at Home!

The Blinking Brightness Game!

  1. Get a flashlight and a dark room
  2. Turn the flashlight ON for 1 second, then OFF for 1 second. Repeat. (That is 50% duty cycle – but you can SEE the blinking!)
  3. Now try blinking it ON for half a second, OFF for half a second. Faster!
  4. Keep going faster and faster until you cannot see the blinks anymore

What you learned: When blinking is fast enough, your eyes blend it into steady light. That is exactly how PWM works – it blinks so fast (hundreds of times per second) that LEDs and motors respond smoothly!

How It Works: ESP32 DAC Converting Digital 200 to Analog 2.59V

The big picture: A DAC is the reverse of an ADC - it uses an R-2R resistor ladder to convert an 8-bit digital value (0-255) into a proportional analog voltage (0-3.3V).

Step-by-step breakdown:

  1. Digital Input: Code calls dacWrite(25, 200) - 200 in binary is 11001000 - Real example: ESP32 GPIO25 DAC receives this 8-bit value
  2. Resistor Ladder: Each bit switches a 2R resistor to either Vref or ground, creating weighted currents - Real example: Bit 7 (MSB) contributes Vref/2 = 1.65V, bit 6 contributes Vref/4 = 0.825V, and so on with each successive bit halving
  3. Summing Amplifier: Op-amp sums all bit contributions to produce output voltage - Real example: V_out = 3.3V × (200/255) = 2.59V

Why this matters: Understanding that PWM average voltage (3.75V at 75% duty cycle) requires RC filtering to become smooth DC explains why motors work with PWM directly (coil inductance acts as filter) but audio needs a true DAC.

Concept Relationships: DAC/PWM and Actuator Control
Concept Relates To Relationship
DAC Resolution (8-bit) ADC Resolution Same 2^n formula - 8-bit DAC has 256 output levels, 12-bit ADC has 4,096 input levels
PWM Duty Cycle Motor Speed Control Average voltage = V_high × duty_cycle - motors respond to average, not individual pulses
RC Filter Cutoff Frequency Sampling Theory Filter fc should be 10× below PWM frequency to smooth ripple (inverse of Nyquist)

Cross-module connection: PWM Actuator Control - Explains how DC motors respond to PWM average voltage via back-EMF and inductance

Key Takeaway

DACs and PWM are the two main ways IoT microcontrollers produce analog-like output signals for actuator control. True DACs provide smooth voltage output ideal for audio and precision applications, while PWM offers a flexible, cost-free alternative for LED dimming and motor speed control available on every GPIO pin. Understanding the tradeoffs between these approaches is essential for designing effective IoT actuator interfaces.

Use this decision table to choose the right output method based on your application requirements.

Application Requirement True DAC PWM Recommended Choice
Audio output (music, voice) ✓ Smooth analog, >90dB SNR possible ✗ High-frequency ripple audible as hiss DAC — Audio requires clean signals
LED brightness control ✓ Flicker-free at any frequency ✓ Flicker-free above 100 Hz PWM — Saves DAC pins, perceptually identical
DC motor speed control ✓ Smooth speed, no torque ripple ✓ Motor inductance filters PWM naturally PWM — Motor coils act as low-pass filter
Servo motor positioning ~ Acceptable but not standard ✓ Industry standard 50 Hz PWM signal PWM — Servos expect PWM input (1-2 ms pulse width)
Precision voltage reference ✓ Stable DC output, <1 mV noise ✗ Ripple voltage 2-10% even with RC filter DAC — Reference voltages must be clean
Analog sensor simulation (testing) ✓ Can mimic smooth sensor output ~ Only for slowly-changing signals DAC — Faster signals need true analog
Multi-channel output (8+ channels) ✗ Most MCUs have only 1-2 DAC pins ✓ Every GPIO can generate PWM PWM — Scalability advantage
Battery-powered application ~ Consumes 0.5-5 mA continuous ✓ <0.1 mA average at low duty cycles PWM — Lower average current

Key Decision Factors:

Choose True DAC When:

  1. Signal purity matters: Audio, instrumentation, reference voltages
  2. High-frequency content: Signals faster than 1 kHz with harmonics
  3. Interfacing with analog circuits: Op-amps, comparators expecting DC levels

Choose PWM When:

  1. Inductive loads: Motors naturally filter high-frequency switching
  2. Human perception: LED dimming (eye can’t see >100 Hz flicker)
  3. Pin scarcity: Need 4+ analog outputs but MCU has only 1-2 DAC channels
  4. Power efficiency: Low duty cycles consume minimal current

Real-World Example: Smart Lighting System

Output Channel Load Method Used Reasoning
Channel 1-8 (RGB LEDs) 8× RGB strips PWM @ 1 kHz Human eye can’t detect flicker, saves DAC pins
Channel 9 (Audio alert) Piezo buzzer DAC @ 44.1 kHz Generates smooth tones, PWM would sound harsh
Channel 10 (Fan speed) 12V DC fan PWM @ 25 kHz Ultrasonic frequency eliminates motor whine

Cost Comparison:

  • Option A (All True DACs): 10× MCP4725 DACs @ $4 each = $40
  • Option B (Hybrid): 1× MCP4725 (audio) + 9× PWM (free GPIOs) = $4
  • Savings: $36 by using PWM where perceptually/functionally equivalent

Rule of Thumb: Start with PWM for actuators (motors, LEDs, heaters). Only use true DAC when you observe problems (audible noise, instability, ripple voltage) or need to interface with analog circuitry expecting clean DC.

17.12 See Also

17.13 Summary

This chapter covered Digital-to-Analog Converters (DACs) and PWM output for actuator control:

  • DAC Operation: Converts digital values to proportional analog voltage
  • DAC Formula: V_out = Vref x (Digital Input / (2^n - 1))
  • DAC Applications: Audio, motor control, LED dimming, waveform generation
  • PWM as Pseudo-DAC: Duty cycle determines average voltage
  • RC Filtering: Converts PWM to smooth analog (f_cutoff = 1/(2piRC))
  • True DAC vs PWM: True DAC for precision, PWM for flexibility
  • Arduino/ESP32: Arduino uses PWM, ESP32 has true DAC on GPIO25/26

Understanding DAC and PWM is essential for controlling actuators in IoT systems.

17.14 What’s Next?

You’ve completed the Analog and Digital Electronics series! You now have the complete hardware foundation for IoT sensor and actuator interfaces.

Chapter Topic Why It Matters
Analog and Digital Electronics Overview Series overview Return to the full electronics series index
ADC/DAC Worked Examples Practical calculations Apply DAC and PWM formulas to real-world design problems
PWM Actuator Control Motor and LED control Hands-on PWM for DC motors, servos, and LED dimming
Sensor Circuits and Signals Sensor interface circuits Connect DAC/ADC knowledge to complete sensor signal chains
Networking Basics Introduction Module 3: Networking Discover how IoT devices connect and communicate over networks
Energy-Aware Power Analysis Power budgets Factor in DAC current (0.5-5 mA) vs PWM average current for battery life