123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899 |
- /**@Doxygen风格注释
- * @file calib_piecewise_linear.c
- * @brief 电容值到油水比例的标定模块(分段线性插值)
- * @details
- * 本模块用于将电容传感器测量的电容值(单位:pF)转换为对应的油水混合比例百分比(单位:%)。
- * 采用 **分段线性插值法** 实现高精度估算。
- *
- * @section 功能特性
- * - 固定11个标定点,百分比范围为90% ~ 100%,每隔1%一个点
- * - 每个百分比点对应一个电容值,按降序排列(电容越小表示油越多)
- * - 使用线性插值法对任意电容值进行估算
- * - 超出标定范围的电容值自动限幅到0%或100%
- * - 支持结构体打包,将 float 电容值转换为 uint32_t,用于Flash存储
- *
- * @section 数据结构
- * - @c CalibPoints_t : 存储11个电容标定点及magic码
- * - @c uint_CalibPoints_t : 与CalibPoints_t等价的整型形式(用于Flash存取)
- * - @c Calib_residual_oil_t : 存储余油电容/压力/高度标定(与主功能无直接关系)
- * - @c Calib_rod_t : 阀杆电压标定(与主功能无直接关系)
- *
- * @section 使用示例
- * @code
- * Load_Default_CalibPoints(); // 加载默认电容标定点
- * float cap = read_sensor_capacitance(); // 读取电容值
- * float percent = Estimate_Percentage_piecewise(cap); // 转换为油水百分比
- * @endcode
- *
- * @note
- * - 标定点对应的百分比是固定的,不在结构体中存储,而是以 const 数组形式保存在代码段
- * - 所有标定点应按 cap 值降序排列(从90%到100%)
- *
- * @author
- * 开发者:
- *
- * @date 2025年8月
- */
- #include "Callback.h"
- #include "calib_piecewise_linear.h"
- #include "FLASH.h"
- #include "main.h"
- #include <string.h>
- CalibPoints_t g_calibPoints; // 油水检测电容float
- Calib_residual_oil_t g_Calibresidualheight; // 余油检测电容值压力值高度值float
- OilType g_oil_type = OIL_95; // 油品
- Calib_rod_t g_Calibrodvol; // 阀杆电压值
- // ========================
- // 标定油水数据点(按百分比升序排列)
- // ========================
- const float calib_cap_values[CALIB_POINT_NUM] = { // 电容值(pf)
- 54.993f, 54.986f, 54.979f, 54.971f, 54.962f, 54.955f, 54.947f, 54.939f, 54.925f, 54.911f, 54.901f};
- const float calib_percent_values[CALIB_POINT_NUM] = { // 百分比%
- 90.0f, 91.0f, 92.0f, 93.0f, 94.0f, 95.0f, 96.0f, 97.0f, 98.0f, 99.0f, 100.0f};
- // 初始化默认值函数
- void Load_Default_CalibPoints(void)
- {
- for (int i = 0; i < CALIB_POINT_NUM; i++) {
- g_calibPoints.cap_values[i] = calib_cap_values[i];
- }
- }
- // ========================
- // 分段线性插值估算百分比(带限幅)
- // ========================
- float Estimate_Percentage_piecewise(float cap)
- {
- const float *caps = g_calibPoints.cap_values;
- const float *percents = calib_percent_values;
-
- // 边界处理
- if (cap <= caps[CALIB_POINT_NUM - 1]) return 100.0f;
- if (cap >= caps[0]) return 90.0f;
- for (int i = 0; i < CALIB_POINT_NUM - 1; i++) {
- float cap_high = caps[i];
- float cap_low = caps[i + 1];
- if (cap <= cap_high && cap >= cap_low) {
- float percent_high = percents[i];
- float percent_low = percents[i + 1];
- float percent = percent_low + (cap - cap_low) * (percent_high - percent_low) / (cap_high - cap_low);
- // 限幅
- if (percent < 0.0f) percent = 0.0f;
- if (percent > 100.0f) percent = 100.0f;
- return percent;
- }
- }
- return 0.0f;
- }
|