This repository has been archived on 2025-02-28. You can view files and clone it, but cannot push or open issues or pull requests.
controller-hd/User/application/src/mode.c

413 lines
8.9 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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