UNIT 11 · LESSON 4 OF 6

Triggered Sampling and Conversion Sequences

Getting samples at the right moments and out of the ADC in time: software-started, free-running and timer-triggered conversions, why sampling-time jitter limits accuracy, sequences and round-robin scans over several inputs and the skew between them, and collecting results through FIFOs, interrupts and DMA without overruns.

INTERACTIVESampling on time: timer trigger or software loop
Samples of a sine taken at slightly wrong times and the resulting errors2πf·t_j = 6.28e-2 of the peak: SNR limit 24.0 dB ≈ 3.7 bitsA 12-bit ADC would give only about 3.7 effective bits here: trigger conversions from atimer.
Samples of a sine taken at slightly wrong times and the resulting errors2πf·t_j = 6.28e-2 of the peak: SNR limit 24.0 dB ≈3.7 bitsA 12-bit ADC would give only about 3.7 effectivebits here: trigger conversions from a timer.

Try this

Signal frequency
Sampling-time jitter (rms)
Jitter-limited SNR 24.0 dB (3.7 bits).

A reading taken a little early or late is the value of the signal at the wrong moment. For a sine of frequency f, random timing errors of rms size t_j cause amplitude errors of about 2πf·t_j of the peak (rms), which limit the signal-to-noise ratio however many bits the ADC has. A hardware trigger from a timer starts each conversion within a few clock cycles; a software loop waits for interrupts and other code.

What you will be able to do
  • Compare software-started, free-running and hardware-triggered conversions.
  • Compute the SNR limit caused by sampling-time jitter for a given signal frequency.
  • Configure a multi-channel sequence and compute the per-channel rate and inter-channel skew.
  • Set the RP2040 ADC clock divider for a target sample rate.
  • Collect results with a FIFO, interrupts or DMA and recognise overruns.
Before you start
  • Sampling rate and Nyquist (lesson 1); acquisition time (lesson 3).
  • Timer output compare and triggers (unit 8, lesson 4); interrupt latency (unit 9, lesson 3).
Steps in this lesson
  1. Starting conversions
  2. Jitter is noise
  3. Sequences over several inputs
  4. Getting results out
  5. Worked example: three channels at 1 kS/s each
  6. Common misconceptions

The puzzle

A vibration monitor reads its sensor in a loop with a 1 ms delay and sees noise that no amount of averaging removes. A three-phase current meter reads its three channels “simultaneously” and computes a power factor that is slightly wrong. Both have the right ADC. What matters is when each conversion happens, and how the results get out.

STEP 1

Starting conversions

  • Software start: code writes a start bit and waits for the result. Simple, but the sampling instant inherits every delay in the code: interrupts, other tasks, cache misses.
  • Free-running: the ADC converts continuously at a rate set by its clock (the RP2040’s clock divider), and software or DMA collects results.
  • Hardware trigger: a timer event or a pin edge starts each conversion (STM32: ADC_EXTERNALTRIGCONV_T1_CC1 and friends). The instant is set by hardware, within a few clock cycles.

STEP 2

Jitter is noise

A sample taken late or early measures the signal at the wrong time. For a sine of amplitude A and frequency f the error is up to 2πf·A times the timing error, and random timing errors with an rms value t_j act like noise with

SNRjitter=−20log⁡10(2πf tj)\text{SNR}_{\text{jitter}} = -20 \log_{10} (2\pi f\, t_j)

independent of the converter’s resolution. The effective bits it allows are (SNR − 1.76) / 6.02.

↑ This step uses the figure at the top of the page.

STEP 3

Sequences over several inputs

Most microcontrollers have one ADC and a multiplexer. A sequence (STM32 scan mode, RP2040 round robin) converts several inputs in turn. Each input then gets the total rate divided by the number of inputs, and the inputs are sampled one conversion period apart, not at the same instant.

INTERACTIVEOne ADC, several inputs: round-robin sampling
The order of conversions in a round-robin ADC sequence012012012012012conversions, one every 2 µstotal 500 000 samples/s over 3 inputs: 166 667 samples/s eachinputs are sampled 2 µs apart: to compare two signals at the same instant, correct forthe skew or use simultaneous-sampling ADCs
The order of conversions in a round-robin ADC sequence0120120120conversions, one every 2 µstotal 500 000 samples/s over 3 inputs: 166 667samples/s eachinputs are sampled 2 µs apart: to compare twosignals at the same instant, correct for the skew oruse simultaneous-sampling ADCs
Inputs in the sequence
Clock divider (div)
166667 S/s per input, 2 µs between inputs.

The RP2040 has one ADC and a five-way input multiplexer. In round-robin mode it converts the selected inputs in turn, so each input is sampled at the total rate divided by the number of inputs, and neighbouring inputs are sampled one conversion period apart, not at the same instant. A conversion takes 96 cycles of the 48 MHz ADC clock (500 kS/s back to back); the clock divider stretches the period to (1 + div) cycles.

On the RP2040 the total rate is set by the divider: a conversion takes 96 cycles of the 48 MHz ADC clock, and with a divider the period is (1 + div) cycles:

fs=48 MHzmax⁡(96, 1+div)f_s = \frac{48\ \text{MHz}}{\max(96,\ 1 + \text{div})}

STEP 4

Getting results out

The RP2040’s ADC has a 4-entry FIFO: if it fills, new results are dropped and the OVER flag is set. At 500 kS/s the FIFO holds 8 µs of data, too little for an interrupt per sample to be comfortable, so continuous capture uses the FIFO’s DMA request (unit 12), as in the pico-examples dma_capture. ST’s HAL similarly chooses between an end-of-conversion flag per channel or per sequence, and notes that overrun detection needs interrupt or DMA mode. An overrun means samples were lost and the timing of the rest is no longer known: treat it as an error, not something to ignore.

STEP 5

Worked example: three channels at 1 kS/s each

Three inputs in round robin at 1 kS/s each need 3 kS/s in total, a period of 48 MHz / 3000 = 16 000 ADC clocks:

1+div=16 000⇒div=15 9991 + \text{div} = 16\,000 \quad\Rightarrow\quad \text{div} = 15\,999

Consecutive inputs are sampled 1 / 3000 s ≈ 333 µs apart. For 50 Hz three-phase currents that is 6° of phase (333 µs × 50 Hz × 360°), exactly the kind of error that spoils a power-factor calculation unless the firmware corrects for it or the channels are converted back to back and interpolated.

MYTHS AND FACTS

Common misconceptions

sleep_ms(1) gives 1 kS/s

It gives about 1 kS/s with jitter from every interrupt and task; trigger from a timer instead.

Round robin samples all inputs at once

It samples them one after another; the skew is one conversion period.

Jitter only matters for fast ADCs

It matters for fast-changing signals, whatever the ADC’s speed.

A lost sample or two doesn’t matter

It breaks the timing assumption of every filter and frequency calculation downstream.

Check yourself

Answer in your head, then open the card.

What SNR does 1 µs of sampling jitter allow on a 5 kHz sine, and how many bits is that?

−20 log10(2π × 5000 × 10⁻⁶) ≈ 30.1 dB, about 4.7 bits.

What RP2040 divider gives 10 kS/s on a single input?

48 MHz / 10 000 = 4800 cycles, so div = 4799.

Two inputs in round robin run back to back (div = 0). What is each input’s rate and the skew between them?

500 kS/s total, 250 kS/s each, sampled 2 µs apart.

Why is the ADC FIFO’s DMA request preferable to an interrupt per sample at 500 kS/s?

An interrupt every 2 µs would consume much of the CPU and must never be late by more than the 4-sample FIFO (8 µs); DMA moves each sample without the CPU.

Sources (4)
  1. Raspberry Pi Ltd, pico-sdk 1.5.1, hardware_adc/adc.h — adc_set_round_robin(input_mask): “the ADC will use that input and move to the next one after a read”; adc_set_clkdiv: “Period of samples will be (1 + div) cycles on average … it takes 96 cycles to perform a conversion, so any period less than that will be clamped to 96”; FIFO “is 4 samples long, if a conversion is completed and the FIFO is full, the result is dropped”; dreq_en “Enable DMA requests when FIFO contains data”
  2. Raspberry Pi Ltd, pico-sdk 1.5.1, rp2040/hardware_regs/adc.h — FCS.OVER: the FIFO overflowed (write 1 to clear); DIV.INT and DIV.FRAC (“Fractional part of clock divisor. First-order delta-sigma”)
  3. STMicroelectronics, stm32f4xx-hal-driver, Inc/stm32f4xx_hal_adc.h — ExternalTrigConv sources such as ADC_EXTERNALTRIGCONV_T1_CC1 … T8_TRGO with ExternalTrigConvEdge rising/falling; ScanConvMode sequencer; ContinuousConvMode; EOCSelection per conversion (ADC_EOC_SINGLE_CONV) or per sequence (ADC_EOC_SEQ_CONV); overrun detection needs interrupt or DMA mode
  4. Raspberry Pi Ltd, pico-examples, adc/dma_capture/dma_capture.c — adc_fifo_setup with DREQ enabled and byte_shift; a DMA channel paced by DREQ_ADC moves 1000 samples into capture_buf while the CPU waits