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

csip_aus.c

源文件路径:logic/csip_aus.c 所属模块:logic(能量调度核心 —— 澳大利亚 CSIP-AUS v1.2 DER 控制) 代码行数:1368

1. 文件职责

本文件实现澳大利亚 CSIP-AUS v1.2 标准下的 DER(分布式能源)远程控制:接收电网运营商通过 SunSpec/CSIP 下发的四类功率限制(OpModExpLimW 馈网、OpModGenLimW 发电、OpModImpLimW 取电、OpModLoadLimW 负载)以及斜坡速率与过渡时间,把它们从"当前值/默认值"三组快照中算出目标变化量,包装成逆变器可执行的斜坡速率下发,并在通信超时、电网丢失、模式切回 NORMAL 时按规范回落到安全默认值。控制的方法是"EMS 计算斜坡速率、逆变器内部执行斜率",因此 g_t_csip_aus_run_data 里的斜坡功率字段被废弃,真正的输出是 s32_ramp_rate_w_per_sec 与 u8_ramp_enable。它由一个 4 态 × 8 事件的状态机组织(IDLE / CONTROL / DEFAULT / TRANSITION),由 logic 任务在 dnsp_ramp_control_handle() 内每控制周期(约 20 ms)调用一次 csip_aus_der_control_process()(logic/logic.c:1035)驱动;限制值与斜坡使能结果被 logic/logic.c 与 midware/inverter/inverter.c 读走用于约束充放电与馈网。

2. 关键数据结构与宏

名称类型说明
CSIP_AUS_DER_CONTROL_T / g_t_csip_aus_der_control结构体 / 全局变量主参数表,本文件 :23 定义(未显式初始化,按 C 标准全 0)
CSIP_AUS_RUN_DATA_T / g_t_csip_aus_run_data结构体 / 全局变量斜坡运行数据,本文件 :24 定义(未初始化)
g_u8_csip_aus_ramp_rate_calculated全局变量本文件 :25 定义,初值 FALSE;防止同一周期重复计算斜坡速率
CSIP_AUS_STATE_E枚举CSIP_AUS_STATE_IDLE(0)、_CONTROL(1)、_DEFAULT(2)、_TRANSITION(3)
CSIP_AUS_EVENT_E枚举NORMAL(0)、DEFAULT_ENTER(1)、DEFAULT_EXIT(2)、CONTROL_ENTER(3)、CONTROL_EXIT(4)、TIMEOUT(5)、GRID_LOSS(6)、GRID_RESTORE(7);后三者中 _DEFAULT_EXIT/_CONTROL_EXIT 无触发点,_GRID_RESTORE 有触发点无处理分支
CSIP_AUS_DER_MODE_NORMAL / _CONTROL / _DEFAULT宏0 / 1 / 2,与 logic.h 的 DER_NORMAL/DER_CONTROL/DER_CONTROL_DEFAULT 数值一一对应,两侧互相直接赋值
CSIP_AUS_RAMP_MIN_TIMEOUT_MS / MAX_TIMEOUT_MS / MAX_TIMEOUT_FACTOR宏5000 / 400000 / 12,斜坡超时下限/上限(ms)与倍率因子
CSIP_AUS_DEBUG宏本文件 :27 定义,值 0。门控约 20 处调试打印与 csip_aus_print_status() 的全部内容
CSIP_AUS_DEBUG_LOG宏本文件 :28 定义,值 0。门控主循环里每 1 秒一次的周期打印
DER_NORMAL枚举(logic/logic.h:73)来自 logic.h 的 DER 模式 0,本文件在 :421、:424 与 CSIP_AUS_DER_MODE_NORMAL 混用
TRUE / FALSE宏includes.h

3. 函数清单

本文件共 30 个函数定义:14 个 static、16 个全局。另有 2 个在 csip_aus.h 声明的函数(csip_aus_set_soft_ramp_rate、csip_aus_print_run_data)没有实现。

函数名作用域说明
inverter_set_softgradwstatic(:58)按逆变器型号把软启动斜坡速率下发(SET 用 inverter_set_dnsp_regulation_rate;AlphaESS/INOVANCE 用速率 ×6 调 inverter_set_rev_machine_rate/inverter_set_regulation_rate)
inverter_der_enablestatic(:91)按逆变器型号/子型号判决是否支持 DER 控制(SET 需 SUB_S5/SUB_S5_II/SUB_M10;AlphaESS、INOVANCE 直接 TRUE)
csip_aus_handle_mode_changestatic(:119)检测 u8_der_control_mode 变化并按新模式的对应事件调用状态机
csip_aus_data_syncstatic(:154)首次初始化 + 每周期把 g_t_logic_info 的外部参数同步进本模块,并做模式变化前后的旧值保存
csip_aus_der_control_process全局(:365)主处理入口,被 logic 任务每周期调用
csip_aus_state_machine_handle全局(:474)按 u8_current_state 分派事件到四个状态处理器;未知状态回落 transition_to_default()
csip_aus_check_and_trigger_eventsstatic(:510)轮询三类事件触发条件并调用状态机
csip_aus_state_idle_handlestatic(:570)IDLE 态:CONTROL_ENTER → 进控制;DEFAULT_ENTER → 进默认;GRID_LOSS → 空实现
csip_aus_state_default_handlestatic(:601)DEFAULT 态:进控制/返正常需并网;TIMEOUT → 返正常;GRID_LOSS → 留在默认
csip_aus_state_control_handlestatic(:641)CONTROL 态:DEFAULT_ENTER/GRID_LOSS → 进默认;TIMEOUT → 改写模式为 DEFAULT 并进默认
csip_aus_state_transition_handlestatic(:681)TRANSITION 态:按事件重定向;末尾若斜坡已结束则按模式落状态
csip_aus_transition_to_default全局(:736)过渡到 DEFAULT;离网时直接落状态不走斜坡;斜坡未使能时先使能并挂起等待
csip_aus_transition_to_control全局(:811)过渡到 CONTROL;重置 u32_control_remaining;挂起等待同 transition_to_default
csip_aus_transition_to_normal全局(:864)置模式 NORMAL、状态 IDLE、刷新 state_enter_tick
csip_aus_calculate_ramp_ratestatic(:885)计算斜坡速率 s32_ramp_rate_w_per_sec(W/s),下限钳 11
csip_aus_check_ramp_complete全局(:970)仅在 TRANSITION 态按 500 ms 周期检查斜坡是否超时,超时即清斜坡标志并落状态
csip_aus_update_control_timeoutstatic(:1037)每秒递减 u32_control_remaining,到 0 触发 csip_aus_handle_control_timeout()
csip_aus_handle_grid_status_change全局(:1088)电网连接状态变化时发 GRID_LOSS / GRID_RESTORE 事件
csip_aus_handle_control_timeout全局(:1116)保存当前限制为旧值后向状态机发 TIMEOUT
csip_aus_update_grid_status全局(:1135)从 g_t_logic_info.t_logic_control_parameter.u8_grid_status 刷新电网状态
csip_aus_print_status全局(:1147)打印状态/限制/斜坡信息;整体被 #if (CSIP_AUS_DEBUG) 包裹,CSIP_AUS_DEBUG=0 时是空函数
csip_aus_calculate_ramp_timeoutstatic(:1191)按四类限制的最大变化量与斜坡速率估算超时,乘 1.2 后钳到 [5000, 400000] ms
csip_aus_common_transition_setupstatic(:1247)通用过渡收尾:确保斜坡使能、算速率、算超时、进 TRANSITION 态
csip_aus_der_control_mode_to_statestatic(:1292)用 u8_der_control_mode 查 3 元素表映射到状态,并置 u8_just_transitioned 保护
csip_aus_get_ramp_enable全局(:1311)读 u8_ramp_enable
csip_aus_get_ramp_rate全局(:1316)读 s32_ramp_rate_w_per_sec
csip_aus_get_exp_limit全局(:1321)读馈网限制;DEFAULT 模式返回 default_opmod_explimw
csip_aus_get_imp_limit全局(:1330)读取电限制;下限钳 10;单相系统(inverter_get_phase_number() == 1)再 ×3
csip_aus_get_gen_limit全局(:1345)读发电限制;DEFAULT 模式返回 default_opmod_genlimw
csip_aus_get_load_limit全局(:1354)读负载限制;下限钳 10

4. 核心逻辑解析

4.1 主处理流程:csip_aus_der_control_process()(:365)

调用者:logic/logic.c:1035(在 dnsp_ramp_control_handle() 中),节拍约 20 ms。执行顺序如下,多处是早期 return,顺序不可调整:

1. g_u8_csip_aus_ramp_rate_calculated = FALSE;         // 重置"已算速率"标志
2. csip_aus_data_sync();                               // 参数同步 + 模式变化检测
3. if (u8_ramp_enable_pending) {                       // 斜坡使能延时闸门
       elapsed = OSTimeGet() - u32_ramp_enable_set_tick;
       if (elapsed >= 3000) { 清 pending 三字段; 按 u8_pending_transition_type 执行
                              1 → transition_to_control(); 2 → transition_to_default(); }
       else  return;                                   // 等待期间直接返回
   }
4. if ((inverter_read_safety_is_AS4777(inverter_read_safety()) != TRUE) ||
       (u8_der_control_enable == FALSE) ||
       ((g_t_logic_info.u8_dercontrol == DER_NORMAL) && (u8_der_control_mode != CSIP_AUS_DER_MODE_NORMAL)))
   { csip_aus_transition_to_normal(); g_t_logic_info.u8_dercontrol = DER_NORMAL; return; }
5. if (u8_setsoftgradw_set_flag == TRUE) { inverter_set_softgradw(u16_setsoftgradw); u8_setsoftgradw_set_flag = FALSE; }
6. csip_aus_update_grid_status();                      // 发 GRID_LOSS / GRID_RESTORE
7. csip_aus_check_and_trigger_events();                // 状态机核心
8. if (g_u8_csip_aus_ramp_rate_calculated == FALSE) csip_aus_calculate_ramp_rate();
9. csip_aus_update_control_timeout();                  // 每秒递减剩余时间
10. csip_aus_check_ramp_complete();                    // TRANSITION 态超时判定
11. #if (CSIP_AUS_DEBUG_LOG) 每 1000 ms 打一次 csip_aus_print_status(); #endif

步骤 3 的 3 秒闸门是设计上的关键:切换模式前必须先让逆变器收到"斜坡使能",因此第一次调用 transition_to_control()/transition_to_default() 时不切换,只置 u8_ramp_enable_pending = TRUE + u8_pending_transition_type,等 3 秒后再真正切换。注意该闸门在安全检查(步骤 4)之前 return,因此等待期间不做 AS4777 判定、不更新电网状态——见备注 4。

步骤 4 的三重前置条件(:419-426):

条件含义
inverter_read_safety_is_AS4777(inverter_read_safety()) != TRUE安全规约非 AS4777(澳洲并网标准)→ CSIP-AUS 不适用,强制 NORMAL
u8_der_control_enable == FALSE当前逆变器型号不支持 DER 控制(inverter_der_enable() 判定)
u8_dercontrol == DER_NORMAL 但内部模式已非 NORMAL云端已撤销控制 → 回 NORMAL

三者任一成立即 csip_aus_transition_to_normal() 并把 g_t_logic_info.u8_dercontrol 强制写回 DER_NORMAL。

4.2 状态机总览

四个状态 × 已接线的 5 个事件的转移矩阵(csip_aus.c:570-724):

当前状态NORMALDEFAULT_ENTERCONTROL_ENTERTIMEOUTGRID_LOSS
IDLE无分支transition_to_default()transition_to_control()无分支空实现(:584-587 被注释掉)
DEFAULT若并网 → transition_to_normal()无分支若并网 → transition_to_control()transition_to_normal()transition_to_default()
CONTROL无分支transition_to_default()若并网 → transition_to_control()置 u8_der_control_mode = DEFAULT、同步 g_t_logic_info.u8_dercontrol、Set_Setup_Config_Extend2_Status(FALSE)、transition_to_default()transition_to_default()
TRANSITION被注释掉(:692-695)若模式 ≠ DEFAULT → transition_to_default()若模式 ≠ CONTROL → transition_to_control()同 CONTROL 的 TIMEOUT 处理transition_to_default()
其他————csip_aus_state_machine_handle 的 default → transition_to_default()

TRANSITION 态的处理器末尾(:719-723)还有一条独立收尾:

if (g_t_csip_aus_run_data.u8_ramp_active == FALSE)  csip_aus_der_control_mode_to_state();

即"斜坡已结束(由 check_ramp_complete 或事件处理器清标志)"时,按当前 u8_der_control_mode 落到 IDLE/CONTROL/DEFAULT 稳态。

4.3 事件轮询:csip_aus_check_and_trigger_events()(:510)

if (u8_der_control_mode == CSIP_AUS_DER_MODE_NORMAL) {          // NORMAL:不动斜坡
    u8_ramp_enable = FALSE;  u8_ramp_active = FALSE;
}
if (u8_just_transitioned) {                                      // 转换后 2 秒防抖
    if ((OSTimeGet() - u32_transition_tick) < 2000)  return;
    u8_just_transitioned = FALSE;  u32_transition_tick = 0;
}
switch (u8_der_control_mode) {
    case NORMAL:  if (u8_current_state != IDLE)    状态机(NORMAL);         break;
    case DEFAULT: if (u8_current_state != DEFAULT) 状态机(DEFAULT_ENTER);  break;
    case CONTROL: if (u32_control_remaining == 0)  状态机(TIMEOUT);
                  else if (u8_current_state != CONTROL) 状态机(CONTROL_ENTER); break;
}

这就是"轮询式状态机"的核心:没有事件队列,每个周期按当前模式与状态推导"应该发生的事件",再交给 csip_aus_state_machine_handle()。两点设计细节:

4.4 过渡路径与 3 秒等待机制

csip_aus_transition_to_control()(:811)与 csip_aus_transition_to_default()(:736)结构对称,都是"两段式":

if (u8_ramp_enable_pending && u8_pending_transition_type == 本次类型)  return;   // 已在等同类转换
if (!u8_ramp_enable) {                       // 斜坡还没使能 → 先使能并挂起
    u8_ramp_enable = TRUE;  u8_ramp_active = TRUE;
    g_t_inv_info.t_control_parameter.u8_csip_aus_data_flag = FALSE;   // 让逆变器下次重新收参数
    u8_ramp_enable_pending = TRUE;  u32_ramp_enable_set_tick = OSTimeGet();
    u8_pending_transition_type = 1 或 2;
    return;
}
// 斜坡已使能 → 真正切换
u8_der_control_mode = CONTROL 或 DEFAULT;
[CONTROL 额外] u32_control_remaining = u32_durationtime;
csip_aus_common_transition_setup(u16_ramptms 或 0);

transition_to_default() 前面还有一条离网快路径(:739-758):u8_grid_connected == FALSE 时直接置模式 DEFAULT、清 u8_ramp_enable/u8_ramp_active/u8_ramp_enable_pending(连同 u32_ramp_enable_set_tick、u8_pending_transition_type)、调 csip_aus_der_control_mode_to_state() 后 return——离网不走斜坡,立即落稳态,因为离网时 EMS 不参与爬坡(注释 :744"确保电网恢复 EMS 不参与爬坡")。

csip_aus_common_transition_setup()(:1247):

// if (u8_current_state == CSIP_AUS_STATE_TRANSITION) return;   ← 被 #if 0 风格注释掉(:1249-1252)
if (!u8_ramp_enable) { u8_ramp_enable = TRUE; u8_ramp_active = TRUE;
                       g_t_inv_info.t_control_parameter.u8_csip_aus_data_flag = FALSE; }
u16_ramptms = ramp_tms_value;
csip_aus_calculate_ramp_rate();
g_u8_csip_aus_ramp_rate_calculated = TRUE;        // 阻止主流程重复计算
if (ramp_tms_value > 0)  u32_ramp_timeout_ms = ramp_tms_value * CSIP_AUS_RAMP_MAX_TIMEOUT_FACTOR;
else                     u32_ramp_timeout_ms = csip_aus_calculate_ramp_timeout();
g_t_inv_info.t_control_parameter.u8_csip_aus_data_flag = FALSE;
u8_current_state = CSIP_AUS_STATE_TRANSITION;
u32_state_enter_tick = OSTimeGet();

被注释掉的"已在 TRANSITION 就不重入"守卫说明作者曾想避免重复过渡,但当前版本每次调用都会重设 u32_state_enter_tick——这意味着斜坡计时会被同一周期内的多次过渡调用反复重置。

4.5 斜坡速率算法:csip_aus_calculate_ramp_rate()(:885)

第一步,算四类限制的变化量:

模式目标值起点
DEFAULTs32_default_opmod_*limws32_old_opmod_*limw
其他(CONTROL/NORMAL)s32_opmod_*limws32_old_opmod_*limw

第二步,按当前潮流方向挑主变化量:

if (actual_meter_power < 0)  power_diff = export_diff;   // 卖电(s32_pgrid_metert < 0)
else                         power_diff = import_diff;   // 买电
if (power_diff == 0)  power_diff = (actual_inv_power > 0) ? gen_diff : load_diff;
if (power_diff == 0)  power_diff = rated_power / 10;     // 兜底:额定功率的 10%

第三步,算速率:

s32 target_ramp_rate = rated_power / 100;                // 默认 1%/s
if (u8_der_control_mode == CSIP_AUS_DER_MODE_CONTROL) {
    if (ramp_tms > 0)      target_ramp_rate = (power_diff * 100) / ramp_tms;      // 由过渡时间反推
    else if (setgradw > 0) target_ramp_rate = (setgradw * rated_power) / 10000;   // 由 0.01%/s 换算
} else {
    if (setgradw > 0)      target_ramp_rate = (setgradw * rated_power) / 10000;
}
s32_ramp_rate_w_per_sec = target_ramp_rate;
if (s32_ramp_rate_w_per_sec < 11)  s32_ramp_rate_w_per_sec = 11;   // 最小速率

公式校验:

rated_power / 100 = 1%/s 是标准允许的最慢默认速率,当既无 ramptms 也无 setgradw 时兜底;:952 的 < 11 下限(W/s)防止速率过小导致斜坡永远走不完。

4.6 斜坡完成判定:csip_aus_check_ramp_complete()(:970)

static u32 s_l_u32_last_check_tick = 0;

if (u8_current_state != CSIP_AUS_STATE_TRANSITION) { s_l_u32_last_check_tick = 0; return; }
if (s_l_u32_last_check_tick == 0) { s_l_u32_last_check_tick = OSTimeGet(); return; }   // 首次只记录
delta = OSTimeGet() - s_l_u32_last_check_tick;
if (delta < 500)  return;                                                       // 节流到 500 ms
ramp_elapsed_ms = OSTimeGet() - u32_state_enter_tick;
if (ramp_elapsed_ms >= u32_ramp_timeout_ms) {                                   // 超时 → 视为完成
    u8_ramp_enable = FALSE;  u8_ramp_active = FALSE;
    csip_aus_der_control_mode_to_state();
    return;
}
s_l_u32_last_check_tick = OSTimeGet();

关键事实:函数名为 "check_ramp_complete",但只做超时判定,从不比较 s32_ramp_current 与 s32_ramp_target(这两个字段全工程无读写点)。也就是说"斜坡是否走完"完全由时间推算,没有基于实际功率的闭环确认。加上首次调用只记录 tick(return)以及 500 ms 节流,从进入 TRANSITION 到最早可能判定完成至少要 1000 ms。

4.7 控制超时:csip_aus_update_control_timeout()(:1037)

static u32 s_last_timeout_tick = 0;
now = OSTimeGet();
if (s_last_timeout_tick == 0) { s_last_timeout_tick = now; return; }
elapsed_sec = (now - s_last_timeout_tick) / 1000;
if (elapsed_sec == 0) return;                        // 未满 1 秒
s_last_timeout_tick = now;
if (u8_der_control_mode == CSIP_AUS_DER_MODE_CONTROL) {
    if (u32_control_remaining > elapsed_sec)  u32_control_remaining -= elapsed_sec;
    else { u32_control_remaining = 0; csip_aus_handle_control_timeout(); }
}

仅在 CONTROL 模式下递减。csip_aus_handle_control_timeout()(:1116)先把四类 opmod_* 快照进 old_*(为回落斜坡算变化量),再向状态机发 TIMEOUT。函数头注释写的 @Name : csip_aus_update_control_timeout(u32 delta_time_ms) 与实际无参签名不符,且实现是内部自己取 OSTimeGet() 而非接收 delta_time——注释里的"避免重复计算"设计未落地。

4.8 参数同步:csip_aus_data_sync()(:154)

这是本文件最复杂的函数,分四段。

(1) 首次初始化(static u8 s_initialized,:160-215) 从 g_t_logic_info 拉取全部初值:四类限制的当前值/默认值、old_* 取默认值、u16_setgradw/u16_setsoftgradw/u16_ramptms、u8_der_control_mode = g_t_logic_info.u8_dercontrol(:188,未做范围校验)、u32_durationtime、状态置 IDLE、u8_setsoftgradw_set_flag = TRUE、各类标志清零。

(2) 模式变化前的旧值保存(:217-250)

u8 old_mode = u8_der_control_mode, new_mode = g_t_logic_info.u8_dercontrol;
u8 is_mode_changing = (old_mode != new_mode);
if (is_mode_changing && new_mode != NORMAL && save_limit_changed) {
    if (old_mode == CONTROL)       old_* = opmod_*;        // 从控制态切走:保存控制值
    else if (old_mode == DEFAULT)  old_* = default_*;      // 从默认态切走:保存默认值
    else {                                                  // 从 NORMAL 切入:用实时测得值
        s32_old_opmod_explimw = (s32_pgrid_metert >= 0) ? 0 : abs(s32_pgrid_metert);
        s32_old_opmod_genlimw = s32_pinvt;
        s32_old_opmod_implimw = (s32_pgrid_metert <= 0) ? 0 : s32_pgrid_metert;
        s32_old_opmod_loadlimw = -s32_pinvt;
    }
    save_limit_changed = FALSE;
}

save_limit_changed 是 static,置 FALSE 后只在 !is_mode_changing 时恢复 TRUE(:351-354)——即连续多周期都处于"模式变化中"时,旧值只会保存一次。

(3) 四个宏完成的限制值同步(:252-314) 用 token-pasting 宏把源字段(无下划线,如 s32_opmodexplimw)与目标字段(带下划线,如 s32_opmod_explimw)配对:

#define SYNC_DEFAULT_LIMIT(param)  if (g_t_logic_info.s32_default_opmod##param##limw != s32_default_opmod_##param##limw) { ... }
#define SYNC_CONTROL_LIMIT(param)  if (g_t_logic_info.s32_opmod##param##limw       != s32_opmod_##param##limw)       { ... }
#define SYNC_NORMAL_LIMIT(param)   ...

在 CONTROL 模式下且外部 u8_dercontrol 也是 CONTROL 时,若四类 opmod_* 任一发生变化,先把全部 opmod_* 存进 old_*(:279-282),再用 SYNC_CONTROL_LIMIT 逐项同步并置 s_limit_changed_in_control = TRUE(该标志会在 :344-349 触发一次 csip_aus_transition_to_control() 重新拉斜坡)。非 CONTROL 模式用 SYNC_NORMAL_LIMIT 只同步不更新旧值。

(4) 斜坡参数与时长同步(:317-337) u16_ramptms、u16_setgradw 单向同步;u16_setsoftgradw 变化时额外置 u8_setsoftgradw_set_flag = TRUE(让主循环重新下发);u32_durationtime 变化时同步并把 u32_control_remaining 重置为该值。

(5) 模式变化处理(:339-354) is_mode_changing 时调 csip_aus_handle_mode_change(new_mode);否则若处于 CONTROL 态且 s_limit_changed_in_control,触发 csip_aus_transition_to_control()。

csip_aus_handle_mode_change()(:119)只在 u8_der_control_mode != new_mode 时动作,按新模式的 0/1/2 分别发 NORMAL/DEFAULT_ENTER/CONTROL_ENTER。注意它不更新 u8_der_control_mode——真正的更新发生在 transition_to_*() 内部。

4.9 斜坡超时估算:csip_aus_calculate_ramp_timeout()(:1191)

// 1) 取四类变化量(DEFAULT 模式用 default_* 重算一次)
// 2) max_diff = max(export_diff, gen_diff, import_diff, load_diff);
//    若为 0 → max_diff = s32_inv_rated_output_power / 10;
// 3) if (s32_ramp_rate_w_per_sec > 0)
//        estimated_time_ms = (u32)((s64)max_diff * 1000 / s32_ramp_rate_w_per_sec);
//    else
//        estimated_time_ms = CSIP_AUS_RAMP_MIN_TIMEOUT_MS;
// 4) estimated_time_ms = estimated_time_ms * CSIP_AUS_RAMP_MAX_TIMEOUT_FACTOR / 10;   // ×1.2
// 5) 钳到 [CSIP_AUS_RAMP_MIN_TIMEOUT_MS, CSIP_AUS_RAMP_MAX_TIMEOUT_MS]

这里用了 (s64) 强制提升再乘 1000,是全文件唯一一处防溢出的乘法(对比 csip_aus_calculate_ramp_rate 的 (power_diff * 100) / ramp_tms 与 (setgradw * rated_power) / 10000 都是纯 s32,见备注 6)。

4.10 电网状态处理

csip_aus_update_grid_status()(:1135)→ csip_aus_handle_grid_status_change()(:1088):

u8 old_status = u8_grid_connected;
u8_grid_connected = grid_connected;
if (old_status != grid_connected) {
    u8_grid_status_change = TRUE;                       // 置位后从不清零
    if (grid_connected == FALSE)
         csip_aus_state_machine_handle(CSIP_AUS_EVENT_GRID_LOSS);     // 只有 IDLE 的空实现、DEFAULT/CONTROL/TRANSITION 会响应
    else csip_aus_state_machine_handle(CSIP_AUS_EVENT_GRID_RESTORE);  // 四个状态处理器都没有这个 case
}

4.11 取值接口与安全钳位(:1311-1367)

接口返回钳位/特例
csip_aus_get_ramp_enableu8_ramp_enable—
csip_aus_get_ramp_rates32_ramp_rate_w_per_sec—
csip_aus_get_exp_limitDEFAULT 模式 → default_opmod_explimw,否则 opmod_explimw无下限钳位
csip_aus_get_imp_limitDEFAULT 模式 → default_opmod_implimw,否则 opmod_implimw下限钳 10;单相系统(inverter_get_phase_number() == 1)再 ×3
csip_aus_get_gen_limitDEFAULT 模式 → default_opmod_genlimw,否则 opmod_genlimw无下限钳位
csip_aus_get_load_limitDEFAULT 模式 → default_opmod_loadlimw,否则 opmod_loadlimw下限钳 10(钳位后不再乘相数)

csip_aus_get_imp_limit() 的 ×3 是"单相系统三相合计取电能力"的经验修正,:1342 的写法把相数判断内联在返回表达式里,读起来容易忽略。

4.12 关键全局变量的读写

变量写者读者
g_t_csip_aus_der_control.*本文件(data_sync、transition_to_*、common_transition_setup、mode_to_state、handle_control_timeout)本文件;外部只经 6 个 csip_aus_get_*()
g_t_csip_aus_run_data.u8_ramp_enable / u8_ramp_active本文件 6 处csip_aus_get_ramp_enable() → logic.c(12 处)、inverter.c:2312/2387
g_u8_csip_aus_ramp_rate_calculated本文件(主流程置 FALSE、common_transition_setup 置 TRUE)本文件主流程判定
g_t_logic_info.u8_dercontrol:424 强制 DER_NORMAL;:661/:707 写入 u8_der_control_mode(TIMEOUT 时置 DEFAULT)logic.c:863/1038/1057-1060/2794-2799、ems.c:1068/2242、modbus.c:3675
g_t_logic_info.u16_ramptms / u16_setgradw / u16_setsoftgradw / u32_durationtime / s32_opmod*limw / s32_default_opmod*limw只读(本文件从它们同步进模块)—
g_t_logic_info.t_logic_control_parameter.s32_pgrid_metert / s32_pinvt只读(算变化量与潮流方向)—
g_t_logic_info.t_logic_control_parameter.u8_grid_status只读—
g_t_inv_info.t_control_parameter.u8_csip_aus_data_flag写 FALSE(4 处::775、:828、:1259、:1279),提示逆变器重新接收 CSIP 参数midware/inverter 内

4.13 定时与 uCOS-II 配合

机制说明
调用节拍由 logic 任务驱动(logic.c:2912 的 OSFlagPend(..., 20, ...),约 20 ms 一次),csip_aus_der_control_process() 每周期执行一次
任务创建本文件不建任务、不使用信号量、不使用消息邮箱
时间基准全部 OSTimeGet(),单位 ms(OS_TICKS_PER_SEC = 1000)
文件内时间常量3 秒(斜坡使能等待,:380)、2 秒(状态转换防抖,:521)、500 ms(斜坡检查节流,:994)、1000 ms(超时递减粒度,:1051)、1000 ms(调试打印周期,:454)
状态机的"事件"来源无队列,全部由 csip_aus_check_and_trigger_events() 按模式/状态轮询推导

4.14 通信协议

本文件不实现帧收发。它消费的是 net/server.c:5142(JSON u8_dercontrol 等字段)与 midware/interface/modbus/modbus.c:6327(SunSpec Modbus 写点)落进 g_t_logic_info 的四类限制值,并通过 midware/interface/modbus/modbus.c:3675 把 u8_dercontrol 回读给 SunSpec 点表。本文件不含起始码/长度/命令字/校验等任何帧层逻辑,也没有超时重传——"超时"在这里只有 u32_control_remaining 与 u32_ramp_timeout_ms 两个业务计时的含义。

5. 对外接口

导出(供外部使用):

名称类型调用方
csip_aus_der_control_process函数logic/logic.c:1035(唯一调用点)
csip_aus_get_ramp_enable函数logic/logic.c:757/871/924/1084/1086/2781/3126/3142/3158/3218/3234/3250、midware/inverter/inverter.c:2312/2387
csip_aus_get_exp_limit函数logic/logic.c:1065
csip_aus_get_gen_limit函数logic/logic.c:1070/1072
csip_aus_get_load_limit函数logic/logic.c:865/866
csip_aus_get_imp_limit函数logic/logic.c:1094/1095
csip_aus_get_ramp_rate函数logic/logic.c:1078/1080
g_t_csip_aus_der_control / g_t_csip_aus_run_data / g_u8_csip_aus_ramp_rate_calculated全局变量外部无直接访问
csip_aus_transition_to_default / _control / _normal、csip_aus_state_machine_handle、csip_aus_check_ramp_complete、csip_aus_handle_grid_status_change、csip_aus_handle_control_timeout、csip_aus_update_grid_status、csip_aus_print_status函数无外部调用方,全部内部使用

被调用(本文件引用的外部符号):

符号来源
OSTimeGet、printfUCOSII/uCOS-II、C 运行库
inverter_read_safety、inverter_read_safety_is_AS4777、inverter_get_type(get_inverter_type)、get_inverter_sub、inverter_get_phase_number、inverter_set_dnsp_regulation_rate、inverter_set_rev_machine_rate、inverter_set_regulation_rate、SET_TYPE、ALPHAESS_TYPE、INOVANCE_TYPE、SUB_S5、SUB_S5_II、SUB_M10midware/inverter/inverter.h
g_t_inv_info.t_control_parameter.u8_csip_aus_data_flagmidware/inverter/inverter.h:1867
g_t_logic_info(s32_opmod*limw、s32_default_opmod*limw、u16_ramptms、u16_setgradw、u16_setsoftgradw、u32_durationtime、u8_dercontrol、u8_dnsp_maxfeedin_priority_flag 等)logic/logic.h
DER_NORMALlogic/logic.h:73
Set_Setup_Config_Extend2_Statusnet/ems.h:512
abs、memset、NULL(未见)C 运行库 / includes.h
TRUE、FALSEincludes.h

6. 依赖关系

依赖(csip_aus.c:13-19):csip_aus.h、logic.h、ac_control.h、dispatch.h、data.h、inverter.h、ems.h。

被依赖:

7. 备注与风险点

  1. #if (CSIP_AUS_DEBUG) 打开会编译失败::955-957 的调试打印引用了未定义标识符 invpower_diff(该变量在函数里不存在)。:1009-1013、:1018-1022 也有可疑打印。这意味着 CSIP_AUS_DEBUG 这个开关实际上不可用——一旦置 1 就会编译报错,调试能力被事实性封死。同理 csip_aus_print_status()(:1147)的全部内容都在该宏内,CSIP_AUS_DEBUG=0 时它是一个空函数体,被 logic.c 调用也毫无输出。
  2. csip_aus_check_ramp_complete() 名不符实,且超时打印重复:函数只做超时判定(:1001-1016),从不比较 s32_ramp_target 与 s32_ramp_current(两个字段全文件无读写点)。:1018-1022 还有一段在 return 之后的调试打印,被 #if 包裹但位置在 return 之外、break 逻辑之内——它是同一段打印的重复粘贴,且照原样打开会打印误导性内容(把"未超时"的情形也打上"ramp timeout"字样)。
  3. mode_to_state 数组用云端可控的值做索引,无边界检查:csip_aus_der_control_mode_to_state()(:1292-1308)
   static const u8 mode_to_state[] = { CSIP_AUS_STATE_IDLE, CSIP_AUS_STATE_CONTROL, CSIP_AUS_STATE_DEFAULT };
   u8 new_state = mode_to_state[g_t_csip_aus_der_control.u8_der_control_mode];

g_t_logic_info.u8_dercontrol 由云端 JSON(net/server.c:5142,(u8)l_u32_json_value1)与 Modbus(modbus.c:6327)直接写入,没有取值校验。它在 csip_aus_data_sync() 首次初始化时被原样赋给 u8_der_control_mode(:188),之后 csip_aus_handle_mode_change() 只处理 0/1/2 不会引入越界值。因此唯一但真实的越界路径是:"云端写入 u8_dercontrol >= 3 → 复位/首次进入 CSIP-AUS → data_sync 首次初始化把它放进 u8_der_control_mode → 任一路径调用 mode_to_state() → 数组越界读"。建议在 :188 加范围钳位。

  1. 3 秒斜坡等待期间跳过全部安全检查:csip_aus_der_control_process() 的 pending 闸门(:375-416)在安全检查之前 return,因此等待的 3 秒内不会调 csip_aus_update_grid_status(),电网丢失事件不会被发出;也不会重新评估 AS4777 与 u8_der_control_enable。若在等待窗口内发生离网,transition_to_default() 的离网快路径(:740)也无法被执行,只能等 3 秒后 u8_pending_transition_type == 2 的分支(此时 u8_grid_connected 是 3 秒前的旧值)或下一周期刷新后才纠正。
  2. CSIP_AUS_EVENT_GRID_RESTORE 发得出无人接、_DEFAULT_EXIT/_CONTROL_EXIT 无触发点::1105 发出 GRID_RESTORE,但四个 state_*_handle 都没有该 case,全部落到 default。这意味着电网恢复后状态机不会主动离开 DEFAULT——要靠 check_and_trigger_events() 下一轮按 u8_der_control_mode(此时已被置为 DEFAULT)再发 DEFAULT_ENTER。整个 "电网恢复" 语义是空转的。
  3. 多处 s32 乘法无溢出保护:csip_aus_calculate_ramp_rate() 的 (power_diff * 100)(:939)与 (setgradw * rated_power)(:941、:946)。rated_power 是 s32_inv_rated_output_power(并机系统的额定输出功率,多机并机时可能上万 W),setgradw 上限未定;setgradw * rated_power 超过 2^31/10000 ≈ 214748 就会溢出。对比 csip_aus_calculate_ramp_timeout() 的 (s64)max_diff * 1000(:1223)——同一个文件里一处做了提升、另两处没做,标准不一致。
  4. u16_ramptms 被两处写入、语义不同:csip_aus_common_transition_setup() 每次都执行 u16_ramptms = ramp_tms_value(:1263)——transition_to_default() 传 0(:792),transition_to_control() 传 g_t_logic_info.u16_ramptms(:847)。因此每次切到 DEFAULT 都会把 u16_ramptms 清 0,随后 csip_aus_calculate_ramp_rate() 就走到 setgradw 分支或 rated/100 兜底,csip_aus_calculate_ramp_timeout() 也就再也拿不到 ramp_tms>0 的路径。这可能是刻意(DEFAULT 用速率而非过渡时间),但 u16_ramptms 同时又是从 g_t_logic_info 同步来的参数(:317-320),被本地清除后下一个周期 data_sync 又会从外部同步回来——两个方向来回覆盖,行为取决于时序。
  5. inverter_set_softgradw() 里的数值 ×6 是未解释的换算::71、:78 都用 u16 rate = setsoftgradw * 6。u16_setsoftgradw 的单位在头文件里写的是 0.01%/s,而 inverter_set_rev_machine_rate()/inverter_set_regulation_rate() 的单位在 inverter.h 里没有说明,×6 的来历无从判断(可能是 %/s ↔ 0.01%/s 加某个机型系数)。注意 (u16)(setsoftgradw * 6) 与 inverter_set_dnsp_regulation_rate(setsoftgradw)(:63,未乘 6)对同一种量用了两种换算,SET 与 AlphaESS/INOVANCE 的口径不一致。
  6. inverter_set_softgradw() 的注释是错的::57 写"暂时未实现的函数,留待后续补充",但函数体完整;:51 与 :85 的 @Name 两处都写成 static u8 inverter_der_enable(void)(复制粘贴),与其真实函数名不符。
  7. csip_aus_data_sync() 的 save_limit_changed 逻辑脆弱:该 static 标志在保存旧值后置 FALSE,只在 !is_mode_changing 时才恢复 TRUE(:351-354)。若模式切换跨多个周期(这在 3 秒 pending 等待的机制下很可能发生),旧值只保存一次,后续周期不再保存——而 csip_aus_calculate_ramp_rate() 又依赖 old_* 算变化量,可能把已被覆盖的 old_* 当作起点。
  8. u8_grid_status_change 置位后永不清零(:1095):无消费者,功能上无害,但属于"永远为真"的陷阱字段。
  9. g_t_csip_aus_der_control / g_t_csip_aus_run_data 未显式初始化::23、:24 都是裸定义,没有 = {0}(对比 dispatch.c:31 的 s_t_agingmode_data_temp = {0} 与 self_test.c:25 的 = {0})。按 C 标准全局对象零初始化,功能正确,但 u16_ramptms、u32_ramp_timeout_ms 等字段在首次 data_sync 之前为 0,若在这之前有调用者读 csip_aus_get_*() 会拿到 0——logic.c:865 的 csip_aus_get_load_limit()+s32_pbackupt 就是这种情况,此时 get_load_limit 的 < 10 钳位起到了兜底作用。
  10. Set_Setup_Config_Extend2_Status(FALSE) 的副作用未在本文件注释::662、:708 在控制超时时调用(实现在 net/ems.c),语义是清除"扩展配置 2"的生效状态。本文件没有说明它具体清什么,从调用位置看是"控制超时后撤销 CSIP 配置的生效标记"。建议补注释。
  11. csip_aus_get_exp_limit() / csip_aus_get_gen_limit() 无下限钳位:对比 get_imp_limit/get_load_limit 都有 < 10 → 10 的保护。若云端下发 0(而非负值),logic.c:1065 的 l_s32_maxfeedin_power = min(..., 0) = 0 会把馈网功率锁死到 0;如果 0 是"未配置"而非"禁止馈网",就是一次静默的过保守行为。
  12. 注释与实现不符的两处:csip_aus_update_control_timeout() 的 @Name 写 (u32 delta_time_ms)、@Note 写"使用主函数传入的 delta_time,避免重复计算",实际是无参函数且内部自取 OSTimeGet()(:1027-1032 vs :1037)。CSIP_AUS_RAMP_MAX_TIMEOUT_FACTOR 的注释"最大超时倍数:1.2倍计算时间"是对的(:1231 用 ×12/10),但同一宏在 :1272 被用作 ramp_tms_value * 12——因为那里的输入单位是 1/100 秒,×12 恰好等于"换算成毫秒后再 ×1.2",两处用法单位基准不同、都正确,但完全没有注释说明,极易在维护时改错。
  13. CSIP_AUS_DEBUG / CSIP_AUS_DEBUG_LOG 用 #define 硬编码在 .c 内(:27-28):无法通过编译器 -D 覆盖(会触发宏重定义告警),也不能按机型分别开启。建议改为 #ifndef ... #define ... #endif。
  14. csip_aus_state_transition_handle() 的 NORMAL 分支被注释掉(:692-695):TRANSITION 态收到 NORMAL 事件时不回到正常,只能依赖 csip_aus_der_control_process() 顶部的安全闸门(:419)兜底。属版本遗留。
  15. u8_previous_state 只写不读::1302 写入后全工程无读取点(csip_aus_print_status() 也不打它),属于为调试预留但未接线的字段。