Increasing the Accuracy of ADC Measurements Using the Two-Point Calibration Approach

Two-Point Calibration for Any ADC (Code-Space Version)

This Tutorial guides you through the process of drastically increasing your ADC circuit's measurement accuracy using the Two-Point Calibration method. To perform this calibration you will need a high accuracy voltage source or voltmeter to monitor the output of a low accuracy voltage source. It is recommended that the high accuracy voltage source or volt meter has at least 4x better accuracy than the ADC circuit it is being used to calibrate. The resulting readings of the two-point calibration approach are then implemented in a reading correction algorithm that is deployed in the firmware used with the ADC being calibrated. 


1) Model the ideal ADC and ADC error contributors in code space

Below you will find formula's and a chart that model the two main types of ADC error. The model also includes the ideal behaviour of our example 4 bit ADC as well as its quantization levels (2^4 = 16 quantization levels). Let the ideal (continuous) input be Cin (in codes) and the ADC output be C (in codes).

  • Ideal (no errors): C = Cin
  • Gain error only: Cg = (1 + g) * Cin
  • Offset error only: Co = Cin + Coff

In our example 4-bit ADC chart below we can see the desired ideal curve, in blue, of the ADC through its entire range. Note that the ideal curve directly fits on the top of the quantization steps as expected. In the ideal case the only error in each ADC reading is caused by the quantization steps being finite. The curve in orange represents the ADC curve with some type of static gain error source. The curve in green represents the ADC curve with some type of static offset error source. Since these error sources are static or constant we can use the two-point calibration approach to cancel them out in firmware.


2) Two-point calibration (solve one line)

Fit a line that maps raw codes (Craw) that have some gain (m) and offset (b) error associated with them to true codes:

Ctrue = m * Craw + b

Measure two well-separated points:

  • Low point of ADC curve or range: apply a known input (ideal code Cin_L), take multiple ADC readings and average them together to get  → Craw_L
  • High point of ADC curve or range: apply a known input (ideal code Cin_H), take multiple ADC readings and average them together to get  → Craw_H

Compute the gain and offset correction coefficients:

m = (Cin_H - Cin_L) / (Craw_H - Craw_L)
b = Cin_L - m * Craw_L

Apply in your ADC control firmware at runtime to every new raw ADC reading:

Ccal = m * Craw + b

What this fixes (in code units)

  • Gain-only error (Craw = (1 + g) * Cin) ⇒ m = 1 / (1 + g), b = 0Ccal = Cin
  • Offset-only error (Craw = Cin + Coff) ⇒ m = 1, b = -CoffCcal = Cin

3) Practical lab recipe (works for any ADC front end)

  1. Warm-up & settle: Power up the circuit and let the reference and analog front end stabilize.
  2. Pick two inputs: choose Cin_L and Cin_H far apart (~10% and ~90% of span).
  3. Average generously: take 512–4096 samples at each point to get Craw_L and Craw_H. The more samples the more you cancel out the affects of random noise sources.
  4. Compute m and b: use the formulas above; store with channel/range IDs.
  5. Use in firmware: Ccal = m * Craw + b for all future readings.
  6. Temperature plan: re-cal on large ΔT or keep multiple (m,b) pairs vs. temperature.

4) One-function pseudo-code (inputs: current reading + the two calibration pairs)

function TwoPointCalibrateCode(
    C_raw_now,      # current raw ADC code
    Cin_L, Craw_L,  # low calibration pair (ideal code, averaged raw code)
    Cin_H, Craw_H,  # high calibration pair (ideal code, averaged raw code)
    Cmin, Cmax      # legal output code range (e.g., 0, 2^N - 1)
) -> C_cal_now:

    # 1) Sanity checks
    if (Cin_H == Cin_L) or (Craw_H == Craw_L):
        return clamp(C_raw_now, Cmin, Cmax)

    # 2) Solve slope and intercept in code space
    m = (Cin_H - Cin_L) / (Craw_H - Craw_L)
    b = Cin_L - m * Craw_L

    # 3) Apply to current reading
    C_cal_now = m * C_raw_now + b

    # 4) Optional: round to nearest code
    # C_cal_now = round(C_cal_now)

    # 5) Optional: clamp to range
    C_cal_now = clamp(C_cal_now, Cmin, Cmax)

    return C_cal_now

Note: You can compute m and b once and reuse them.


5) Error intuition (code units)

  • Gain error: eg(Cin) = Cg - C = g * Cin (grows linearly with input)
  • Offset error: eo(Cin) = Co - C = Coff (constant vertical shift)

6) Checklist & tips

  • Keep calibration points away from the rails (~10–90% of span).
  • Average a lot during calibration; you pay this cost once and it suppresses transition noise.
  • Maintain separate (m,b) per channel and per range.
  • Store metadata: channel/range ID, date, temperature, etc.

External Reference

Texas Instruments – “Understanding and calibrating ADC offset and gain” (TI Precision Labs / Data Converters).

Back to blog