To condition a sensor signal for a microcontroller SAR (Successive Approximation Register) ADC, use a series resistor and shunt capacitor (RC low-pass filter). For a typical ESP32 or Arduino reading a sub-1kHz sensor, the optimal baseline adc circuit uses a 100Ω series resistor and a 100nF X7R ceramic capacitor. This configuration provides anti-aliasing while acting as a charge reservoir to prevent voltage sag during the ADC sampling window.
The Standard RC Anti-Aliasing ADC Circuit Topology
Microcontroller ADCs do not present a purely static, high-impedance load. Inside the ESP32 or ATmega328P, the ADC input routes through a multiplexer to a sample-and-hold (S/H) switch and an internal sampling capacitor (typically 10pF to 15pF). When the S/H switch closes to take a reading, it draws a sudden spike of current to charge this internal capacitor.
If you connect a high-impedance sensor directly to the GPIO pin, the sensor cannot supply this instantaneous current. The voltage at the pin sags during the acquisition window (often just 2 to 4 microseconds), resulting in erratic, low-bias digital readings. Furthermore, high-frequency noise from the microcontroller's own digital switching can inject back into the sensor.
The standard RC topology solves both issues using three distinct nodes:
- Node A (V_in): The raw signal from your sensor or voltage divider.
- Node B (V_mid): The junction between the series resistor and the shunt capacitor.
- Node C (V_adc): The microcontroller GPIO pin configured for analog input.
The series resistor (R) isolates the sensor from the microcontroller's switching noise and limits current. The shunt capacitor (C) acts as a local charge reservoir. Because C is orders of magnitude larger than the internal S/H capacitor, it instantly supplies the required charge when the S/H switch closes, keeping the voltage at Node C perfectly stable during the conversion.
Design Walkthrough: Sizing R and C for an ESP32
Let's design an adc circuit for an ESP32 reading a slow-moving analog temperature sensor (like an LM35) or a potentiometer. We want to filter out high-frequency RF noise while preserving the DC and low-frequency signal.
Selected Components:
- R1: 100Ω (0805 SMD or 1/4W through-hole, 1% tolerance)
- C1: 100nF (0.1µF) X7R Ceramic Capacitor (0805 SMD or 50V through-hole)
The Math:
The cutoff frequency ($f_c$) of this low-pass filter is calculated as:
$f_c = \frac{1}{2 \pi R C} = \frac{1}{2 \pi \times 100 \times 100 \times 10^{-9}} \approx 15.9 \text{ kHz}$
This 15.9 kHz cutoff easily passes our slow-moving temperature signal but aggressively attenuates RF interference and the ESP32's internal WiFi switching noise (which operates in the MHz range). Additionally, the 100nF external capacitor is roughly 10,000 times larger than the ESP32's ~10pF internal S/H capacitor. When the S/H switch closes, the voltage droop is virtually unmeasurable.
Component Behavior Matrix
Understanding how component drift or substitution affects the adc circuit is critical for debugging. Here is what happens when you alter the baseline values:
| Component Changed | Direction | Effect on Cutoff Frequency | Effect on ADC Settling Time | Effect on Signal Integrity |
|---|---|---|---|---|
| Series R | Increased (e.g., to 10kΩ) | Decreases (more filtering) | Increases (slower recovery) | Risks incomplete settling if MCU samples too fast; increases thermal noise. |
| Series R | Decreased (e.g., to 10Ω) | Increases (less filtering) | Decreases (faster recovery) | Allows MCU digital noise to inject back into the sensor; reduces anti-aliasing. |
| Shunt C | Increased (e.g., to 1µF) | Decreases (more filtering) | Increases (slower step-response) | Excellent charge reservoir, but slows down the circuit's ability to track rapid legitimate signal changes. |
| Shunt C | Decreased (e.g., to 1nF) | Increases (less filtering) | Decreases (faster step-response) | Reservoir becomes too small; internal S/H capacitor causes measurable voltage sag during sampling. |
Failure Modes: What Breaks at the Extremes?
When troubleshooting a breadboard or a custom PCB, you must understand how the adc circuit behaves when a component fails open or short. Unlike simple series or parallel power circuits, signal conditioning failures manifest as data corruption rather than blown fuses.
- R1 Shorts (0Ω): The anti-aliasing filter is defeated. The ADC will still take readings, but high-frequency noise will alias into the digital output. Furthermore, the microcontroller's internal digital switching noise will inject directly back into Node A, potentially disrupting sensitive sensor op-amps.
- R1 Opens (Infinite Ω): Node C (V_adc) is completely disconnected from the signal source. The microcontroller pin will float, picking up ambient electromagnetic interference. Your serial monitor will show random, wildly fluctuating ADC values (e.g., jumping between 0 and 4095 on a 12-bit ESP32).
- C1 Shorts (0Ω): Node C is hard-tied to ground. The ADC will consistently read 0 (or the absolute minimum floor noise). A multimeter will show 0V at the GPIO pin. This is a common failure if a ceramic capacitor cracks due to mechanical board flex.
- C1 Opens (Missing Capacitor): The circuit loses its charge reservoir. If your sensor has a low output impedance (like a 50Ω op-amp), it might still work fine. However, if driven by a high-impedance voltage divider (e.g., two 100kΩ resistors), the ADC readings will consistently read lower than the actual voltage due to charge injection droop.
Step-by-Step Breadboard Testing Protocol
Never plug a newly built adc circuit directly into your microcontroller without verifying the analog behavior first. Follow this bench protocol:
- Build the passive network: Insert the 100Ω resistor and 100nF capacitor into the breadboard. Connect the capacitor's other leg to the ground rail. Do not connect the microcontroller yet.
- Inject a known DC voltage: Use a bench power supply or a potentiometer wired across 3.3V and GND to feed Node A (V_in). Set it to exactly 1.65V.
- Verify DC transfer: Use a digital multimeter (DMM) to measure Node C. It should read 1.65V (±5mV). If it reads lower, your capacitor might be leaky, or your breadboard contacts are oxidized.
- Inject an AC signal: Connect a function generator to Node A. Set it to a 1kHz sine wave, 1V peak-to-peak, with a 1.65V DC offset.
- Verify passband: Probe Node C with an oscilloscope. The amplitude should match the input (1Vpp) with no visible attenuation, confirming 1kHz is well within the 15.9kHz passband.
- Verify stopband (Anti-aliasing): Increase the function generator frequency to 50kHz. The oscilloscope should show the amplitude at Node C dropping significantly (attenuated by roughly -10dB), proving the low-pass filter is actively rejecting high frequencies.
- Connect the MCU: Once verified, wire Node C to your ESP32/Arduino ADC pin and run your firmware.
ADC Circuit FAQ
Why is my ESP32 ADC circuit reading erratic values at high impedance?
The ESP32's internal ADC is notoriously non-linear and sensitive to source impedance. If your voltage divider uses high-value resistors (e.g., 220kΩ and 100kΩ) and you omit the shunt capacitor, the internal S/H capacitor cannot charge fully within the ~2µs acquisition window. The fix is to either lower the divider resistor values (e.g., to 22kΩ and 10kΩ) or ensure your adc circuit includes a 100nF to 1µF shunt capacitor directly at the GPIO pin to act as a charge reservoir.
Can I use an electrolytic capacitor instead of ceramic for the ADC circuit?
It is highly discouraged. Aluminum electrolytic capacitors have high Equivalent Series Resistance (ESR) and significant parasitic inductance, making them ineffective at supplying the instantaneous, high-frequency current spikes required by the SAR ADC's sample-and-hold switch. Furthermore, electrolytics suffer from leakage current that can introduce DC offset errors. Always use a multilayer ceramic capacitor (MLCC). For general hobbyist use, X7R dielectric is fine; for high-precision laboratory measurements, use a C0G/NP0 dielectric to avoid piezoelectric microphonic noise and DC bias derating.
Do I need an op-amp buffer before my ADC circuit?
You only need an op-amp buffer if your sensor cannot drive the 100Ω series resistor without significant voltage drop, or if you need to scale/shift the voltage to match the microcontroller's specific input range (e.g., shifting a ±5V signal to 0-3.3V). If you are reading a low-impedance source like an LM35 temperature sensor or a standard 10kΩ potentiometer, the passive RC adc circuit described above is entirely sufficient and avoids the added noise, cost, and power consumption of an active op-amp stage.
How does the ADC circuit topology handle DC voltage dividers?
When measuring a high-voltage DC source (like a 12V battery) using a resistor voltage divider, the Thevenin equivalent resistance of the divider acts as your series resistor. For example, a divider made of a 100kΩ and a 33kΩ resistor has a Thevenin output impedance of roughly 25kΩ. This is far too high for direct ADC sampling. In this scenario, you place the 100nF shunt capacitor directly at the divider's midpoint (Node C). The 25kΩ divider resistance and the 100nF capacitor naturally form your RC low-pass adc circuit, providing both the necessary voltage scaling and the charge reservoir in one step.






