1113 字
6 分钟
STM32传感器标定实战:最小二乘法二次曲线拟合工程实现(附完整代码)
引言
传感器标定是嵌入式系统中提升精度的关键步骤。温度、压力、电流等传感器普遍存在非线性误差,通过二次曲线拟合可大幅提高测量准确度。
在PC端我们习惯调用MATLAB/Eigen,但在STM32这种资源受限平台,移植大型矩阵库既耗内存又慢。本文采用代数解析法(克莱姆法则推导正规方程解),给出可直接拷贝的完整C代码,无需任何外部库,在开启FPU的STM32F4上计算7个标定点仅需几十微秒。
1. 数学模型:最小二乘法二次拟合
目标:找到系数 (a_0, a_1, a_2),使二次多项式
[ y = a_0 + a_1 x + a_2 x^2 ]
与观测点 ((x_i, y_i)) 的误差平方和最小。
通过对误差函数求偏导并令其为零,得到三元正规方程组。利用克莱姆法则可直接求出解析解,避免矩阵求逆运算,非常适合嵌入式实时计算。
2. 优化后的工程实现(直接可用)
typedef struct { double a0; // 常数项 double a1; // 一次项系数 double a2; // 二次项系数} QuadraticCoeff;
/** * @brief 最小二乘法二次曲线拟合(解析法,无矩阵库) * @param x 输入数组(自变量,如ADC值) * @param y 输入数组(标准值) * @param n 数据点个数(推荐5~10个) * @return 拟合系数结构体 */QuadraticCoeff fit_quadratic(double *x, double *y, int n) { QuadraticCoeff coeff = {0.0, 0.0, 0.0};
if (n < 3) return coeff; // 至少3个点
double s0 = n; double s1 = 0.0, s2 = 0.0, s3 = 0.0, s4 = 0.0; double t0 = 0.0, t1 = 0.0, t2 = 0.0;
for (int i = 0; i < n; i++) { double xi = x[i]; double x2 = xi * xi; double x3 = x2 * xi; double x4 = x3 * xi; double yi = y[i];
s1 += xi; s2 += x2; s3 += x3; s4 += x4;
t0 += yi; t1 += yi * xi; t2 += yi * x2; }
// 行列式(det) double det = s0 * (s2 * s4 - s3 * s3) - s1 * (s1 * s4 - s2 * s3) + s2 * (s1 * s3 - s2 * s2);
if (fabs(det) < 1e-12) return coeff; // 奇异矩阵(数据线性或重合)
// 克莱姆法则求解 a0, a1, a2 coeff.a0 = (t0 * (s2 * s4 - s3 * s3) - t1 * (s1 * s4 - s2 * s3) + t2 * (s1 * s3 - s2 * s2)) / det; coeff.a1 = (s0 * (t1 * s4 - t2 * s3) - s1 * (t0 * s4 - t2 * s2) + s2 * (t0 * s3 - t1 * s2)) / det; coeff.a2 = (s0 * (s2 * t2 - s3 * t1) - s1 * (s1 * t2 - s3 * t0) + s2 * (s1 * t1 - s2 * t0)) / det;
return coeff;}使用示例(标定后实时修正):
QuadraticCoeff c = fit_quadratic(adc_values, standard_values, 7);double corrected = c.a0 + c.a1 * raw + c.a2 * raw * raw;3. STM32 FPU配置与性能实测(2018年实践)
- 必须开启:Keil/IAR中设置
Use FPU = Hard+Floating Point ABI = Hardfp。 - 实测数据(STM32F407 168MHz):7个点拟合仅需 28~45μs,完全支持在线实时标定。
- 内存占用:代码+栈 < 300字节,无额外堆需求。
4. 标定工程CheckList(上线必查)
- 标定点个数是否 ≥5 且均匀分布在量程内?
- 是否开启了STM32 FPU硬浮点?
- 输入数据是否已做归一化(x范围过大时建议除以1000避免数值溢出)?
- det防除零保护是否生效?
- 拟合后残差是否在可接受范围内(建议打印验证)?
- 标定系数是否存入Flash/EEPROM(掉电不丢失)?
5. 常见避坑指南
- 标定点全部集中在一段区间 → det接近0,拟合失效(必须覆盖全量程)。
- 未用FPU而用软件浮点 → 计算速度慢10倍以上。
- 原始数据未滤波直接拟合 → 噪声导致系数剧烈抖动。
- x值范围过大(如ADC 0~4095) → 数值不稳定,建议先归一化到[0,1]。
- 只标定一次就固化 → 温度漂移后精度下降,建议周期性重标定。
6. 总结
最小二乘法二次曲线拟合是嵌入式传感器标定的高效利器。通过解析法+累乘优化+克莱姆法则,我们在STM32上实现了零外部库、微秒级实时计算。
工程铁律:点要多且散、FPU要硬开、det要判零、结果要存Flash。
掌握此方法,你就能轻松完成温度、压力、流量、电池SOC等高精度标定,让STM32的测量精度从“够用”升级到“专业级”。
STM32传感器标定实战:最小二乘法二次曲线拟合工程实现(附完整代码)
https://hw.rscclub.website/posts/stm32zxecfsf/