Skip to content
Home » Embedded Systems » ADC and DAC in Microcontrollers: Converting Between Analog and Digital

ADC and DAC in Microcontrollers: Converting Between Analog and Digital

ADC and DAC in Microcontrollers featured image with dark green background, HARDWARE badge, A/D icon in green circle, and Analog to Digital Conversion subtitle by nerdyelectronics.com
Sensors for Embedded Systems
Part 10 of 18View Full Path →

KEY TAKEAWAYS

  • ADC converts analog signals (sensor voltages) to digital values the microcontroller can process
  • ADC resolution (8, 10, 12 bits) determines the number of discrete levels: 2^n possible values
  • DAC converts digital values back to analog voltages for driving analog outputs
  • Sampling rate must be at least twice the signal frequency (Nyquist theorem) for accurate conversion

The Analog-Digital Gap

What is a DAC in a microcontroller, and how does it differ from an ADC?

The physical world is analog. Temperature, light, pressure, and sound all vary continuously. But microcontrollers are digital: they work with discrete binary values (0s and 1s). To bridge this gap, we use:

  • ADC (Analog-to-Digital Converter) – Reads analog voltages and converts them to digital numbers the MCU can process
  • DAC (Digital-to-Analog Converter) – Takes a digital number and produces a corresponding analog voltage
Analog World          Microcontroller          Analog World
(sensors)             (digital processing)      (actuators)

Temperature ──[ADC]──> Process ──[DAC]──> Audio output
Light       ──[ADC]──> Calculate          Motor speed (via PWM)
Pressure    ──[ADC]──> Decide             Analog meter

ADC (Analog-to-Digital Converter)

How ADC Works

An ADC measures the voltage on an input pin and converts it to a digital number proportional to a reference voltage.

Digital Value = (V_input / V_reference) * (2^resolution - 1)

Example (10-bit ADC, 3.3V reference, input = 1.65V):
  Digital Value = (1.65 / 3.3) * (1024 - 1) = 511

ADC Resolution

Resolution determines how many distinct values the ADC can output:

ResolutionLevelsStep Size (3.3V ref)Step Size (5V ref)Common In
8-bit25612.9 mV19.6 mVSimple MCUs
10-bit10243.22 mV4.88 mVArduino (ATmega328)
12-bit40960.81 mV1.22 mVSTM32, ESP32
16-bit655360.05 mV0.076 mVExternal ADCs (ADS1115)

Higher resolution means the ADC can detect smaller voltage changes. For example, a 12-bit ADC can distinguish voltages that differ by less than 1 mV, while an 8-bit ADC needs at least 13 mV difference.

Key ADC Parameters

Sampling Rate: How many conversions per second. A 1 MSPS (mega-samples per second) ADC takes 1 million readings per second. Audio needs at least 44.1 kHz. Temperature readings might only need 10 Hz.

Reference Voltage (Vref): The maximum voltage the ADC can measure. Input voltages above Vref give the maximum digital value. Voltages below 0V can damage the ADC.

Input Impedance: The ADC input has limited impedance. High-impedance sources (like some sensors) may need a buffer amplifier for accurate readings.

Reading an ADC: Code Example

// STM32 HAL example
#include "stm32f4xx_hal.h"

ADC_HandleTypeDef hadc1;

uint16_t read_adc(void) {
    HAL_ADC_Start(&hadc1);
    HAL_ADC_PollForConversion(&hadc1, 100);
    uint16_t value = HAL_ADC_GetValue(&hadc1);
    HAL_ADC_Stop(&hadc1);
    return value;
}

float adc_to_voltage(uint16_t adc_value) {
    return (adc_value / 4095.0f) * 3.3f;  // 12-bit, 3.3V ref
}

int main(void) {
    HAL_Init();
    // ... clock and ADC configuration ...

    while (1) {
        uint16_t raw = read_adc();
        float voltage = adc_to_voltage(raw);
        printf("ADC: %d, Voltage: %.3f V\n", raw, voltage);
        HAL_Delay(1000);
    }
}

Improving ADC Accuracy

  1. Averaging: Take multiple readings and average them to reduce noise.
    uint32_t sum = 0;
    for (int i = 0; i < 16; i++) {
        sum += read_adc();
    }
    uint16_t average = sum / 16;
  2. Decoupling capacitor: Place a 100nF capacitor between the ADC input and GND to filter high-frequency noise.
  3. Stable reference voltage: Use a dedicated voltage reference IC instead of relying on VCC.
  4. Avoid reading during noisy operations: WiFi transmissions, motor switching, and other noisy activities can affect ADC readings.

Troubleshooting Common ADC Problems

When ADC readings are inaccurate or unstable, these are the most common causes and solutions:

Reference Voltage Issues

  • Problem: ADC readings drift or are inconsistent across different power conditions
  • Cause: Using VCC as reference when VCC varies with load or battery level
  • Solution: Use a dedicated voltage reference IC (like TL431 or MAX6350) for stable Vref

Electrical Noise

  • Problem: ADC readings jump erratically or show high-frequency variations
  • Cause: Switching circuits, motors, or digital signals coupling into analog inputs
  • Solution:
    • Add 10-100nF capacitor directly at ADC pin to GND
    • Use twisted pair or shielded cables for analog signals
    • Separate analog and digital ground planes when possible
    • Take ADC readings when noisy circuits are idle

Source Impedance Mismatch

  • Problem: Readings are lower than expected or change based on sampling rate
  • Cause: High-impedance sensor (>10kΩ) cannot charge ADC sample-and-hold capacitor quickly
  • Solution: Add op-amp buffer or reduce sampling rate to allow settling time

Grounding Problems

  • Problem: ADC readings shift when other circuits turn on/off
  • Cause: Ground loops or voltage drops in ground connections
  • Solution: Use star ground topology, ensure low-resistance ground connections

DAC (Digital-to-Analog Converter)

How DAC Works

A DAC does the opposite of an ADC. You give it a digital number, and it produces a corresponding analog voltage.

V_output = (Digital Value / (2^resolution - 1)) * V_reference

Example (12-bit DAC, 3.3V reference, digital value = 2048):
  V_output = (2048 / 4095) * 3.3V = 1.65V

DAC Resolution

Like ADCs, DAC resolution determines the number of distinct voltage levels it can produce. A 12-bit DAC with a 3.3V reference can output voltages in steps of about 0.8 mV.

DAC Code Example

// STM32 HAL example
#include "stm32f4xx_hal.h"

DAC_HandleTypeDef hdac;

void set_dac_voltage(float voltage) {
    // Convert voltage to 12-bit value
    uint16_t dac_value = (uint16_t)((voltage / 3.3f) * 4095.0f);

    if (dac_value > 4095) dac_value = 4095;

    HAL_DAC_SetValue(&hdac, DAC_CHANNEL_1, DAC_ALIGN_12B_R, dac_value);
}

int main(void) {
    HAL_Init();
    // ... clock and DAC configuration ...
    HAL_DAC_Start(&hdac, DAC_CHANNEL_1);

    // Generate a staircase waveform
    while (1) {
        for (float v = 0.0f; v <= 3.3f; v += 0.3f) {
            set_dac_voltage(v);
            HAL_Delay(100);
        }
    }
}

DAC Applications

  • Audio output: Generate sounds and tones
  • Waveform generation: Create sine, triangle, or sawtooth waves for testing
  • Analog control signals: Set reference voltages for comparators or control loops
  • Calibration: Provide precise voltages for testing other analog circuits

Not All MCUs Have a DAC

Many microcontrollers (including Arduino/ATmega328 and many Cortex-M0 chips) do not have a built-in DAC. Alternatives include:

PWM + Low-Pass Filter

A PWM signal filtered with an RC circuit approximates an analog output. This is the most common approach for microcontrollers without DACs.

Simple RC Low-Pass Filter:

PWM Pin ──[R]──┬── Analog Output
               │
              [C]
               │
              GND

R = 1kΩ to 10kΩ
C = 100nF to 10μF
Cutoff frequency = 1/(2π×R×C)

When to use PWM vs DAC:

  • Use PWM + filter when:
    • Slow-changing signals (LED dimming, motor speed control)
    • Cost is critical
    • 8-bit resolution is sufficient
    • Some ripple voltage is acceptable
  • Use true DAC when:
    • Audio applications requiring low distortion
    • High-resolution control (12-bit or higher)
    • Fast-changing signals
    • Minimal output ripple required

Improved PWM filtering with active filter:

PWM Pin ──[R1]──┬──[R2]──┬── Analog Output
                │       │
               [C1]   ┌─[C2]
                │    │  │
               GND   │ GND
                     │
                   [Op-Amp Buffer]

Two-stage filter reduces ripple further
Op-amp provides low output impedance

External DAC Chips

  • External DAC chip: MCP4725 (12-bit I2C), AD5220 (SPI), or other dedicated DAC ICs
  • Resistor ladder (R-2R): Simple but requires precise resistor matching

ADC vs DAC Comparison

FeatureADCDAC
FunctionAnalog → DigitalDigital → Analog
InputAnalog voltageDigital number
OutputDigital numberAnalog voltage
Resolution Examples8-16 bits typical8-16 bits typical
8-bit range (3.3V)0-255 (12.9mV steps)0-255 (12.9mV steps)
12-bit range (3.3V)0-4095 (0.81mV steps)0-4095 (0.81mV steps)
16-bit range (3.3V)0-65535 (0.05mV steps)0-65535 (0.05mV steps)
Common ApplicationsSensor reading, measurementAudio, waveform generation
Key ParameterSampling rateSettling time
AvailabilityNearly all MCUsMid-range MCUs and up

Summary

ADCs and DACs are the bridge between the analog physical world and the digital microcontroller. ADCs let your MCU read sensors and measure real-world signals, while DACs enable precise analog output control. Understanding their resolution, sampling rates, and limitations is crucial for building reliable embedded systems that interact with the physical world.

Remember that not all microcontrollers include DACs, but PWM with proper filtering can often substitute for many applications. For critical applications requiring high precision or low noise, dedicated external converters may be necessary.

Leave a Reply

Your email address will not be published. Required fields are marked *