EMS 知识库
首页 / knowledge/代码解析/logic

handle_priority.c

源文件路径:logic/handle_priority.c 所属模块:logic(能量调度核心) 代码行数:206

1. 文件职责

本文件实现「光伏优先(PV priority)」AC 控模式下总功率目标值的下发动作函数集合,是 PV_PRIORITY_AC_CONTORL_STATE 状态机的执行层(状态判断在上层、功率赋值在本文件)。文件头注释说明它是因为 DC 控 / AC 控条件编译的需要,从 logic/ac_control.c 中拆分出来的。它只写入 g_t_logic_info 里 AC 侧的总设值(s32_ac_total_set_inv_power、s32_ac_total_set_bat_charge_limit_power、s32_ac_total_set_bat_discharge_limit_power、u8_ac_total_set_bat_forced_charge_en),不做逆变器/电池的直接硬件操作。驱动方有两个:logic/logic.c 的 ac_control_total_power_photovoltaic_priority_calculate()(光伏优先状态机,软定时限制调整速率)与 logic/ac_control.c 的 fsm_total_power_ac_control()(自发自用状态机,INV_AC_CTRL 条件编译内)。数据流位置:电表/逆变器采样 → t_logic_control_parameter → 本文件的反馈闭环计算 → s32_ac_total_set_* → 上层限幅与逆变器下发。

2. 关键数据结构与宏

名称类型说明
PV_PRIORITY_AC_CONTORL_STATE枚举(定义于 handle_priority.h)光伏优先 AC 控状态机的 6 个状态:PRIORITY_DEFAULT_STATE=0、PRIORITY_GRID_TRACK_BACKUP_BELOW_PV_STATE=1、PRIORITY_GRID_TRACK_BACKUP_OVER_PV_STATE=2、PRIORITY_GRID_TRACK_WITHOUT_PV_STATE=3、PRIORITY_GRID_ZERO_WITHOUT_PV_STATE=4、PRIORITY_BAT_OPEN_WITH_PV_STATE=5
g_t_logic_info全局结构体(logic.h)本文件唯一读写对象,含 t_config_data / t_logic_control_parameter / AC 总设值三组字段
g_t_logic_info.s32_ac_total_set_inv_powers32AC 侧逆变(电表侧)功率总设值,本文件核心输出量,单位为 W
g_t_logic_info.s32_ac_total_set_bat_charge_limit_powers32电池充电功率上限,写入后被 logic_charge_dischg_power_limit() 等消费
g_t_logic_info.s32_ac_total_set_bat_discharge_limit_powers32电池放电功率上限
g_t_logic_info.u8_ac_total_set_bat_forced_charge_enu8强制充电使能,本文件各状态一律写 FALSE
TRUE / FALSE宏定义于公共头文件,取值为 1 / 0(本文件仅用于给 u8_ac_total_set_bat_forced_charge_en 赋 FALSE)
OSTimeGetuCOS-II API 间接相关本文件自身未调用;调用方 logic.c 用 OSTimeGet() + u32_calculation_interval 作为软定时门控

本文件没有定义结构体、联合体或位域,也没有自定义宏常量(阈值全部以字面量出现在表达式中)。

3. 函数清单

函数名作用域说明
total_power_control_grid_track_calculate全局(函数头注释误写为 static)有 PV 追踪电表归零:置满充/放限值,并按电表功率做 PI 增量闭环
total_power_control_grid_zero_without_pv_calculate全局(函数头注释误写为 static)无 PV 且电表已归零时的处理,含 s_u8_cnt 去抖与防小电流放电逻辑
handle_priority_default_state全局默认态:不做电池限值,仅按馈网上限跟踪逆变功率
handle_priority_grid_track_backup_below_pv_state全局低于 PV 的馈网跟踪备份态:允许充电、禁止放电
handle_priority_grid_track_backup_over_pv_state全局高于 PV 的馈网跟踪备份态:按电表增量给放电限值、禁止充电
handle_priority_grid_track_without_pv_state全局无 PV 追踪态,直接转调 total_power_control_grid_track_calculate()
handle_priority_grid_zero_without_pv_state全局无 PV 归零态,直接转调 total_power_control_grid_zero_without_pv_calculate()

共 7 个函数,全部为文件级非 static 定义(尽管注释块里写着 static)。

4. 核心逻辑解析

4.1 状态机与驱动时序

状态迁移条件不在本文件,而在 logic/logic.c 的 pp_total_power_ac_control_state_handle() 内,本文件只负责「进入某状态后如何算功率」。迁移判定依据(t_logic_control_parameter):

当前输入迁移结果
u8_pv_status == FALSE 且 (s32_pgrid_metert < -50 或 s32_pgrid_metert > s32_system_self_consumption)PRIORITY_GRID_TRACK_WITHOUT_PV_STATE
u8_pv_status == FALSE 且电表在 ±区间内PRIORITY_GRID_ZERO_WITHOUT_PV_STATE
u8_pv_status == TRUE、u8_bat_status == FALSEPRIORITY_BAT_OPEN_WITH_PV_STATE
PV 有效、电池有效、s32_pgrid_metert < -50(馈网中),且 `\\s32_pgrid_metert\\ 落在 s32_max_feedin_power ± 200 内,或逆变已接近满载(s32_pinvt > s32_inv_rated_output_power - 100`)PRIORITY_GRID_TRACK_BACKUP_BELOW_PV_STATE
PV 有效、电池有效、馈网中但既不贴近馈网上限也不满载PRIORITY_DEFAULT_STATE
PV 有效、电池有效、s32_pgrid_metert > s32_system_self_consumption(取电超过自耗)PRIORITY_GRID_TRACK_BACKUP_OVER_PV_STATE
其余PRIORITY_DEFAULT_STATE

驱动时序:ac_control_total_power_photovoltaic_priority_calculate() 每次先用 OSTimeGet() 与 u32_calculation_ac_total_inv_tick / u32_calculation_interval 做软定时门控(未到间隔直接 return),然后「先判状态、再执行动作」(pp_total_power_ac_control() 的 switch)。整个调用链在 task_system_logic_control 任务中周期执行(该任务同时被 g_t_fast_dispatch_flag 事件标志触发快调度)。

4.2 关键算法与公式

(1)馈网跟踪的增量闭环(total_power_control_grid_track_calculate、handle_priority_grid_track_backup_below_pv_state、handle_priority_grid_track_backup_over_pv_state 三处完全相同的代码):

s32_ac_total_set_inv_power += s32_pgrid_metert / u8_regulator_speed;

s32_pgrid_metert 为正表示电表侧取电、为负表示馈网。取电时增大逆变目标功率以抵消,馈网时减小。这是一个纯增量(积分型)调节器,u8_regulator_speed(取值 1~5,由 get_inv_regulator_speed() 按机型/电网功率给出)是调节步长分母,值越大调节越慢。

(2)大偏差直接前馈 + 小偏差增量微调(handle_priority_default_state 等):

if (abs(s32_max_feedin_power + s32_pgrid_metert) > 100)
    s32_ac_total_set_inv_power = s32_max_feedin_power + s32_pgrid_metert + s32_pinvt;
else
    s32_ac_total_set_inv_power += (s32_max_feedin_power + s32_pgrid_metert) / u8_regulator_speed;

即:当「馈网上限 + 实际电表功率」的绝对值超过 100 W 时,用前馈方式一步把目标拉到 max_feedin + pgrid_metert + pinvt;进入 ±100 的死区后改用增量微调,避免在设定点附近来回过冲。

(3)无 PV 归零态的三段判断(total_power_control_grid_zero_without_pv_calculate,含 static u8 s_u8_cnt 去抖):

条件动作
abs(s32_pinvt) < s32_system_self_consumptions_u8_cnt = 0;s32_ac_total_set_inv_power = 20;充、放限值均置 0(禁充禁放,避免电池小电流放电)
abs(s32_pinvt) < 140 && abs(s32_pgrid_metert) < 10s_u8_cnt = 0;s32_ac_total_set_inv_power = 40;充、放限值均置 0(逆变不封波空载场景)
其余s_u8_cnt++,仅当 s_u8_cnt > 2 才:inv_power += pgrid_metert / regulator_speed,并把充/放限值恢复为配置的满值

第三段连续 3 次(受计算间隔门控,实际约 3 个调度周期)才动作,起的是「确认进入稳态再恢复电池能力」的去抖作用。

(4)各状态的电池限值:

状态充电限值放电限值
PRIORITY_DEFAULT_STATE00(第 105-106 行先置 0)
..._BACKUP_BELOW_PV_STATEs32_bat_charge_power_limit(满)0
..._BACKUP_OVER_PV_STATE0s32_pgrid_metert / u8_regulator_speed(增量值)
..._GRID_TRACK_WITHOUT_PV_STATEs32_bat_charge_power_limits32_bat_dischg_power_limit
..._GRID_ZERO_WITHOUT_PV_STATE前两段 0、第三段满值前两段 0、第三段满值

handle_priority_default_state / ..._below_pv_state / ..._over_pv_state 三者在结尾都有统一的负值保护:

if (g_t_logic_info.s32_ac_total_set_inv_power < 0) g_t_logic_info.s32_ac_total_set_inv_power = 0;

4.3 通信协议帧格式

本文件不涉及任何通信收发,无帧格式、校验、超时重试逻辑(属 net/、midware/ 模块)。

4.4 与 uCOS-II 的配合

本文件不直接调用任何 uCOS-II API,不使用信号量/消息邮箱。它运行在 task_system_logic_control 任务上下文内,被事件标志 g_t_fast_dispatch_flag(POST_PEND_FAST_ENABLE)加速;跨任务同步由调用方通过 g_t_logic_info 结构体字段的「写—读」隐式完成,本文件自身无临界区保护。

4.5 关键全局变量读写

变量读/写触发条件
s32_ac_total_set_inv_power读+写5 个状态处理函数都会写;default/below/over 为「大偏差赋值、小偏差累加」两种语义
s32_ac_total_set_bat_charge_limit_power写状态相关,见 4.2 表
s32_ac_total_set_bat_discharge_limit_power写状态相关,见 4.2 表
u8_ac_total_set_bat_forced_charge_en写每个状态处理入口都无条件写 FALSE
t_logic_control_parameter.s32_pgrid_metert读闭环输入,电表总相功率
t_logic_control_parameter.s32_pinvt读逆变侧总功率
t_logic_control_parameter.s32_max_feedin_power读系统最大允许馈网功率
t_logic_control_parameter.s32_system_self_consumption读系统自耗阈值
t_logic_control_parameter.u8_regulator_speed读调节步长(1~5),所有除法分母
t_logic_control_parameter.s32_bat_charge_power_limit / s32_bat_dischg_power_limit读满充/满放限值来源

5. 对外接口

导出(供外部调用)——均通过 handle_priority.h 声明:

名称调用者
handle_priority_default_state()logic/logic.c:1947、logic.c:1968(switch 的 default 分支)
handle_priority_grid_track_backup_below_pv_state()logic/logic.c:1951
handle_priority_grid_track_backup_over_pv_state()logic/logic.c:1955
handle_priority_grid_track_without_pv_state()logic/logic.c:1959
handle_priority_grid_zero_without_pv_state()logic/logic.c:1963
total_power_control_grid_track_calculate()logic/ac_control.c:1022(fsm_total_power_ac_control,覆盖 GRID_TRACK_WITH_PV_STATE / GRID_TRACK_WITHOUT_PV_STATE / GRID_ZERO_WITH_PV_STATE 三个自发自用状态)、本文件 191 行
total_power_control_grid_zero_without_pv_calculate()logic/ac_control.c:1030(GRID_ZERO_WITHOUT_PV_STATE)、本文件 203 行
PV_PRIORITY_AC_CONTORL_STATE 枚举类型logic/logic.c(状态变量 s_u32_prestate、l_u32_nextstate)

本文件不导出任何全局变量(全部输出都通过 g_t_logic_info 生效)。

被调用(外部依赖):

名称来源
abs()C 标准库 stdlib.h(经 includes.h → logic.h 引入)
g_t_logic_info(含 t_logic_control_parameter、t_config_data)logic/logic.c 定义,logic.h 声明
FALSE公共类型/宏头文件(includes.h 链)

6. 依赖关系

依赖:

被依赖:

7. 备注与风险点

  1. 函数头注释与实际定义不符:20 行、36 行的注释写 @Name :static void total_power_control_grid_track_calculate(),但 26 行/42 行的真实定义没有 static;同理其余 5 个函数头都挂着错误的 @Name(例如 114 行的函数名叫 handle_priority_grid_track_with_pv_state、147/182/194 行的注释全部重复成 ..._backup_over_pv_state)。这些是复制粘贴遗留,容易误导调用者,建议同步修正。
  2. 大量重复代码:handle_priority_default_state、..._below_pv_state、..._over_pv_state 三个函数里「前馈 + 增量」的逆变功率计算块字节级相同(仅电池限值不同),是典型的三份拷贝,后续修改极易漏改其中一份。
  3. PRIORITY_BAT_OPEN_WITH_PV_STATE 没有对应处理函数:logic.c 的 pp_total_power_ac_control() 没有该 case,会落到 default 分支静默执行 handle_priority_default_state()。也就是说「PV 有效但电池未使能」这一状态在光伏优先路径下与默认态行为完全相同,与该状态的语义可能不一致(自发自用路径 ac_control.c 里有独立的 BAT_OPEN_WITH_PV_STATE/total_power_control_bat_open_with_pv_calculate() 处理)。switch 的 default 里只有一句 // TODO:报错信息,无任何告警上报。
  4. 除法无零保护:4 处 s32_pgrid_metert / u8_regulator_speed 与 2 处 (max_feedin + pgrid_metert) / u8_regulator_speed 都直接以配置量为分母。当前 get_inv_regulator_speed()(inverter.c:2634)的默认值是 REGULATOR_SPEED_5 且所有分支都赋 1~5,不会为 0;但该值来自运行期机型判断,一旦被外部或未覆盖分支写成 0 就会触发除零(GD32F407 上为硬件异常)。
  5. 整数除法截断与闭环死区:pgrid_metert / regulator_speed 在 |pgrid_metert| < regulator_speed(即 <5 W)时结果为 0,目标功率会「卡死」不再调整;负值除法向零取整(C99),在馈网方向与取电方向的步长不对称。
  6. 累积量无上限:s32_ac_total_set_inv_power += ... 是累加写,只有 < 0 的下限钳位,没有上限钳位。若上层限幅函数(logic_charge_dischg_power_limit())不兜底,持续同向偏差会让该值单向爬升到 s32 饱和。相对地,前馈分支是直接赋值、不累加,两种语义混在同一变量上。
  7. 魔法数字:100(死区/阈值 W)、-50(判定馈网的功率门限)、200(馈网上限允许偏差)、20 / 40(归零态固定逆变设值)、140(逆变功率门限)、10(电表功率门限)、> 2(去抖次数)、s32_inv_rated_output_power - 100。这些既无宏、也无注释说明量纲(推断为 W),建议提取为具名常量。
  8. 去抖计数期间限值保持旧值:total_power_control_grid_zero_without_pv_calculate() 的第三段在 s_u8_cnt <= 2 时既不写充电限值也不写放电限值,而是保留上一状态遗留在 g_t_logic_info 中的值。若上一状态是放电(如 ..._over_pv_state 刚写过放电限值),这 3 个周期内电池仍沿用旧限值,属于状态切换瞬态的未定义行为。
  9. 注释与实现不一致:第 65 行注释写「电池放电满足电表归零」,但该分支实际把充电限值也恢复成了满值 s32_bat_charge_power_limit;第 157 行注释掉的 s32_ac_total_set_bat_charge_limit_power = 0; 在 174 行又原样出现;第 158 行先把放电限值置 0,第 173 行又立刻覆盖,属冗余赋值。
  10. 跨任务可见性:本文件写的 g_t_logic_info 字段被其他任务(逆变器下发、并机、云端上报)读取,而写入过程(例如 4 个字段的非原子赋值序列)没有关中断/临界区保护。若读方在写入中途取值,会看到「电压目标已更新但电池限值还是上一状态」的混合状态。