forked from gary/ems
2
0
Fork 0
sun_ems/ems_c/logic/logic_demandctrl.c

172 lines
6.2 KiB
C
Raw Normal View History

2025-05-13 17:49:49 +08:00
/*****************************************************************************
* @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);
}
}
}