/**@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 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; }