/** * @file convert.c * @author xxx * @date 2023-08-30 08:58:43 * @brief 此文件实现数据处理、转换等功能 * @copyright Copyright (c) 2023 by xxx, All Rights Reserved. */ #include "../inc/convert.h" #include "../inc/params.h" #include "board.h" #include #include "eeprom_fm24.h" #include "mode.h" static float32 last_travel = 0; // 上次目标值 /** * @brief 判断运行方向 * @return {*} * @note */ void adjust_target_direction(void) { // 计算 actual_travel 和 target_travel 的误差 target_actual_diff = pid_target - pid_actual; // 通过当前行程和目标行程来判断移动方向 if (target_actual_diff >= 0) { target_direction = 1; } else { target_direction = 0; } } /** * @brief 获取显示行程 * @param {float32} in - 行程百分比 * @return {float32} 显示行程 * @note */ float32 get_show_travel(float32 in) { float32 travel = in; if (uDevice.eTravelDispMode == TRAVEL_DISPLAY_REVERSE) // 反向显示 { travel = 100 - travel; } return travel; } /** * @brief 获取PID控制行程 * @param {float32} in - 行程百分比 * @return {float32} PID控制行程 * @note */ float32 get_pid_travel(float32 in) { float32 travel = in; if (uDevice.eAirAction == ATC) // 气关 { travel = 100 - travel; } return travel; } /** * @brief 实际行程处理 * @param {float32} in - 实际行程 * @return {*} * @note */ float32 actual_travel_deal(float32 in) { float32 travel = in; if (!is_manual_test()) { // SWO输出 swo_output_deal(travel); // PWM输出阀位占空比 pwm_output_deal(travel); } return travel; } /** * @brief PWM输出处理 * @param {float32} in - 行程百分比 * @return {*} * @note */ void pwm_output_deal(float32 in) { float32 travel = in; if (uDevice.mAOutputEnable == true) // pwm输出使能 { pwm_output_position(travel); } } void swo_output_deal(float32 in) { float32 travel = in; if (uDevice.eSWTriggerLogic[0] == TRIGGER_LOGIC_BELOW) { if (travel < uDevice.SWTriggerValue[0]) SWO1_OPEN(); else SWO1_CLOSE(); } else if (uDevice.eSWTriggerLogic[0] == TRIGGER_LOGIC_ABOVE) { if (travel > uDevice.SWTriggerValue[0]) SWO1_OPEN(); else SWO1_CLOSE(); } else { SWO1_CLOSE(); } if (uDevice.eSWTriggerLogic[1] == TRIGGER_LOGIC_BELOW) { if (travel < uDevice.SWTriggerValue[1]) SWO2_OPEN(); else SWO2_CLOSE(); } else if (uDevice.eSWTriggerLogic[1] == TRIGGER_LOGIC_ABOVE) { if (travel > uDevice.SWTriggerValue[1]) SWO2_OPEN(); else SWO2_CLOSE(); } else { SWO2_CLOSE(); } } /** * @brief 目标行程处理 * @param {float32} in - 行程百分比 * @return {float32} 目标行程 * @note */ float32 target_travel_deal(float32 in) { float32 travel = in; // 小信号切除 travel = small_signal_deal(travel); // 死区处理 travel = dead_zone_deal(travel); // 分程处理 travel = part_travel_deal(travel); return travel; } /** * @brief 分程处理 * @param {float32} *in - 行程百分比 * @return {*} * @note */ float32 part_travel_deal(float32 in) { float32 travel = in; float32 min = uDevice.PartTravelMin; float32 max = uDevice.PartTravelMax; if (uDevice.PartTravelEnable == true) // 部分行程 { travel = (max - min) * travel * 0.01f + min; } return travel; } /** * @brief 死区处理 * @param {float32} in * @return {*} * @note */ float32 dead_zone_deal(float32 in) { float32 travel = in; float32 target_diff = fabsf(travel - last_travel); if (target_diff >= uDevice.TravelDead) { last_travel = travel; } return last_travel; } /** * @brief 小信号切除 * @param {float32} *in - 行程百分比 * @return {*} * @note */ float32 small_signal_deal(float32 in) { float32 travel = in; float32 SmallSignalLower = 0; float32 SmallSignalUpper = 0; if (uDevice.SmallSignalCutEnable > 0) // 使能,使用设定值 { SmallSignalLower = uDevice.SmallSignalLower; SmallSignalUpper = uDevice.SmallSignalUpper; } else // 禁用,使用默认值 { SmallSignalLower = 0; SmallSignalUpper = 100; } // 最大最小需要快速的反应 if (travel >= SmallSignalUpper) // 上限 { travel = 100.0; } else if (travel <= SmallSignalLower) // 下限 { travel = 0; } return travel; } /** * @brief 4~20mA输入电流转换成需要控制的阀门开度(不是显示的开度) %(1位小数,如 0~100%, 100% = 1000) * @param {float32} in 当前输入的电流值 * @return {float32} 阀门开度 - 百分比 */ float32 i2psb(float32 in) { float32 deltI, ftmp; float32 travel; uint16_t index; if (in < LOOP_CURRENT_MIN) { return 0; } else { // 计算相邻两个点之间的电流差值 deltI = uDevice.InputIH - uDevice.InputIL; deltI /= 16; // 判断输入电流在哪个范围内 ftmp = in - LOOP_CURRENT_MIN; index = ftmp / deltI; /* 计算百分比 (I - Iindex) % = ------------- * (%[index+1]-%[index]) + %[index] deltI */ if (index > 15) { ftmp = valve_characteristics_table[uDevice.eValveCharacteristics][16]; } else { ftmp = in - LOOP_CURRENT_MIN; ftmp -= deltI * index; ftmp /= deltI; ftmp *= (valve_characteristics_table[uDevice.eValveCharacteristics][index + 1] - valve_characteristics_table[uDevice.eValveCharacteristics][index]); ftmp += valve_characteristics_table[uDevice.eValveCharacteristics][index]; } } ftmp /= 100; /* 定位器的正作用:输入信号I增大时,输出的气压增大 定位器的反作用:输入信号I增大时,输出的气压减小 */ if (uDevice.eAirAction == ATO) { // 气开 if (uDevice.eControllerAction == CONTROLLER_ACTING_NORMAL) { // 定位器正作用:电流增大->气压增大->弹簧压缩->开方向->%增大(正显示、反馈) travel = ftmp; } else if (uDevice.eControllerAction == CONTROLLER_ACTING_REVERSE) { // 定位器反作用:电流增大->气压减小->弹簧释放->关方向->%减小(正显示、反馈) travel = 100 - ftmp; } else { travel = ftmp; } } else { // 气关 if (uDevice.eControllerAction == CONTROLLER_ACTING_NORMAL) { // 定位器正作用:电流增大->气压增大->弹簧压缩->关方向->%减小(正显示、反馈) travel = 100 - ftmp; } else { // 定位器反作用:电流增大->气压减小->弹簧释放->开方向->%增大(正显示、反馈) travel = ftmp; } } if (travel < 0) travel = 0; else if (travel > 100) travel = 100; return travel; } /** * @brief 温度值转换:摄氏度转华氏度 * @param {float32} celsius 摄氏度 * @return {float32} 华氏度 * @note */ float32 temperature_c2f(float32 celsius) { float32 temp = 32 + celsius * 1.8f; return temp; } /** * @brief 压力值转换,kPa -> mPa psi bar kgf/cm2 * @param {float32} kpa 压力值 kPa * @param {uint16_t} unit 要转换的单位 * @return {float32} 转换后的压力值 * @note */ float32 pressure_kpa2unit(float32 kpa, uint16_t unit) { float32 pre = 0; switch (unit) { case PRESSURE_UNIT_Kpa: // kPa pre = kpa; break; case PRESSURE_UNIT_Mpa: // mPa pre = kpa * 0.001f; break; case PRESSURE_UNIT_Psi: // psi pre = kpa * 0.145037743897f; break; case PRESSURE_UNIT_Bar: // bar pre = kpa * 0.01f; break; case PRESSURE_UNIT_Kgf: // kgf/cm2 pre = kpa * 0.0101972f; break; default: pre = kpa; break; } return pre; }