ems/ems_c/logic/logic_demandctrl.c

172 lines
6.2 KiB
C
Raw Permalink 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.

/*****************************************************************************
* @copyright 2024-202, . POWER SUPPLY CO., LTD.
* @file logic_demandctrl.c
* @brief xxxx
* @author Gary
* @date 2024/09/27
* @remark 初修订
*****************************************************************************/
#include "logic_comm.h"
// static sliding_window_t g_window; //滑差结构体
void initSlidingWindow(sliding_window_t *window)
{
window->pccCount = 0;
window->pccIndex = 0;
window->pccSum = 0;
window->loadCount = 0;
window->loadIndex = 0;
window->loadSum = 0;
window->foreCount = 0;
window->foreIndex = 0;
}
int updateSlidingWindow(sliding_window_t *window, double_t pcc, double_t load)
{
// 如果窗口尚未填满,直接添加数据并更新总和
if (window->pccCount < 450)
{
window->pccDemand[window->pccCount] = pcc;
window->pccSum += pcc;
window->pccCount++;
window->loadDemand[window->loadCount] = load;
window->loadSum += load;
window->loadCount++;
return 0;
}
else
{
// 如果窗口已经填满,移除最早的数据并添加新数据
window->pccSum -= window->pccDemand[window->pccIndex];
window->pccDemand[window->pccIndex] = pcc;
window->pccSum += pcc;
window->pccIndex = (window->pccIndex + 1) % 450; // 更新索引
window->loadSum -= window->loadDemand[window->loadIndex];
window->loadDemand[window->loadIndex] = load;
window->loadSum += load;
window->loadIndex = (window->loadIndex + 1) % 450; // 更新索引
return 1;
}
}
int UpdateForeDemand(sliding_window_t *window, double_t fore)
{
// 如果窗口尚未填满,直接添加数据并更新总和
if (window->foreCount < 15)
{
window->foreDemand[window->foreCount] = fore;
window->foreCount++;
return 0;
}
else
{
// 如果窗口已经填满,移除最早的数据并添加新数据
window->foreDemand[window->foreIndex] = fore;
window->foreIndex = (window->foreIndex + 1) % 15; // 更新索引
return 1;
}
}
// 拟合二次方程
double_t fitQuadraticEquation(double_t *loadDemand)
{
// 拟合二次方程y = ax^2 + bx + c
double sum_x = 0, sum_x2 = 0, sum_x3 = 0, sum_x4 = 0;
double sum_y = 0, sum_xy = 0, sum_x2y = 0;
for (int i = 0; i < 15; ++i)
{
double x = i + 1; // 每分钟对应的时间
double y = loadDemand[i]; // 对应的数据点
sum_x += x;
sum_x2 += x * x;
sum_x3 += x * x * x;
sum_x4 += x * x * x * x;
sum_y += y;
sum_xy += x * y;
sum_x2y += x * x * y;
}
// 计算二次方程系数
double a = (sum_x2y * sum_x2 - sum_xy * sum_x3) / (sum_x2 * sum_x4 - sum_x3 * sum_x3);
double b = (sum_xy - a * sum_x3) / sum_x2;
double c = (sum_y - a * sum_x4 - b * sum_x3) / sum_x2;
printf("拟合的二次方程为: y = %.2fx^2 + %.2fx + %.2f\n", a, b, c);
return a * 15 * 15 + b * 15 + c;
}
/*****************************************************************************
* @brief 获取实际需量 但是不能超过变压器器容量
* @param[in] float_t aimDemand 目标需量 float_t nowDemand 实时电表需量
* float_t maxActivePower 变压器容量
* @return float_t 实际需量
*****************************************************************************/
float_t getActiveDemand(float_t aimDemand, float_t nowDemand, float_t maxActivePower)
{
return float_min(float_max(aimDemand, nowDemand), maxActivePower);
}
/*****************************************************************************
* @brief 需量超阈值防护判断及处理
* @param[in] protect_demand_t demandParams 运行参数
* @return 参数指针返回
*****************************************************************************/
void logic_protect_demandCtrl(protect_params_t *charge_params)
{
float_t demand = getActiveDemand(charge_params->aimActiveDemand, charge_params->nowActiveDemand, charge_params->maxActivePower);
float_t tmp_active_demand = demand - charge_params->demandCtrlCloseLimt; // 预留
if (tmp_active_demand >= charge_params->totalActivePower) // 关机判断
{
float_t load_active_power = charge_params->totalActivePower - charge_params->emsActivePower; // 算出负载功率
tmp_active_demand = demand - charge_params->demandCtrlLowLimt; // 限流值
if (tmp_active_demand >= charge_params->totalActivePower) // 限流判断
{
float_t tmp_power = tmp_active_demand - load_active_power - charge_params->demandCtrlLowLimt / 10;
if (tmp_power > 0)
{
charge_params->power = -float_min(abs(charge_params->power), tmp_power);
}
else
{
charge_params->power = 0;
}
if ((uint8_t)getRtdbPointValue(rtdbType, kDev_Type_EMS, 0, kEms_LogicLog_Enable) == 1)
{
KITLOG(LOG_MODBUS_EN, INFO_EN, "触发需量保护!!! 并网点功率:%.2f kw 目标需量:%.2f kw 实时需量:%.2f kw 新的目标功率:%.2f kw",
charge_params->totalActivePower, charge_params->aimActiveDemand, charge_params->nowActiveDemand, charge_params->power);
KITLOG(LOG_MODBUS_EN, INFO_EN, "触发需量保护!!! 并网点功率:%.2f kw 目标需量:%.2f kw 实时需量:%.2f kw 新的目标功率:%.2f kw",
charge_params->totalActivePower, charge_params->aimActiveDemand, charge_params->nowActiveDemand, charge_params->power);
}
}
else
{
float_t tmp_power = tmp_active_demand - load_active_power - charge_params->demandCtrlLowLimt / 2;
if (tmp_power > 0)
{
charge_params->power = -float_min(abs(charge_params->power), tmp_power);
}
else
{
charge_params->power = 0;
}
}
}
else
{
charge_params->power = 0;
if ((uint8_t)getRtdbPointValue(rtdbType, kDev_Type_EMS, 0, kEms_LogicLog_Enable) == 1)
{
KITLOG(LOG_MODBUS_EN, INFO_EN, "触发需量关机!!! 并网点功率:%.2f kw 目标需量:%.2f kw 实时需量:%.2f kw 新的目标功率:%.2f kw",
charge_params->totalActivePower, charge_params->aimActiveDemand, charge_params->nowActiveDemand, charge_params->power);
KITLOG(LOG_MODBUS_EN, INFO_EN, "触发需量关机!!! 并网点功率:%.2f kw 目标需量:%.2f kw 实时需量:%.2f kw 新的目标功率:%.2f kw",
charge_params->totalActivePower, charge_params->aimActiveDemand, charge_params->nowActiveDemand, charge_params->power);
}
}
}