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:
-
Systematic bias (not random noise)
-
Error magnitude increases as current decreases
-
High-current region is accurate
-
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
kin low-current segments fixes 30A but causes over-scaling at 50A
This indicates a missing intercept (offset) term, not just a gain mismatch.
