Load-cell virtual qualification
Executed thermal/load corners, contaminated-calibration rejection, correlated uncertainty, aliasing and zero-tracking fault cases using synthetic data.
Methods and declared inputs
The original 10 kg bridge, 100 Hz sample rate and 25-sample moving average are retained. The corner study adds temperature changes of -10, 0 and +10 C, masses 0/2/5/10 kg, both hysteresis directions and 1.2 g of accumulated drift at 60 s.
The corner criterion is an explicitly selected +/-5 g screen: the empirical 95th percentile of absolute error must be <=5 g. It is not a legal metrology class or a promise of device accuracy. Each corner contains 20,000 generated observations; the first 100 filtered samples are discarded.
Selected synthetic operating envelope: temperature remains within +/-2 C of calibration, zero is established at most 30 s before the reading, and the 25-sample filter is allowed 0.25 s to settle. Sixteen independent-seed load/temperature/direction corners meet the same 5 g screen. Exact extrema of the assumed sinusoidal systematic-error curve, plus 1.96 filtered-noise standard deviations, also bound the entire 0-10 kg interval below 5 g for this generated calibration. The wider +/-10 C, 60 s cases are rejected where they exceed it.
The calibration diagnostic checks mean residual at each mass, rejecting a group exceeding 2 g. This is a completed synthetic acceptance gate for the declared dataset, not a universal detector of bad calibration. Common-mode reference-mass error or a perfectly linear span error can pass residual tests.
The shared-temperature study gives 1.913 g standard uncertainty and 3.826 g expanded uncertainty at k=2 and 5 kg. It uses a separate generated calibration and analytical filter noise. The uncertainty experiment draws 50,000 independent synthetic realizations of all budget terms. Zero and span temperature terms share one rectangular random variable, so their covariance is explicit. k=2 coverage is reported empirically for this assumed error distribution only.
The aliasing example is a 20 g-amplitude, 93 Hz interference tone sampled at 100 Hz. A hypothetical analog filter has two identical 10 Hz first-order poles. Its exact complex response is applied before sampling. Digital averaging acts after aliasing and cannot identify the original frequency.
Executed cases
| mass_g | temperature_change_c | direction | drift_at_60_s_g | systematic_mean_error_g | absolute_error_95th_g | meets_reference_5_g |
|---|---|---|---|---|---|---|
| 0.0 | -10.0 | unloading | 1.2 | -0.9761582614551035 | 1.622741236104428 | True |
| 0.0 | -10.0 | loading | 1.2 | 1.0487484663084086 | 1.7358560259156148 | True |
| 0.0 | 0.0 | unloading | 1.2 | 0.5397450652623738 | 1.1783282776240036 | True |
| 0.0 | 0.0 | loading | 1.2 | 2.527818966938422 | 3.145889574464258 | True |
| 0.0 | 10.0 | unloading | 1.2 | 2.045677699700335 | 2.7056271559036227 | True |
| 0.0 | 10.0 | loading | 1.2 | 4.027812189609848 | 4.67251153373407 | True |
| 2000.0 | -10.0 | unloading | 1.2 | -0.11728983107811757 | 0.844244317780317 | True |
| 2000.0 | -10.0 | loading | 1.2 | 1.8727735736687559 | 2.52052309574226 | True |
| 2000.0 | 0.0 | unloading | 1.2 | 1.5505760037446201 | 2.196353872977204 | True |
| 2000.0 | 0.0 | loading | 1.2 | 3.57563990815993 | 4.229981779982301 | True |
| 2000.0 | 10.0 | unloading | 1.2 | 3.259236410575387 | 3.9348566432641174 | True |
| 2000.0 | 10.0 | loading | 1.2 | 5.265432614386661 | 5.916931490457034 | False |
| 5000.0 | -10.0 | unloading | 1.2 | 0.22985555792016152 | 0.9046311273572427 | True |
| 5000.0 | -10.0 | loading | 1.2 | 2.2254222237168824 | 2.885594820451888 | True |
| 5000.0 | 0.0 | unloading | 1.2 | 2.2186489897077712 | 2.8722116484677827 | True |
| 5000.0 | 0.0 | loading | 1.2 | 4.207678503131792 | 4.850492865785054 | True |
| 5000.0 | 10.0 | unloading | 1.2 | 4.206667997018038 | 4.871812276205719 | True |
| 5000.0 | 10.0 | loading | 1.2 | 6.233318568548072 | 6.891987950223165 | False |
| 10000.0 | -10.0 | unloading | 1.2 | -2.571494236685728 | 3.2496212384493446 | True |
| 10000.0 | -10.0 | loading | 1.2 | -0.6021433151895119 | 1.2738572862406725 | True |
| 10000.0 | 0.0 | unloading | 1.2 | -0.06848550430309185 | 0.7776960418234921 | True |
| 10000.0 | 0.0 | loading | 1.2 | 1.907395548852018 | 2.5799869811869938 | True |
| 10000.0 | 10.0 | unloading | 1.2 | 2.4339447560583056 | 3.0853332956624397 | True |
| 10000.0 | 10.0 | loading | 1.2 | 4.405813013947655 | 5.034144054444914 | False |
Acceptance checks
| id | description | expected | observed | passed | method |
|---|---|---|---|---|---|
| thermal-count | All declared thermal/load/direction corners executed | 24 | 24 | True | 4 masses x 3 temperatures x 2 loading directions |
| thermal-failures | Aligned thermal/systematic error can exceed 5 g | At least one adverse corner | 3 | True | Declared +/-5 g screening criterion on 95th absolute error; failures retained |
| selected-envelope | Selected temperature/time envelope meets the error screen | All 16 corners <= 5 g | 4.701848058270707 | True | Independent seed; +/-2 C since calibration and <=30 s drift; both hysteresis directions |
| continuous-envelope | Selected mass range satisfies a continuous theoretical bound | Conservative 95% absolute-error bound <= 5 g | {'worst_systematic': {'mass_g': 4788.088588382688, 'temperature_change_c': 2.0, 'direction': 1, 'mean_error_g': 4.027639087022941}, 'filtered_noise_std_g': 0.39981535588755024, 'conservative_95pct_absolute_error_g': 4.811262785028603} | True | Solve exact extrema of the declared sinusoidal error curve; add 1.96 filtered-noise standard deviations |
| calibration-valid | Uncontaminated batch passes residual gate | True | True | True | 2 g maximum mean residual at each calibration mass |
| calibration-corrupt | Biased mass group is rejected | Both 10 g and 50 g injected biases rejected | [False, False] | True | Inject group-wide offset into 30 readings at 8 kg; fit with original OLS implementation |
| covariance | Shared temperature source increases variance | Correlated budget greater than independent | {'independent_g': 1.777736266947072, 'correlated_g': 1.9132031347504401} | True | Add 2*u_zero*u_span for the shared rectangular temperature variable |
| monte-carlo | Synthetic correlated uncertainty agrees with analytic variance | Standard deviation difference < 2% | 5.582826424710419e-06 | True | 50000 seeded draws; all bounds and correlation explicit |
| alias-frequency | Sampled 93 Hz tone aliases to 7 Hz | Dominant discrete frequency 7 Hz | 7.0 | True | 100 Hz acquisition, frequency folding f_alias = abs(93 - 100) |
| analog-suppression | Declared analog filter reduces the aliased amplitude | RMS ratio agrees with transfer magnitude within 1e-8 | 0.011429877700308608 | True | H(f)=(1+j*f/10)^-2; two identical 10 Hz RC poles |
| zero-confirmation | Correct empty-pan gate preserves a real 2 g load | 0.0 | 0.0 | True | 300 updates with empty confirmation false |
| wrong-confirmation | False empty confirmation absorbs a real load | Offset exceeds 1.9 g | 1.9953349886640968 | True | Same updates with deliberately incorrect external empty indication; adverse result |
Scope of the evidence
This completes the theoretical and synthetic qualification run-through. No real bridge, ADC, temperature chamber, weights or calibration certificate was used.
The analog filter is an ideal transfer function, not a released circuit. ADC common-mode limits, reference tracking, component tolerances, EMI and physical overload survival are not established by this model.
Systematic effects can align rather than cancel. The failed thermal corners remain visible; a small white-noise standard deviation does not guarantee a small total error.
Zero tracking still depends on a trustworthy external empty-pan indication. The simulation shows why a false confirmation can remove a genuine small load.
Reproduce
python -m pip install -r requirements.txt python run.py
Acceptance matrix · Evidence record and source hashes · Original analysis
16 verified selected-envelope corners
All 24 temperature/load corners
Calibration contamination cases