27  Quantization and Digital Filtering

In 60 Seconds

Quantization converts continuous voltage into discrete levels: an N-bit ADC has 2^N levels, with step size (LSB) = Vref / 2^N. For a 12-bit ADC with 3.3V reference, each step is 0.8 mV. Match resolution to sensor accuracy – a sensor with 1% accuracy over 3.3V has 33 mV uncertainty, so 8-bit (12.9 mV steps) is already sufficient. For noise, combine filters: median filter first to remove spike outliers, then low-pass (exponential moving average) to smooth gradual noise. Never use moving average alone – one outlier corrupts the entire window.

27.1 Learning Objectives

By the end of this chapter, you will be able to:

  • Calculate Quantization Parameters: Derive ADC step size, effective resolution, and quantization error from bit depth and reference voltage
  • Select ADC Resolution: Choose appropriate bit depth by matching ADC precision to sensor accuracy and power budget
  • Implement Digital Filters: Write moving average, median, and exponential moving average (low-pass) filters in firmware
  • Diagnose Noise Sources: Distinguish between spike outliers, periodic interference, and random noise in sensor readings
  • Design Filter Pipelines: Combine median and low-pass filters in the correct order to eliminate both transient spikes and continuous noise

Quantization is the process of rounding a sensor’s continuous voltage into a set of discrete digital steps – like rounding your height to the nearest centimeter instead of measuring to the nearest atom. Digital filtering then cleans up noisy readings, similar to how you might average several bathroom scale readings to get a more reliable weight. This chapter teaches you to choose the right level of measurement precision and the right type of noise filter for your IoT application.

27.2 ADC Resolution: How Precisely to Measure?

Time: ~11 min | Level: Intermediate | Unit: P02.C05.U04

Resolution determines measurement precision:

8-bit ADC (0-255):

Voltage range: 0-3.3V
Step size: 3.3V / 256 = 12.9 mV
Reading 127 means: 127 x 12.9mV = 1.638V +/- 6.4mV

12-bit ADC (0-4095):

Voltage range: 0-3.3V
Step size: 3.3V / 4096 = 0.8 mV
Reading 2048 means: 2048 x 0.8mV = 1.638V +/- 0.4mV

Three-column comparison of 8-bit, 12-bit, and 16-bit ADC choices showing step size, typical sensor-fit guidance, and when each resolution is appropriate for IoT measurement systems.

ADC Resolution Comparison: 8-bit, 12-bit, and 16-bit Quantization Levels
Figure 27.1

Quantization Levels Comparison: Higher bit depth provides more levels and finer resolution. 8-bit (orange) is coarse with 256 steps. 12-bit (teal) is typical for IoT with 4096 steps. 16-bit (navy) provides medical-grade precision with 65536 steps at the cost of power and speed.

Trade-offs:

Resolution Levels Precision Cost Power Speed
8-bit 256 ~0.4% Low Low Fast
10-bit 1024 ~0.1% Medium Medium Medium
12-bit 4096 ~0.025% Medium Medium Medium
16-bit 65536 ~0.0015% High High Slow

Rule of thumb for IoT:

  • 8-bit: Simple applications, on/off detection
  • 10-12-bit: Most sensor applications (temperature, light, pressure)
  • 16-bit: High-precision measurements (audio, medical, scientific)

Matching ADC Resolution to Sensor Accuracy: LM35 temperature sensor (±0.5°C accuracy, 10 mV/°C):

Temperature range: 0-100°C → voltage range: 0-1.0V (but ADC measures 0-3.3V)

8-bit ADC (256 levels over 3.3V): \[\text{Step size} = \frac{3.3\text{V}}{256} = 12.9\text{ mV}\]

Temperature resolution: \(\frac{12.9\text{ mV}}{10\text{ mV/°C}} = 1.29°C\) per step ✗ (worse than sensor’s ±0.5°C)

10-bit ADC (1024 levels): \[\text{Step size} = \frac{3.3\text{V}}{1024} = 3.22\text{ mV}\]

Temperature resolution: \(\frac{3.22\text{ mV}}{10\text{ mV/°C}} = 0.32°C\) ✓ (adequate, 1.5× better than sensor)

12-bit ADC (4096 levels): \[\text{Step size} = \frac{3.3\text{V}}{4096} = 0.81\text{ mV}\]

Temperature resolution: \(\frac{0.81\text{ mV}}{10\text{ mV/°C}} = 0.081°C\) ✓ (6× better than sensor)

Decision: 10-bit sufficient, 12-bit comfortable. 16-bit (0.005°C resolution) = overkill at 100× sensor accuracy, wastes 3× power.

Explore how ADC resolution affects measurement precision:

Try it: Adjust the sliders to see how resolution and reference voltage affect measurement precision. Notice how 12-bit provides a good balance for most IoT applications.

27.2.1 ADC Selection Decision Tree

A step-by-step ADC selection guide that checks signal span, required precision, and power budget before recommending a practical converter choice for IoT devices.

ADC Selection Decision Tree Based on Bandwidth, Precision, and Power
Figure 27.2

ADC Selection Decision Tree: Choose ADC based on three key factors: signal bandwidth (sampling speed), required precision (bit depth), and power budget. Most IoT applications use 10-12-bit ADCs as they balance precision, speed, and power consumption.


27.3 Digital Filtering

Time: ~10 min | Level: Advanced | Unit: P02.C05.U05

Problem: ADC readings are noisy due to electrical interference, sensor limitations, and quantization.

Solution: Apply digital filters in firmware.

27.3.1 Moving Average Filter

Simplest filter: Average the last N samples.

Readings: [23.4, 23.6, 23.5, 23.7, 23.5]
5-point average: (23.4+23.6+23.5+23.7+23.5)/5 = 23.54C

Pros: Simple, smooths noise Cons: Slow response to rapid changes

27.3.2 Median Filter

Better for removing spikes: Take the middle value of last N samples.

Readings: [23.5, 23.6, 99.9, 23.7, 23.5]  (99.9 is a spike/outlier)
5-point median: Sort -> [23.5, 23.5, 23.6, 23.7, 99.9]
Median = 23.6C  (spike removed!)

Pros: Removes outliers effectively Cons: More complex than moving average

27.3.3 Low-Pass Filter (Simple RC)

Removes high-frequency noise, keeps slow changes:

// Simple exponential moving average
float filtered_value = 0.9 * previous_value + 0.1 * new_reading;

Weight factor (0.9) determines how much history to keep: - High weight (0.95): Very smooth, slow response - Low weight (0.5): Faster response, less smoothing

Filter Performance Analysis: Temperature sensor with 50 Hz noise (1°C amplitude) on 25°C signal:

Low-pass RC filter with time constant τ: \[f_c = \frac{1}{2\pi\tau}\]

For 10 Hz cutoff (reject 50 Hz noise): \(\tau = \frac{1}{2\pi \times 10} = 15.9\) ms

Digital equivalent (exponential moving average): \[y[n] = \alpha \cdot y[n-1] + (1-\alpha) \cdot x[n]\]

where \(\alpha = e^{-\Delta t/\tau}\). Sampling at 100 Hz (Δt = 10 ms): \[\alpha = e^{-10/15.9} = 0.53\]

Attenuation at 50 Hz: \[H(50) = \frac{1}{\sqrt{1 + (f/f_c)^2}} = \frac{1}{\sqrt{1 + (50/10)^2}} = 0.196\]

50 Hz noise: 1°C × 0.196 = 0.196°C remaining (80% rejection)

Moving average (5-sample at 100 Hz = 50 ms window): - Frequency response zeros at 20, 40, 60, 80 Hz (multiples of \(f_s/N\) = 100/5 = 20 Hz) - 50 Hz attenuation: \(\left|\frac{\sin(\pi N f / f_s)}{N \sin(\pi f / f_s)}\right| = \left|\frac{\sin(2.5\pi)}{5 \sin(0.5\pi)}\right| = \frac{1}{5} = 0.2\)

50 Hz noise: 1°C x 0.2 = 0.2°C remaining (80% rejection) — comparable to the low-pass filter at this frequency. However, at frequencies near the zeros (e.g., 40 Hz or 60 Hz), rejection approaches 100%.

27.3.4 Filter Comparison

A four-card comparison of no filter, moving average, median filter, and exponential low-pass filtering applied to noisy sensor readings with a spike outlier, highlighting the strengths and trade-offs of each method.

Digital Filter Comparison: No Filter, Moving Average, Median, and Low-Pass
Figure 27.3

Digital Filter Comparison: Four approaches to handling noisy temperature data with outlier spike (99.9C). No filter keeps noise and spikes. Moving average is corrupted by outliers. Median filter (teal) effectively removes spikes by selecting middle value. Low-pass filter smooths gradually but responds slowly to changes.

See how different filters handle noisy sensor data in real-time:

Try it: Adjust noise level and spike frequency to see how different filters perform. Notice how the two-stage pipeline (median + low-pass) handles both spikes and continuous noise.

This variant presents filtering as a decision-making process based on your specific noise problems:

A mobile-friendly decision guide that maps common IoT noise symptoms such as spikes, ripple, and slow drift to the most appropriate filter strategy.
Figure 27.4: Filter selection decision tree: choose based on noise type, then optimize

Why this variant helps: The original compares all filters side-by-side. This decision tree helps students answer the practical question: “Which filter should I use for MY problem?” It turns knowledge into actionable decisions by matching filter type to noise characteristics.


27.4 Practical Quiz: ADC Configuration

Scenario: You’re designing a smart irrigation system using a turbine water flow sensor. The sensor outputs: - Voltage range: 0.5V (no flow) to 4.5V (maximum flow 10 L/min) - Signal characteristics: Pulsed output, 1-50 Hz depending on flow rate - Noise: +/-50mV from pump electrical interference

Your microcontroller options: - Option A: 8-bit ADC, 100 ksps (samples/second), 10uA power - Option B: 12-bit ADC, 10 ksps, 100uA power - Option C: 16-bit ADC, 1 ksps, 500uA power

Think about:

  1. What sampling rate do you need to accurately measure 50 Hz pulses? (Nyquist)
  2. What ADC resolution do you need to measure +/-0.1 L/min precision (assuming linear sensor)?
  3. Which ADC option provides the best balance of precision, speed, and power?

Key Insights:

Sampling rate requirement:

  • Maximum frequency: 50 Hz
  • Nyquist requirement: > 100 samples/second
  • Practical target: 250-500 samples/second for safety
  • All options meet this (slowest is 1000 sps)

Resolution requirement:

  • Voltage span: 4.5V - 0.5V = 4.0V
  • Flow span: 10 L/min - 0 L/min = 10 L/min
  • Sensitivity: 4.0V / 10 L/min = 0.4V per L/min
  • Desired precision: +/-0.1 L/min = +/-0.04V

8-bit ADC:

  • Step size: 5V / 256 = 19.5 mV
  • Precision: 19.5mV / 400mV per L/min = +/-0.05 L/min (Just barely meets requirement!)

12-bit ADC:

  • Step size: 5V / 4096 = 1.2 mV
  • Precision: 1.2mV / 400mV per L/min = +/-0.003 L/min (Excellent!)

Noise consideration:

  • Noise: +/-50mV
  • 8-bit: Noise = +/-2.5 steps (poor SNR)
  • 12-bit: Noise = +/-40 steps (good SNR, averaging helps)

Best choice: Option B - 12-bit ADC - Plenty of resolution (0.003 L/min vs. 0.1 L/min requirement) - Adequate sampling rate (10,000 sps >> 100 sps needed) - Reasonable power (100uA vs. 500uA for 16-bit) - Good SNR with noise (40 steps margin)

Option A (8-bit) would work but has minimal margin for noise. Option C (16-bit) is overkill and wastes 5x more power for precision you don’t need.

Real-world lesson: Don’t over-specify. Match ADC resolution to actual sensor precision and application requirements. The 16-bit ADC costs more, draws 5x power, and provides 400x the precision - but irrigation doesn’t need microliter accuracy!

Make the right ADC choice for your application:

Try it: Adjust your application requirements to see which ADC resolution is recommended. The calculator considers speed, precision, and power trade-offs.


27.4.1 Worked Example: Bosch Air Quality Sensor Filter Pipeline for Stuttgart Traffic Monitoring

Scenario: Bosch operates 150 urban air quality monitoring stations along Stuttgart’s B14 highway corridor. Each station has a Sensirion SPS30 particulate matter sensor (PM2.5) that suffers from two noise sources: electrical spikes from passing diesel trucks (single-sample outliers up to 500 ug/m3) and 50 Hz mains interference from nearby tram power lines.

Given:

  • Sensor: Sensirion SPS30, 0-1000 ug/m3 range, 1 Hz sampling (1 reading/second)
  • ADC: Built-in 16-bit (in sensor module)
  • Noise source 1: Truck exhaust plumes cause single-sample spikes of 200-500 ug/m3 lasting 1 second
  • Noise source 2: 50 Hz electromagnetic interference from tram lines adds 5-10 ug/m3 ripple
  • Typical PM2.5 readings: 15-35 ug/m3 (normal Stuttgart air quality)
  • Regulatory reporting: 1-minute averages, accuracy requirement less than 5 ug/m3

Step 1: Identify filter requirements

Noise Type Characteristics Best Filter
Truck spikes Single-sample outliers, 200-500 ug/m3 Median filter (removes outliers without distortion)
50 Hz mains Continuous periodic, 5-10 ug/m3 amplitude Low-pass filter (smooths periodic noise)

Step 2: Design two-stage filter pipeline

Stage 1 – Median filter (window = 5 samples):

Sample Raw Reading 5-Sample Window (sorted) Median Output
t=1 22.3 22.3 (pass through, window filling)
t=2 23.1 23.1
t=3 21.8 21.8
t=4 22.5 22.5
t=5 487.2 (truck spike) [21.8, 22.3, 22.5, 23.1, 487.2] 22.5 (spike removed)
t=6 22.9 [22.3, 22.5, 22.9, 23.1, 487.2] 22.9

The 487.2 ug/m3 truck spike is completely eliminated. A moving average would have reported (22.3+23.1+21.8+22.5+487.2)/5 = 115.4 ug/m3 – a 5x exaggeration.

Stage 2 – Exponential moving average (alpha = 0.85):

After the median filter removes spikes, the EMA smooths the remaining 50 Hz ripple:

filtered = 0.85 x previous_filtered + 0.15 x median_output
Parameter Value Reasoning
Alpha 0.85 Balances 50 Hz rejection with 1-minute response
Time constant dt/(1-alpha) = 1s/0.15 = 6.7 seconds Smooths 50 Hz noise completely
Step response time 3 x tau = 20 seconds Fast enough for 1-minute regulatory average

Step 3: Verify pipeline performance

Metric No Filter Moving Average Only Median + EMA
Truck spike error 487.2 ug/m3 115.4 ug/m3 0 ug/m3
50 Hz noise (RMS) 7.1 ug/m3 3.2 ug/m3 0.4 ug/m3
True signal tracking Perfect 4-second lag 20-second lag
Meets 5 ug/m3 accuracy? No No (spikes) Yes
Computational cost 0 5 additions + 1 division 5 sorts + 2 multiplies

Result: The two-stage pipeline (median first, then EMA) eliminates both noise sources while meeting the 5 ug/m3 regulatory accuracy requirement. Total computation cost is negligible on the station’s ESP32 microcontroller, adding less than 0.1 ms per sample.

Key Insight: Filter order matters. Applying the median filter first removes outlier spikes so they cannot corrupt the subsequent EMA stage. Reversing the order (EMA first) would spread each truck spike across multiple samples before the median could remove it, reducing but not eliminating the distortion. The rule is always: median first to remove spikes, then low-pass to smooth continuous noise.

Time: ~10 min | Difficulty: Beginner | No hardware needed

Challenge: Your outdoor air quality sensor reads PM2.5 particulate concentration. Sample data shows: [22, 24, 23, 187, 25, 24, 26] where 187 is clearly a spike (bug flew past sensor). Design a filter pipeline.

Steps:

  1. Apply 5-point median filter to remove the spike
  2. Apply exponential moving average (alpha=0.2) to smooth remaining noise
  3. Calculate the filtered output

Solution:

  • Median filter output: [22, 23, 23, 24, 25, 25, 25] so the spike at 187 is removed before it can distort the average.
  • EMA progression starting from 22:
    • 0.2×22 + 0.8×22 = 22.0
    • 0.2×23 + 0.8×22.0 = 22.2
    • 0.2×23 + 0.8×22.2 = 22.4
    • 0.2×24 + 0.8×22.4 = 23.7
  • Final result: the output stays in the 23-24 range, which means the spike is gone and the remaining signal is smoothed without a large false excursion.

Common Pitfalls

Adding more bits does not improve the sensor itself. If the transducer, reference rail, or analog front-end is noisy, a 16-bit ADC mostly gives you a more detailed view of the noise. Match resolution to the real sensor chain first, then earn extra precision through calibration and cleaner hardware.

Moving average, median, and exponential smoothing do different jobs. A moving average is poor at handling outliers, a median filter is not a replacement for continuous smoothing, and an EMA will happily smear a spike across several samples if you feed it bad data first. Diagnose the noise type, then build the filter chain around that failure mode.

If a spike reaches the moving average or EMA before the median stage, it contaminates several future samples and creates fake trends. In mixed-noise systems, the safe rule is usually median first to eliminate outliers, then low-pass smoothing for the remaining continuous noise.

27.5 Summary

Key concepts from this chapter:

  • ADC Resolution: Higher bits = more precision, but also more power and cost
  • Step Size: V_ref / 2^bits determines measurement granularity
  • Match Resolution to Sensor: Don’t use 16-bit ADC for a sensor that’s only 1% accurate
  • Digital Filters:
    • Moving average: Smooths noise, but corrupted by outliers
    • Median filter: Best for spike/outlier removal
    • Low-pass (EMA): Smooths gradual noise, slow response
    • Combination: Median first (remove spikes), then low-pass (smooth)

Decision Framework:

  1. Identify signal bandwidth -> choose sampling rate
  2. Identify precision needs -> choose ADC resolution
  3. Identify noise type -> choose filter strategy
  4. Consider power budget -> optimize all choices
Concept Relationships: Quantization and Filtering
  • ADC resolution -> step size: every extra bit halves the least-significant-bit size, but only matters if the sensor and analog chain can support the finer steps.
  • Input range -> effective resolution: if your signal only uses a small fraction of Vref, most ADC codes are wasted and the effective precision drops sharply.
  • Median filter -> spike rejection: sorting a window and taking the middle value removes outliers without letting one bad sample dominate the result.
  • Moving average / EMA -> continuous smoothing: both reduce random variation, but they trade off response speed against smoothness.
  • Filter order -> output credibility: outlier rejection should happen before smoothing, otherwise a single glitch can spread across multiple downstream samples.

Cross-module connection: Signal Processing Labs provides hands-on ESP32 experiments with the filters and ADC trade-offs from this chapter.

27.6 See Also


27.7 Knowledge Check

27.8 What’s Next

Continue with:

Key Takeaway

ADC resolution determines measurement precision, but more bits always cost more power. The key design decision is matching resolution to sensor accuracy: don’t use a 16-bit ADC (0.05 mV steps) for a sensor that’s only accurate to 33 mV. For noise reduction, always apply median filtering first (removes spikes without distorting signal) before low-pass smoothing (removes gradual noise). This two-stage approach handles both bursty interference and continuous noise.

Max the Microcontroller was explaining quantization using a staircase!

“Imagine measuring your height,” Max said. “An 8-bit ruler has 256 steps – each step is about half a centimeter. Pretty good!”

“A 12-bit ruler has 4,096 steps – each step is the thickness of a hair!” added Lila the LED.

Sammy the Sensor asked: “Should I always use the finest ruler?”

“NO!” shouted Bella the Battery. “The finer ruler costs 5 times more energy! If Sammy can only sense temperature to the nearest 0.5 degrees, using a ruler that measures to 0.001 degrees is like using a microscope to measure a building – total waste!”

Max then showed his filter toolkit: “And when readings are noisy, I clean them up! My median filter sorts 5 readings and picks the middle one – goodbye, crazy outliers! Then my smoothing filter averages nearby readings to remove the wobbles.”

“First remove the spikes, THEN smooth,” Sammy remembered. “Like picking rocks out of flour before sifting it fine!”