413 lines
8.9 KiB
C
413 lines
8.9 KiB
C
/**
|
||
* @file mode.c
|
||
* @author xxx
|
||
* @date 2023-09-18 10:00:52
|
||
* @brief 此文件用于实现不同工作模式的功能
|
||
* @copyright Copyright (c) 2023 by xxx, All Rights Reserved.
|
||
*/
|
||
|
||
#include <math.h>
|
||
#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);
|
||
}
|