/** * @file mode.c * @author xxx * @date 2023-09-18 10:00:52 * @brief 此文件用于实现不同工作模式的功能 * @copyright Copyright (c) 2023 by xxx, All Rights Reserved. */ #include #include "app.h" #include "main.h" #include "filter.h" #include "mode.h" mode_params_t mode_params; // 模式参数 volatile static uint8_t last_work_mode = 0xff; // 上一次的工作模式 volatile static uint8_t manual_test_flag = FALSE; // 手动测试模式 volatile static BOOL mode_control_state = FALSE; // TRUE:算法控制器可以运行 FALSE:算法控制器不可以运行 volatile static uint8_t alog_control_count = 0; // 算法控制计数器 lpf_t show_actual_lpf; /** * @brief 改变自动重装载寄存器的值 * @param {uint8_t} autoload * @return {*} * @note */ static void mode_autoload_change(uint8_t autoload) { LL_TIM_SetAutoReload(TIM7, autoload); } /** * @brief 工作模式参数保存,回调处理 * @return {*} * @note */ static void mode_params_save_cb(void) { fal_execution_kv_write(KEY_MODE_PARAM, (uint8_t *)&mode_params, sizeof(mode_params_t)); } static void set_manual_test(BOOL status) { manual_test_flag = status; } /** * @brief * > 在线模式:根据4~20ma控制阀位 * > 离线模式:根据hart指令控制阀位 * @return {*} * @note */ static void online_offline_mode_adjust(void) { mode_control_state = TRUE; } /** * @brief 待机模式:DCS专用,阀门保持现状,定位器正常工作,不接收外部信号 * @return {*} * @note */ static void wait_mode_adjust(void) { mode_control_state = TRUE; } /** * @brief 按键测试模式 * @return {*} * @note */ static void manual_test_mode(void) { set_manual_test(TRUE); mode_control_state = TRUE; } BOOL is_manual_test(void) { return (manual_test_flag == TRUE) ? TRUE : FALSE; } /** * @brief 行程统计(100ms以上运行一次) * @return {*} * @note */ void travel_statistics(void) { static float32 loop_current_last = 0.0f; // 上一次的电流 static uint8_t change_count = 0; // 输入电流 loop_current = get_current(); loop_current = get_current_deal(loop_current); if (loop_current_last != loop_current) // 过滤掉不稳定的电流值 { if (change_count++ >= 2) { loop_current_last = loop_current; change_count = 0; } else { return; } } else { change_count = 0; } // 获取目标行程 if (uDevice.WorkMode == ON_LINE_MODE) // 在线模式:根据4~20ma控制阀位 { // 目标行程 target_travel = i2psb(loop_current); } else if (uDevice.WorkMode == OFF_LINE_MODE) // 离线模式:根据hart指令控制阀位 { target_travel = uRtData.travel_target; } target_travel = target_travel_deal(target_travel); pid_target = get_pid_travel(target_travel); show_target = get_show_travel(target_travel); // 实际行程处理 actual_travel = actual_travel_deal(actual_travel); show_actual = get_show_travel(actual_travel); show_actual = lpf_update(&show_actual_lpf, show_actual); show_loop = loop_current; } /** * @brief 算法控制模块 * @return {*} * @note 该模块在TIM7中执行 */ void alog_control_module(void) { // 注: travel_statistics因为在flow中被更新,如果UI更新时会导致延时,所以在这里更新 if (alog_control_count++ >= 10) // 100ms { alog_control_count = 0; travel_statistics(); leds_toggle(LEDS_1_GREEN); } if (mode_control_state == FALSE) { // 算法控制器不可以运行 return; } // 当电流达到4mA时才进行控制 if (loop_current >= LOOP_CURRENT_MIN) { if (uDevice.SpecControlOutputMode == PDCTRL_DAC) { mode_dac_process(); } else if (uDevice.SpecControlOutputMode == PDCTRL_PWM) { mode_pwm_process(); } else if (uDevice.SpecControlOutputMode == PDCTRL_PWMP) { mode_pwmp_process(); } else if (uDevice.SpecControlOutputMode == PDCTRL_PWMP_HD) { mode_pwmp_hd_process(); } else { DBG_ASSERT(FALSE __DBG_LINE); } } else { pdctrl_out(0); } } /** * @brief 模式整定开始 * @return {*} * @note */ void mode_adjust_start(void) { switch (uDevice.SpecControlOutputMode) { case PDCTRL_DAC: break; case PDCTRL_PWM: break; case PDCTRL_PWMP: break; case PDCTRL_PWMP_HD: pwmp_hd_process_state_set(PWMP_HD_PROCESS_ADJUST); break; default: break; } } /** * @brief 模式整定停止 * @return {*} * @note */ void mode_adjust_stop(void) { switch (uDevice.SpecControlOutputMode) { case PDCTRL_DAC: break; case PDCTRL_PWM: break; case PDCTRL_PWMP: break; case PDCTRL_PWMP_HD: pwmp_hd_process_state_set(PWMP_HD_PROCESS_STOP); break; default: break; } } /** * @brief 获取整定步骤数量 * @return {*} * @note */ uint8_t mode_adjust_step_count(void) { switch (uDevice.SpecControlOutputMode) { case PDCTRL_DAC: return 0; case PDCTRL_PWM: return 0; case PDCTRL_PWMP: return 0; default: return 0; } } /** * @brief 获取当前整定步骤 * @return {*} * @note */ uint8_t mode_adjust_step_current(void) { switch (uDevice.SpecControlOutputMode) { case PDCTRL_DAC: DBG_ASSERT(mode_dac != NULL __DBG_LINE); return 0; case PDCTRL_PWM: DBG_ASSERT(mode_pwm != NULL __DBG_LINE); return 0; case PDCTRL_PWMP: return 0; default: return 0; } } /** * @brief LCD绘图前需要判断算法是否空闲 * @return {*} * @note 在死区或者棒棒控制区间可以绘图,这个功能对算法要求极高,必须在短时间内进入到死区。后面测试看效果考虑是否需要该功能 */ BOOL mode_control_idel(void) { switch (uDevice.SpecControlOutputMode) { case PDCTRL_DAC: return TRUE; case PDCTRL_PWM: return TRUE; case PDCTRL_PWMP: return TRUE; default: return FALSE; } } /** * @brief 模式处理 * @param {uint8_t} work_mode * @return {*} * @note */ void mode_detection(uint8_t work_mode) { switch (work_mode) { case ON_LINE_MODE: case OFF_LINE_MODE: online_offline_mode_adjust(); break; case WAIT_MODE: // 等待模式 wait_mode_adjust(); break; case MANUAL_TEST_MODE: // 手动测试模式 manual_test_mode(); break; // 以下状态算法不能运行 case FORBIDEN_MODE: // 禁止模式 case STOP_MODE: // 停止模式 mode_control_state = FALSE; break; default: break; } // 模式切换时各个组件工作状态的切换 if (last_work_mode != work_mode) { last_work_mode = work_mode; if (TRUE == mode_control_state) { // 按键初始化 key_init(); // LCD初始化 lcd_init(); pdctrl_run(); // 输出软使能 } else { if (work_mode == STOP_MODE) { // 禁用LCD显示 lcd_dinit(); // 禁用按键 key_dinit(); } if (work_mode == OFF_LINE_MODE) { if (uDevice.ControlMode != TRUE) // 不运行到上次位置 { uRtData.travel_target = 0; } } pdctrl_stop(); // 输出软禁止 } } if (work_mode != MANUAL_TEST_MODE) { set_manual_test(FALSE); } } /** * @brief 工作模式初始化 * @return {*} * @note */ void mode_init(void) { mode_autoload_change(mode_default_autoload); // 反初始化,释放内存 mode_dac_dinit(); mode_pwm_dinit(); mode_pwmp_dinit(); mode_pwmp_hd_dinit(); if (uDevice.SpecControlOutputMode == PDCTRL_DAC) { pdctrl_init(PDCTRL_DAC); mode_dac_init(&mode_params.mode_dac_params, mode_params_save_cb); } else if (uDevice.SpecControlOutputMode == PDCTRL_PWM) { pdctrl_init(PDCTRL_PWM); mode_pwm_init(&mode_params.mode_pwm_params, mode_params_save_cb); ///< 要放在pdctrl_init()后面执行 } else if (uDevice.SpecControlOutputMode == PDCTRL_PWMP) { pdctrl_init(PDCTRL_PWMP); mode_pwmp_init(&mode_params.mode_pwmp_params, mode_params_save_cb); } else if (uDevice.SpecControlOutputMode == PDCTRL_PWMP_HD) { pdctrl_init(PDCTRL_PWMP_HD); mode_pwmp_hd_init(&mode_params.mode_pwmp_hd_params, mode_params_save_cb); } else { DBG_ASSERT(FALSE __DBG_LINE); } show_actual_lpf.alpha = 0.2f; lpf_init(&show_actual_lpf); }