Every Arduino beginner quickly learns that analogWrite() doesn’t actually produce a true analogue voltage — it generates a PWM square wave that only averages to a target voltage. For many applications that’s fine. But audio output, arbitrary waveform generation, precise voltage control, and signal synthesis all demand a genuine, continuously variable analogue voltage. That’s where a Digital-to-Analogue Converter (DAC) comes in — and the MCP4725 is the most popular I2C DAC module for Arduino projects.
PWM vs True DAC: What’s the Difference?
Understanding why you need an external DAC requires understanding what analogWrite() actually does. PWM (Pulse Width Modulation) rapidly switches the output between 0 V and 5 V at a fixed frequency. By varying the duty cycle (the fraction of time the output is high), the average voltage changes. A low-pass filter on the output can smooth this into a DC voltage, but:
- There’s always residual switching noise at the PWM frequency
- For audio, the 490 Hz default PWM rate is in the audible range — you’d hear it as a constant tone
- PWM output changes slowly (limited by the RC filter time constant)
- True sine waves and arbitrary waveforms cannot be generated cleanly
A true DAC converts a digital code directly to a continuous analogue voltage with no switching. The output settles within microseconds and contains no inherent ripple noise. The MCP4725 is a 12-bit I2C DAC — meaning 4096 discrete voltage steps from 0 V to VCC, with each step representing just 1.22 mV at 5 V supply.
MCP4725 Module Overview
The MCP4725 is a single-channel, 12-bit DAC from Microchip Technology. Key specifications:
- Resolution: 12-bit (4096 steps, 0–4095)
- Interface: I2C (up to 400 kHz Fast Mode)
- Supply voltage: 2.7 V to 5.5 V
- Output voltage range: 0 V to VDD (rail-to-rail output)
- Built-in EEPROM: saves the last output value for power-on restoration
- Default I2C address: 0x60 (or 0x61/0x62/0x63 depending on A0/A1 address pins)
- Settling time: ~6 µs for a full-scale change
- Maximum output current: 1 mA (buffer the output for higher current loads)
The module version of the MCP4725 typically breaks out: VCC, GND, SDA, SCL, and VOUT pins on a small PCB with decoupling capacitors already fitted. Some modules also expose the A0 address select pin.
Wiring the MCP4725 to Arduino
Connecting the MCP4725 module to an Arduino Uno is simple — only four wires needed:
| MCP4725 Pin | Arduino Uno Pin | Notes |
|---|---|---|
| VCC | 5V | Or 3.3V for 3.3V systems |
| GND | GND | Common ground |
| SDA | A4 | I2C data line |
| SCL | A5 | I2C clock line |
| VOUT | — | Analogue output to your load |
The I2C bus already has 4.7 kΩ pull-up resistors on most MCP4725 modules. If you’re connecting multiple I2C devices, confirm pull-ups are only on the bus once (remove extras from other modules).
Installing the Adafruit MCP4725 Library
The easiest way to use the MCP4725 is via the Adafruit library. Install it through the Arduino Library Manager:
- Open Arduino IDE → Sketch → Include Library → Manage Libraries
- Search for “MCP4725”
- Install “Adafruit MCP4725” by Adafruit
- Also install “Adafruit BusIO” if prompted (I2C dependency)
Basic DAC Output Code
Setting the DAC output to a specific voltage is just two lines:
#include <Wire.h>
#include <Adafruit_MCP4725.h>
Adafruit_MCP4725 dac;
void setup() {
Serial.begin(9600);
dac.begin(0x60); // Default I2C address
// Set output to 2.5V (midpoint: 4095/2 ≈ 2047)
dac.setVoltage(2047, false);
// false = don't save to EEPROM
// true = save to EEPROM (persists after power off)
Serial.println("DAC set to ~2.5V");
}
void loop() {}
The second parameter of setVoltage() controls EEPROM writing. Pass true when you want the output to restore automatically on power-up — useful for power supply control or reference voltage generation.
Converting Voltage to DAC Value
// Formula: DAC_value = (desired_voltage / VCC) * 4095
// For VCC = 5.0V:
float targetVoltage = 3.3; // Want 3.3V output
int dacValue = (int)((targetVoltage / 5.0) * 4095);
dac.setVoltage(dacValue, false);
Serial.print("DAC value: ");
Serial.println(dacValue); // 2705
Waveform Generation
The real fun begins when you use the DAC to generate waveforms. The MCP4725’s 6 µs settling time allows waveforms up to about 10–20 kHz (limited by I2C throughput at 400 kHz Fast Mode).
Sine Wave Generation
#include <Wire.h>
#include <Adafruit_MCP4725.h>
#include <math.h>
Adafruit_MCP4725 dac;
// Pre-compute 256-point sine lookup table
const int SAMPLES = 256;
int sineTable[SAMPLES];
void setup() {
dac.begin(0x60);
// Build table: values 0–4095 (full 12-bit range)
for (int i = 0; i < SAMPLES; i++) {
// Map sin(-1 to +1) → 0 to 4095
sineTable[i] = (int)((sin(2.0 * PI * i / SAMPLES) + 1.0) * 2047.5);
}
}
void loop() {
for (int i = 0; i < SAMPLES; i++) {
dac.setVoltage(sineTable[i], false);
// No extra delay — I2C speed limits us to ~6-10 kHz
}
}
Using a pre-computed lookup table avoids floating-point sin() calculations inside the loop, keeping output rate as high as possible. The I2C transaction for each 12-bit value takes approximately 100–150 µs at 400 kHz, giving a maximum sine frequency of roughly 1000/256 × 6.5 = ~25 Hz to 1 kHz depending on I2C clock speed.
Triangle and Sawtooth Waves
// Sawtooth wave: ramp from 0 to 4095 then reset
void sawtoothWave() {
for (int v = 0; v <= 4095; v += 4) {
dac.setVoltage(v, false);
}
}
// Triangle wave: ramp up then ramp down
void triangleWave() {
for (int v = 0; v <= 4095; v += 8) {
dac.setVoltage(v, false);
}
for (int v = 4095; v >= 0; v -= 8) {
dac.setVoltage(v, false);
}
}
Simple Audio Tone Generation
At lower frequencies the MCP4725 can produce audible audio tones. Here’s a simple tone synthesiser:
#include <Wire.h>
#include <Adafruit_MCP4725.h>
Adafruit_MCP4725 dac;
// Play a tone at given frequency for duration milliseconds
void playTone(float freq, int durationMs) {
float period = 1000000.0 / freq; // Period in microseconds
int halfPeriod = (int)(period / 2);
unsigned long endTime = millis() + durationMs;
while (millis() < endTime) {
dac.setVoltage(4095, false); // High
delayMicroseconds(halfPeriod);
dac.setVoltage(0, false); // Low
delayMicroseconds(halfPeriod);
}
dac.setVoltage(2048, false); // Return to midpoint
}
void setup() {
dac.begin(0x60);
// Play A4 (440 Hz) for 1 second
playTone(440, 1000);
delay(500);
// Play C5 (523 Hz)
playTone(523, 1000);
}
void loop() {}
Connect the VOUT pin through a 100 Ω resistor to a small speaker (8 Ω) with the other terminal to GND. The output current limit means volume will be low — add a small amplifier IC (LM386 or PAM8403) for audible volume.
Using Multiple MCP4725 Modules
The MCP4725 supports two I2C addresses (0x60 and 0x61) by setting the A0 address pin high or low. This allows two MCP4725 modules on the same I2C bus — useful for stereo audio or dual-axis control.
Adafruit_MCP4725 dacLeft;
Adafruit_MCP4725 dacRight;
void setup() {
dacLeft.begin(0x60); // A0 pin = GND
dacRight.begin(0x61); // A0 pin = VCC
}
void loop() {
dacLeft.setVoltage(1000, false);
dacRight.setVoltage(3000, false);
}
For more than two channels, consider the MCP4728 (quad 12-bit DAC, I2C) or use SPI DACs like the MCP4922 (dual 12-bit) which allow faster update rates through chip select lines.
Practical Use Cases for Arduino DAC
- Sensor simulation: Generate known reference voltages to test ADC circuits and calibrate sensor amplifiers.
- Variable power supply: Control a voltage regulator (like an LM317 with an op-amp buffer) over I2C for a digitally-controlled bench supply.
- Signal generator: Create sine, triangle, and sawtooth waveforms for testing audio circuits and filters.
- Audio output: Low-quality audio from a text-to-speech engine or pre-recorded samples stored in EEPROM.
- Motor speed control: Generate a precise analogue speed reference for variable-speed drives that accept 0–10 V input.
- LED dimming: True linear brightness control without PWM flicker (important for camera lighting and medical applications).
Frequently Asked Questions
Does Arduino Uno have a built-in DAC?
No — the Arduino Uno (ATmega328P) has no hardware DAC. analogWrite() generates PWM, not a true analogue voltage. Boards with built-in DACs include the Arduino Due (two 12-bit DAC channels on DAC0/DAC1 pins), Arduino MKR series, and Arduino Nano 33 IoT (via the SAMD21’s DAC). For Uno, Nano, and Mega, you need an external DAC module like the MCP4725.
What is the maximum frequency waveform I can generate with MCP4725 and Arduino?
At 400 kHz I2C Fast Mode, each DAC update takes approximately 100–150 µs. With 256 points per waveform cycle, the maximum sine frequency is roughly 26–39 Hz. For higher frequencies, reduce the number of points per cycle (e.g., 16 points gives up to ~400 Hz at the cost of waveform smoothness). For audio frequencies above 1 kHz, use SPI DACs or Arduino boards with built-in DAC peripherals.
Can I use the MCP4725 with a 3.3V Arduino?
Yes — the MCP4725 operates from 2.7 V to 5.5 V. At 3.3 V supply the output range is 0–3.3 V with 0.8 mV per step. The I2C logic levels must match your Arduino’s VIO — most 3.3 V Arduinos (Nano 33 IoT, MKR, Zero) use 3.3 V I2C, which the MCP4725 handles without level shifters.
How do I save a DAC output value to EEPROM?
Pass true as the second argument: dac.setVoltage(value, true). The MCP4725 writes the current output code to its internal non-volatile EEPROM. On next power-up, the DAC automatically outputs that saved voltage before the Arduino has even booted — useful for power supply control where you need a defined voltage immediately at power-on.
Why does my MCP4725 output have noise or ripple?
Common causes: insufficient power supply decoupling (add a 100 nF ceramic capacitor between VCC and GND close to the module), ground loops (ensure single-point grounding), or I2C clock noise coupling onto VOUT (route I2C traces away from the VOUT trace and the load). Adding a 10 µF electrolytic cap in parallel with the 100 nF ceramic greatly improves low-frequency ripple rejection.
Build Real Analogue Circuits with Arduino
Adding an MCP4725 DAC module to your Arduino opens a whole new dimension of projects — from signal generators and audio synthesisers to precise variable power supplies and sensor simulators. The 12-bit resolution and I2C simplicity make it the ideal first external DAC for any Arduino enthusiast.
Browse the full range of Arduino boards and expansion modules at Zbotic.in — get genuine components with fast delivery anywhere in India.
Add comment