Passive & Active Filters: Butterworth, Chebyshev, Bessel, Sallen-Key & MFB

Shaping the frequency content of signals. Learn filter types (low-pass, high-pass, band-pass, band-stop/notch, all-pass), specifications (passband, stopband, ripple, attenuation, transition band, order), passive RC/RLC filters and their loading problems, response families (Butterworth, Chebyshev, Bessel, elliptic) and their trade-offs in flatness, steepness, phase and step response, active topologies (Sallen-Key, multiple-feedback, state-variable, biquads), cascading second-order sections, component sensitivity and anti-aliasing filters — with Python computing the required order, Sallen-Key component values and comparing Butterworth and Chebyshev attenuation.

Filters remove what you don't want — noise, interference, aliasing components, DC offsets — while keeping the signal. Every sensor front end, audio system, radio and ADC input needs at least one.

Designing a filter means choosing a response family and order that meet the attenuation requirement, then realising it with a topology whose components are practical and insensitive to tolerances.

An analogy

A filter is like a sieve with carefully shaped holes: a Butterworth sieve is smooth and uniform, a Chebyshev sieve has slightly bumpy holes but a sharper cut-off, and a Bessel sieve lets everything through at the same speed so shapes aren't distorted.

Filter types and specifications

What filters do:

Response families

Butterworth: maximally flat passband, moderate roll-off, some overshoot — the default. Chebyshev I: passband ripple for a steeper transition. Inverse Chebyshev: flat passband, ripple in the stopband. Elliptic (Cauer): ripple in both, the steepest transition for a given order. Bessel: maximally flat group delay — preserves pulse shape with no overshoot, but a gentle roll-off. Choose by what matters: amplitude accuracy, steepness, or time-domain fidelity.

Active topologies

Passive RC filters load each other when cascaded and cannot produce high-Q poles without inductors. Op-amps isolate stages and synthesise complex poles. Sallen-Key (non-inverting, simple, low component spread; high-frequency leakage through C₁ at very high frequencies), multiple-feedback MFB (inverting, better high-frequency rejection, good for band-pass), state-variable / KHN and Tow-Thomas biquads (simultaneous LP/HP/BP outputs, independently tunable f₀ and Q). A high-order filter is a cascade of second-order sections plus one first-order section for odd orders, ordered by increasing Q.

Practical design

Use C0G/NP0 or film capacitors (not X7R, which drift and distort), 1% resistors, and op-amps with GBW ≥ 100 × f₀ × Q for accurate high-Q sections. Check sensitivity (high-Q sections are sensitive to tolerances), output swing at internal nodes (peaking), noise and the op-amp's output impedance at high frequency. Anti-aliasing filters must attenuate everything above f_s/2 to below the ADC's LSB — often combined with oversampling and digital filtering. Switched-capacitor and integrated active filters (e.g. programmable filter ICs) simplify tunable designs.

Formulas

Worked example: RC cut-off

Given: R 1 kΩ, C 100 nF

Find: f_c.

Answer: 1.59 kHz

Worked example: Butterworth attenuation

Given: 3rd order, f = 2f_c

Find: Gain.

Answer: −18.1 dB

Worked example: Sallen-Key values

Given: R 10 kΩ, C₁ 22 nF, C₂ 10 nF

Find: f₀ and Q.

Answer: 1.07 kHz, Q = 0.74

Unity-gain Sallen-Key low-pass

              C1 (20 nF, to output)
          ┌───────||─────────────┐
  vin ─R1─┴─R2─┬──────┤+         │
      11.3k  11.3k    │  ▷──────┴─── vout
               C2     ┌┤−        │
             10 nF    └──────────┘  (follower)
               GND

Two RC sections with the first capacitor bootstrapped from the output create a complex pole pair. Using a follower (gain 1) makes the circuit simple and insensitive to op-amp gain; the capacitor ratio sets Q (2:1 gives Butterworth Q = 0.707).

Order, component values and response comparison

import math
# Active filter design: Butterworth order, unity-gain Sallen-Key low-pass, and response comparison
fp, fs, Ap, As = 1e3, 4e3, 3.0, 40.0          # passband edge, stopband edge, dB
n = math.log10((10**(As/10) - 1) / (10**(Ap/10) - 1)) / (2 * math.log10(fs / fp))
print(f"Butterworth order needed: {n:.2f} -> {math.ceil(n)}")
# Unity-gain Sallen-Key 2nd-order LPF, f0 = 1 kHz, Q = 0.7071: equal R, C1 (feedback) = 2*C2
f0, Q, C2 = 1e3, 1 / math.sqrt(2), 10e-9
C1 = 4 * Q**2 * C2
R = 1 / (2 * math.pi * f0 * math.sqrt(C1 * C2))
print(f"Sallen-Key: C1 = {C1*1e9:.0f} nF, C2 = {C2*1e9:.0f} nF, R1 = R2 = {R/1e3:.2f} kohm")
def butter(f, n): return -10 * math.log10(1 + (f / f0) ** (2 * n))
for f in (500, 1000, 2000, 4000):
    print(f"f = {f:4d} Hz: 2nd-order {butter(f,2):7.2f} dB, 4th-order {butter(f,4):7.2f} dB")
# Chebyshev 1 dB ripple, 4th order at 4 kHz (fp = 1 kHz): |H|^2 = 1/(1 + e^2 Tn^2)
eps2 = 10**(1/10) - 1
x = 4.0
Tn = math.cosh(4 * math.acosh(x))
print(f"Chebyshev 1 dB, 4th order at 4 kHz: {-10*math.log10(1+eps2*Tn**2):.1f} dB (vs Butterworth {butter(4000,4):.1f} dB)")
# Butterworth order needed: 3.32 -> 4
# Sallen-Key: C1 = 20 nF, C2 = 10 nF, R1 = R2 = 11.25 kohm
# f =  500 Hz: 2nd-order   -0.26 dB, 4th-order   -0.02 dB
# f = 1000 Hz: 2nd-order   -3.01 dB, 4th-order   -3.01 dB
# f = 2000 Hz: 2nd-order  -12.30 dB, 4th-order  -24.10 dB
# f = 4000 Hz: 2nd-order  -24.10 dB, 4th-order  -48.16 dB
# Chebyshev 1 dB, 4th order at 4 kHz: -59.8 dB (vs Butterworth -48.2 dB)

To get 40 dB rejection just two octaves above the passband edge, a Butterworth filter needs order 4 (two cascaded Sallen-Key sections). Each doubling of order doubles the roll-off slope. A 4th-order Chebyshev with 1 dB ripple gives ~12 dB more attenuation at 4 kHz than the Butterworth — at the cost of passband ripple and worse phase/step response.

Common mistakes

Applications

Key takeaways

Going further