966 字
5 分钟
基于 STM32 的最小二乘法二次曲线拟合应用
一、 背景概述
在工业传感器应用中,精确度是系统的核心指标。由于传感器材料特性、非线性响应或环境干扰,其输出往往呈现非线性偏移。为了矫正这些误差,通常需要通过**标定(Calibration)**过程推导出一条修正曲线。
在 PC 端,我们可以轻松调用复杂的矩阵运算库进行拟合,但在嵌入式系统(如 STM32)中,内存和主频资源有限。如何在不移植大型矩阵库的前提下,高效、高精度地实现二次曲线拟合?本文将分享一种优化的代数解析法,直接在 STM32F4 上实现实时标定。
二、 数学模型:最小二乘法二次拟合
我们的目标是找到一组系数 ,使得拟合出的二次多项式 与实际观测点 的误差平方和最小:
根据最小二乘法原理,通过对误差函数求偏导并令其为零,可以得到正规方程组(Normal Equations):
由于阶数较低(二次),我们可以通过**克莱姆法则(Cramer’s Rule)**推导出系数的直接解析表达式,从而避开复杂的矩阵求逆运算。
三、 解决方案与工程实现
1. 硬件加速建议
STM32F4 系列具备 FPU(浮点运算单元)。在编译器设置中,请务必开启硬浮点运算(Hardfp),这将使 double 和 float 的运算速度提升数倍。
2. 优化后的 C 语言实现
原代码中频繁调用 pow() 函数会消耗大量的 CPU 周期,优化方案改用累乘,并加入 FPU 友好的数据类型。
/** * @brief 二次曲线拟合计算函数 * @param x: 传感器采集数据数组 * @param y: 标准输出数据数组 * @param n: 数据点个数 */void fit_quadratic_curve(double *x, double *y, int n) { double s0 = n; double s1 = 0, s2 = 0, s3 = 0, s4 = 0; // x的幂次方累加 double t0 = 0, t1 = 0, t2 = 0; // y与x幂次方的乘积累加
for (int i = 0; i < n; i++) { double x1 = x[i]; double x2 = x1 * x1; double x3 = x2 * x1; double x4 = x3 * x1; double y1 = y[i];
s1 += x1; s2 += x2; s3 += x3; s4 += x4;
t0 += y1; t1 += y1 * x1; t2 += y1 * x2; }
// 计算分母行列式 (通过解析化简提高实时性) double det = s0 * (s2 * s4 - s3 * s3) - s1 * (s1 * s4 - s2 * s3) + s2 * (s1 * s3 - s2 * s2);
if (fabs(det) < 1e-12) return; // 防止除零错误
// 克莱姆法则求解系数 a0 = (t0 * (s2 * s4 - s3 * s3) - t1 * (s1 * s4 - s2 * s3) + t2 * (s1 * s3 - s2 * s2)) / det; a1 = (s0 * (t1 * s4 - t2 * s3) - s1 * (t0 * s4 - t2 * s2) + s2 * (t0 * s3 - t1 * s2)) / det; a2 = (s0 * (s2 * t2 - s3 * t1) - s1 * (s1 * t2 - s3 * t0) + s2 * (s1 * t1 - s2 * t0)) / det;}四、 性能评估与应用考量
- 运算效率:在开启 FPU 的 STM32F407 上,计算 7 个点的二次拟合耗时在微秒级,完全满足在线实时标定的要求。
- 内存占用:由于避开了 Eigen 或 Arm_Math 等大型库,该函数仅占用极少量堆栈,非常适合 RAM 资源紧张的单片机环境。
- 稳定性:当数据点 跨度过小或趋于线性时,行列式
det可能趋于 0,代码中加入了防除零保护。
五、 结论
通过解析法实现最小二乘法二次曲线拟合,是在嵌入式系统中平衡“计算精度”与“系统开销”的最优解。在传感器标定、电池 SOC 估算、电机参数辨识等领域,该算法能显著提升系统的智能化水平。
基于 STM32 的最小二乘法二次曲线拟合应用
https://hw.rscclub.website/posts/stm32zxecfsf/