ADC-based current calibration: low-current error increases despite correct full-scale calibration

This is running on a PIC16F18313.

typedef struct {

uint16_t adc_th; // ADC diff threshold

uint16_t k_q10; // Q10 gain

} seg_cal_t;

seg_cal_t seg[4] = {

{ 200, 1180 },

{ 450, 1120 },

{ 650, 1060 },

{ 0xFFFF, 1024 }

};

static inline void update_pwm(int16_t diff, uint16_t span_adc)

{

if (diff < 0) diff = 0;

if (diff <= 1) return;

if (span_adc < MIN_VALID_RANGE) span_adc = MIN_VALID_RANGE;

uint32_t v_mV = (uint32_t)diff * 825u / span_adc;

uint16_t k_q10;

if (diff < seg[0].adc_th) k_q10 = seg[0].k_q10;

else if (diff < seg[1].adc_th) k_q10 = seg[1].k_q10;

else if (diff < seg[2].adc_th) k_q10 = seg[2].k_q10;

else k_q10 = seg[3].k_q10;

v_mV = (v_mV * k_q10) >> 10;

uint32_t duty = v_mV * g_pwm_full / 3300u;

duty = (duty * g_vgain_q10) >> 10;

CCP1_LoadDutyValue((uint16_t)duty);

}

Observation

The figure below compares equivalent current (true input current) with the current value reported by the module (MP).

  • Blue line: Ideal behavior (y = x)

  • Orange curve: Actual measured output of the current-sensing module

Key observation:

  • The system is accurate near 50A (calibration point)

  • As current decreases, the displayed value becomes systematically lower

  • The error increases toward low current, indicating non-linearity rather than noise


Measured Data Points

Equivalent Current MP Display Error Error Rate
50 A ~50 A 0 A 0%
40 A ~36 A −4 A −10%
30 A ~22 A −8 A −27%

Error characteristics:

  1. Systematic bias (not random noise)

  2. Error magnitude increases as current decreases

  3. High-current region is accurate

  4. Low-current region is strongly compressed

The current implementation uses:

  • Zero-offset calibration at 0 A

  • Single-point dynamic calibration at 50 A

  • Piecewise gain correction using segment-specific multipliers

Mathematically, the current model is:

y = k(segment) × x

This allows only slope adjustment (curve rotation).

However, the plotted result clearly shows that:

  • The error is not purely a slope error

  • The curve is shifted downward at low current

  • Increasing k in low-current segments fixes 30A but causes over-scaling at 50A

This indicates a missing intercept (offset) term, not just a gain mismatch.