To calculate the cutoff frequency of an RC circuit, use the formula fc = 1 / (2πRC). If you are trying to smooth a standard 5kHz ESP32 PWM signal into a clean DC voltage, your target cutoff should be roughly 1/10th to 1/100th of the PWM frequency. Using a 10kΩ series resistor and a 1µF shunt capacitor yields a cutoff frequency of 15.9Hz, providing a smooth DC output with minimal ripple and an acceptable settling time of roughly 50ms.

This guide moves past the basic math to show you exactly how to configure, build, and troubleshoot a passive low-pass RC filter for microcontroller applications.

The Core Topology: Low-Pass RC Filter Node Map

A standard first-order passive low-pass filter consists of a series resistor and a shunt (parallel) capacitor. Here is the exact node mapping for a microcontroller PWM smoothing circuit:

  • Node Vin: The raw PWM signal source (e.g., ESP32 GPIO 25). This node carries a square wave toggling between 0V and 3.3V.
  • Component R1: The series resistor. It limits current and, together with C1, sets the time constant (τ = R × C).
  • Node Vout (Junction): The connection point between R1 and C1. This is your filtered analog output.
  • Component C1: The shunt capacitor, connected between Node Vout and Ground.
  • Node GND: The common ground reference shared by the microcontroller and the measuring device.
Pro-Tip on Output Impedance: The output impedance of this passive filter at DC is exactly equal to R1. If you connect a load with an input impedance lower than 10× R1 (e.g., a 50kΩ load on a 10kΩ filter), your output voltage will sag due to the voltage divider effect. Always buffer Vout with an op-amp voltage follower if driving low-impedance loads.

Why Low-Pass Over High-Pass (and Active Alternatives)

When designing for frequency, you must choose between a low-pass (resistor in series, capacitor to ground) and a high-pass (capacitor in series, resistor to ground) topology.

For PWM-to-DC conversion or audio anti-aliasing, low-pass is the mandatory choice. A high-pass filter blocks DC and passes AC; it would strip away your steady-state voltage and only output sharp spikes on the rising and falling edges of the PWM wave.

Why not use an active filter (op-amp based Sallen-Key)? Active filters provide gain and low output impedance, but they require dual power rails or virtual ground biasing, consume quiescent current, and introduce op-amp slew-rate limitations. A passive RC filter costs less than $0.05, requires no power supply, and is perfectly adequate when followed by a high-impedance ADC input or an op-amp buffer.

Behavior Matrix: Tuning R and C for Target Frequency

Using an rc circuit calculator frequency tool will give you infinite combinations of R and C that yield the exact same fc. However, changing the ratio of R to C drastically alters the physical behavior of the circuit. Refer to the All About Circuits RC Filter Tutorial for the foundational math, but use this matrix for practical design trade-offs:

Design Change Effect on Cutoff Freq (fc) Effect on Output Impedance Effect on Settling Time Physical Trade-off
Increase R, Keep C same Decreases Increases (Worse) Increases (Slower) Less current draw from GPIO, but highly susceptible to noise and load sag.
Decrease R, Increase C Remains Same Decreases (Better) Remains Same Stiffer output, but draws more peak current from the microcontroller pin during charging.
Increase both R and C Decreases heavily Increases (Worse) Increases heavily Extremely smooth DC, but the circuit takes seconds to reach the target voltage.

Design Walkthrough: 5kHz PWM to Smooth DC

Let’s design a filter for an ESP32 running the default LEDC PWM peripheral at 5kHz. Our goal is a clean 0-3.3V DC signal to drive an analog gauge or feed an external DAC.

  1. Identify the Base Frequency: fpwm = 5000Hz.
  2. Set Target Cutoff: To adequately suppress the 5kHz carrier and its harmonics, we want fc to be at least two decades below the fundamental, or roughly 50Hz. Let's target 15.9Hz for ultra-low ripple.
  3. Pick the Capacitor First: Capacitors have fewer standard values and worse tolerances than resistors. We select a 1µF capacitor. Critical selection: Choose an X7R dielectric ceramic. Avoid Y5V or Z5U dielectrics, as they suffer from severe DC bias derating (a 1µF Y5V cap might drop to 0.2µF at 3.3V, shifting your cutoff frequency to 80Hz and ruining the filter).
  4. Calculate the Resistor: Rearranging the formula: R = 1 / (2π × fc × C).
    R = 1 / (2 × 3.14159 × 15.9 × 0.000001) = 10,010Ω.
  5. Select Standard Component: The closest 1% standard E96 value is 10.0kΩ.

Decision Tree: Picking Your Exact R and C Values

Do not guess your component values. Use this decision path to lock in your bill of materials based on your specific application constraints.

Application Scenario Priority Constraint If-Then Decision Path Concrete Default Pick
Microcontroller PWM to DC (e.g., ESP32, Arduino) Minimal ripple, acceptable settling time (<100ms) If fpwm > 1kHz → Target fc = 20Hz. Pick C = 1µF (X7R). Calculate R. R = 10kΩ, C = 1µF (fc = 15.9Hz)
Audio DAC Anti-Aliasing (20kHz bandwidth) Flat passband, fast transient response If audio → Target fc = 30kHz. Pick C = 1nF (C0G/NP0 for low distortion). Calculate R. R = 5.1kΩ, C = 1nF (fc = 31.2kHz)
Mechanical Switch Debounce Absorb 5ms contact bounce If debounce → Target time constant τ = 5ms. Pick C = 100nF. Calculate R for τ = RC. R = 51kΩ, C = 100nF (τ = 5.1ms)

Failure Modes: What Breaks at the Extremes?

When troubleshooting a dead or noisy output, you must understand how component failures manifest. A series/parallel topology behaves very differently depending on which element fails open or short.

Series Resistor (R1) Failures

  • R1 Open (Infinite Resistance): The circuit is broken. Vout floats. If measured with a high-impedance multimeter, you might read ghost voltages from capacitive coupling, but the node cannot source current. Fix: Check for cold solder joints or a burnt resistor.
  • R1 Short (Zero Resistance): The filtering action is entirely defeated. Vout becomes identical to Vin. You will see the full 5kHz square wave on your oscilloscope. This often happens if a solder bridge spans the resistor pads.

Shunt Capacitor (C1) Failures

  • C1 Open (Zero Capacitance): Similar to R1 shorting, the filter ceases to exist. The raw PWM signal passes directly to Vout unattenuated. Ceramic caps rarely fail open unless physically cracked.
  • C1 Short (Zero Impedance): Vout is hard-tied to Ground. The output reads 0V. More dangerously, the microcontroller GPIO pin is now pulling current through R1 directly to ground. With a 10kΩ resistor, current is limited to 0.33mA (safe). If R1 was a low value like 100Ω, the GPIO would source 33mA, potentially destroying the microcontroller pin.

Breadboard Verification: Step-by-Step Testing

Do not trust the rc circuit calculator frequency output until you verify it on the bench. Parasitic capacitance on a breadboard (typically 2pF to 5pF per row) won't affect a 15Hz filter, but it will ruin a 1MHz RF filter. Follow this exact sequence to validate your 10kΩ / 1µF PWM filter.

Safety & Equipment Check: Ensure your oscilloscope is grounded to the same earth ground as your microcontroller's USB supply. Never measure a floating circuit with a grounded scope probe without an isolation transformer or differential probe.
  1. Assemble the Circuit: Insert the ESP32, 10kΩ resistor, and 1µF X7R capacitor into the breadboard. Wire GPIO 25 to the resistor, the resistor to the capacitor's positive leg (if polarized, though ceramics are not), and the capacitor's other leg to the common ground rail.
  2. Program the Source: Flash a simple Arduino sketch using ledcSetup(0, 5000, 8); and ledcWrite(0, 128); to output a 50% duty cycle 5kHz square wave (nominally 1.65V average).
  3. Probe Vin (Baseline): Clip the scope ground to the breadboard GND rail. Probe the ESP32 GPIO pin. Verify a clean 0V to 3.3V square wave at exactly 5.00kHz.
  4. Probe Vout (DC Coupling): Move the probe tip to the junction of R and C. Set the oscilloscope channel to DC Coupling. You should see a flat line at approximately 1.65V. Zoom in vertically (e.g., 20mV/div) to measure the peak-to-peak ripple. For this component combo, expect less than 5mV of ripple.
  5. Measure Settling Time: Change the code to ledcWrite(0, 255); (100% duty cycle). Trigger the scope on the rising edge. Measure the time it takes for the Vout trace to reach 99% of 3.3V (approx 3.27V). It should take roughly 5τ (5 × 10ms = 50ms).
  6. Load Test (Optional but recommended): Connect a 10kΩ load resistor from Vout to GND. Observe the DC voltage drop. Because the filter's output impedance (10kΩ) matches the load (10kΩ), the voltage will drop by exactly 50% (to ~1.65V). This proves why buffering is required for low-impedance loads.

By locking in your topology, respecting dielectric limitations, and verifying the transient response on a scope, you transition from simply plugging numbers into an online calculator to engineering a robust, production-ready analog interface.