The formula
The difference equation your microcontroller actually executes:
y[n] = b₀·x[n] + b₁·x[n−1] + b₂·x[n−2] − a₁·y[n−1] − a₂·y[n−2]
Reading: the new output is a weighted mix of recent inputs and recent outputs — that feedback term is what makes the impulse response run on forever and what makes the filter cheap.
The same filter in the z-domain — this second-order section is the biquad:
H(z) = (b₀ + b₁·z⁻¹ + b₂·z⁻²) / (1 + a₁·z⁻¹ + a₂·z⁻²)
Reading: two zeros over two poles; the poles do the heavy lifting, and every practical IIR filter of any order is built as a cascade of these.
Stability lives in the denominator:
poles inside the unit circle: |z_pole| < 1
biquad shortcut: |a₂| < 1 and |a₁| < 1 + a₂
Reading: a pole at radius r decays like rⁿ; at r = 1 it rings forever, and outside it grows without bound. The settle time constant is about −1/ln(r) samples.
The bilinear transform, which converts a proven analog prototype into digital coefficients:
s = (2/T)·(1 − z⁻¹)/(1 + z⁻¹), with prewarp ω_analog = (2/T)·tan(ω_digital·T/2)
Reading: the whole analog frequency axis gets squeezed into 0 to Nyquist, so frequencies compress as you approach Nyquist — design the analog prototype at the prewarped frequency or your cutoff lands in the wrong place.
Where you meet it
- In DAQ and controller firmware. The 60 Hz notch on a strain channel, the smoothing on a thermocouple reading, the anti-alias cleanup before decimation — on a Cortex-M or a cRIO these are almost always biquads, because a three-multiply-per-sample recursive filter fits in the interrupt budget where a 200-tap FIR does not.
- In the control loop on a test stand. A filter inside a feedback loop contributes phase lag, and IIR phase is not linear — a low-pass biquad near your crossover frequency eats phase margin fast. More than one "unstable actuator" investigation has ended at a filter somebody added to quiet a noisy sensor.
- In fixed-point audio and RF signal chains. Codec EQ stages, receiver channel filters, and PLL loop filters ship as cascaded biquad coefficients burned into a DSP. The vendor tool that spits out
bandaarrays is running the analog-prototype-plus-bilinear-transform flow described here. - At the design review. The recurring argument is IIR versus FIR. The honest answer: IIR when you need cheap and sharp and can tolerate phase distortion; FIR when you need linear phase (matched channels, data that gets integrated downstream) and can afford the taps and the latency.
How it works
The standard flow is sixty years old and still right: pick an analog prototype — Butterworth for flat passband, Chebyshev for a steeper knee with ripple, elliptic for the steepest transition physics allows at a given order — then map it to digital with the bilinear transform, prewarping the critical frequencies, and factor the result into biquads.
Why bother: order economy. For a low-pass with the passband edge at 0.4× Nyquist, the stopband at 0.5× Nyquist, 1 dB of passband ripple and 60 dB of stopband rejection, the required orders (computed, scipy.signal): elliptic 6, Chebyshev 10, Butterworth 24. A linear-phase FIR hitting the same spec needs about 43 taps (Parks–McClellan equiripple, verified with scipy.signal.remez; the Kaiser-window estimate of 74 is the number that usually gets quoted, but it wastes taps forcing the passband ripple down to stopband level). The elliptic version is three biquads — roughly 15 multiplies per sample against 43, or about 22 where the hardware folds the FIR's symmetric coefficients — plus a fraction of the group delay. Still a real win, just not the 5× rout the Kaiser number suggests; the ratio does grow brutally as the transition band narrows.
What you pay:
- Nonlinear phase. A causal IIR filter cannot have exactly linear phase; group delay bunches up near the band edge, so a sharp transient smears differently at different frequencies. If two instrumentation channels get subtracted or cross-correlated downstream, mismatched IIR phase is a silent error source. (Offline you can cheat: filter forward, then backward —
filtfilt— for zero phase at double the cost. Never in real time.) - The warping trap. Skip prewarping at fs = 48 kHz and a 10 kHz analog cutoff lands at 8.85 kHz digital — 11 % low (computed:
f_d = (fs/π)·arctan(π·f_a/fs)). At 1 kHz the same mapping lands at 998.6 Hz and nobody notices. That is exactly why the bug survives: it hides until someone designs closer to Nyquist. - Coefficient sensitivity at low cutoffs. Push the cutoff far below the sample rate and the poles crowd against the unit circle at z = 1. Worked example, verified numerically: a 2nd-order Butterworth at fc = 10 Hz, fs = 48 kHz gives
a = [1, −1.9981488, 0.9981505], pole radius 0.99907 — a settle time constant of about 1,080 samples (22.5 ms). Quantize those coefficients to 16-bit Q2.14 and the rounded integers happen to satisfy−a₁ = 1 + a₂exactly: one pole lands on the unit circle at z = 1. Worse,b₀ ≈ 4.3·10⁻⁷is below one LSB of the same format, so the entire numerator quantizes to zero. The filter, as coded, outputs nothing. The fixes are standard: cascade second-order sections instead of one high-order polynomial, keep coefficients and states in wider arithmetic than the data, and if fc/fs is extreme, decimate first and filter at the lower rate. - Fixed-point limit cycles. Rounding inside the feedback path can sustain a small self-generated oscillation with zero input — a filter that hums to itself at a few LSBs. Dither, magnitude truncation, or floating point make it go away; it matters when those LSBs get amplified downstream.
The mistake people actually make is implementing an 8th-order design as a single direct-form difference equation because the textbook transfer function came that way. Root sensitivity to coefficient error grows viciously with polynomial order; the same filter as four cascaded biquads (pair the poles with their nearest zeros, order sections by increasing pole radius) is numerically boring and just works. Every serious tool — MATLAB's sos output, scipy's output='sos' — defaults to sections for this reason. Use that output, not b, a.
History
The prototypes came first, from the analog world. In 1930 Stephen Butterworth, a physicist at the British Admiralty Research Laboratory with a reputation for knocking down "impossible" mathematics, published "On the Theory of Filter Amplifiers" in Experimental Wireless and the Wireless Engineer, showing how to build a filter whose passband gets flatter — maximally flat, in the trade's language — as the order climbs [1][2]. Across the North Sea, Wilhelm Cauer had already put the whole business of network synthesis on a rigorous footing in his 1926 dissertation, and in the 1930s used elliptic functions to solve the sharpest-possible-transition problem; the elliptic filter still carries his name [3][4][5]. Cauer's story ends badly: he stayed in Berlin as the war closed in and was shot by Soviet soldiers in April 1945, days before the fighting stopped [3][4].
The bridge from continuous to sampled time came from control engineering, not audio. In 1947 Arnold Tustin — newly appointed professor at Birmingham after a career in servo systems — published "A method of analysing the behaviour of linear systems in terms of time series" in the Journal of the IEE, representing continuous behavior by sequences of equally spaced samples with simple combining rules [6][7]. His substitution is the bilinear transform, and control engineers still call discretizing a plant model "Tustin's method."
The digital filter as we now ship it took shape at Bell Labs in the 1960s, when general-purpose computers made it practical to simulate — and then replace — analog hardware. James Kaiser, who spent his Bell Labs career on signal processing for speech and hearing before concentrating on digital filter design, laid out the design methodology in his "Digital Filters" chapter of System Analysis by Digital Computer (Kuo and Kaiser, Wiley, 1966) — the recipe of analog prototype, transformation, and quantization analysis that this entry describes [8][9]. The biquad coefficient formulas most working engineers actually paste into firmware trace to the same lineage, standardized today in the W3C's Audio EQ Cookbook [10].
Related tools
- /tools/rc-filter — the first-order analog prototype the simplest IIR filter is a bilinear image of
- /tools/q-factor-bandwidth — the Q you hand to a biquad design formula, and what it costs in ringing
- /tools/lc-resonance — the analog resonator a two-pole IIR section imitates
- /tools/adc-resolution — the word length that decides whether your coefficients quantize to garbage
- /tools/frequency-period — keeping fc, fs, and Nyquist straight before you design anything
Sources
- https://en.wikipedia.org/wiki/Butterworth_filter
- https://www.electronics-notes.com/articles/radio/rf-filters/what-is-butterworth-filter-basics.php
- https://en.wikipedia.org/wiki/Wilhelm_Cauer
- https://mathshistory.st-andrews.ac.uk/Biographies/Cauer/
- https://www.semanticscholar.org/paper/Life-and-Work-of-Wilhelm-Cauer-(1900-1945)-Cauer-Mathis/adc672b4f00141361683b8e871760499cff8e791
- https://digital-library.theiet.org/doi/10.1049/ji-2a.1947.0020
- https://en.wikipedia.org/wiki/Arnold_Tustin
- https://en.wikipedia.org/wiki/James_Kaiser
- https://archive.org/details/systemsanalysisb0000fran
- https://www.w3.org/TR/audio-eq-cookbook/