172 lines
6.2 KiB
C
172 lines
6.2 KiB
C
/*****************************************************************************
|
||
* @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);
|
||
}
|
||
}
|
||
} |