Files
UPP/UPP/Core/PowerMonitor/power_protect.c
Razvalyaev 804d302d2d Проверены и оптимизирвоаны защиты
- в матлаб проверена отрабокта всех защит
- добавлены быстрые защиты на КЗ, которые проверяются в прерывании АЦП
- определены и проверены более менее приоритеты ошибок

- в мтлаб добавлена симуляция MOE расширенных таймеров
2026-02-03 16:32:30 +03:00

231 lines
6.1 KiB
C
Raw 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.
/**
******************************************************************************
* @file power_protect.c
* @brief Модуль реализующий защиты по Напряжению/Токам/Температуре
******************************************************************************
* @details
******************************************************************************/
#include "power_protect.h"
/**
* @brief Проверяет защиты по напряжению.
* @note Заполняет флаги prvt ошибок (приватные).
* Потом в @ref UPP_ErrorsHandle исходя из них заполняются ошибки для ПУИ
* @return 1 - напряжение есть, 0 - напряжения нет
*/
int Protect_Voltages(PowerMonitor_Measured_t *measure, UPP_PUI_Params_t *params, UPP_ParamsNominal_t *nominal)
{
/* Переводим уставки ПУИ в удобный вид */
float lUmin = u2f(params->Umin, 100)/**u2f(nominal->U, 10)*/;
float lUmax = u2f(params->Umax, 100)/**u2f(nominal->U, 10)*/;
UPP_PhaseSequence_t nomPhaseSequence = nominal->PhaseSequence;
/* Общее напряжение */
if(measure->final.Uamp > lUmax)
{
ERR_PRIVATE->uamp_max = 1;
}
else if (measure->final.Uamp < lUmin)
{
ERR_PRIVATE->uamp_min = 1;
}
else
{
ERR_PRIVATE->uamp_max = 0;
ERR_PRIVATE->uamp_min = 0;
}
/* Последовательность фаз */
if(measure->final.PhaseSequence != nomPhaseSequence)
{
ERR_PRIVATE->interlance = 1;
}
else
{
ERR_PRIVATE->interlance = 0;
}
return (ERR_PRIVATE->uamp_min == 0);
}
/**
* @brief Проверяет защиты по току.
* @note Заполняет флаги prvt ошибок (приватные).
* Потом в @ref UPP_ErrorsHandle исходя из них заполняются ошибки для ПУИ
*/
int Protect_Currents(PowerMonitor_Measured_t *measure, UPP_PUI_Params_t *params, UPP_ParamsNominal_t *nominal)
{
/* Переводим уставки ПУИ в удобный вид */
float lIref = u2f(params->Iref, 100)/**u2f(nominal->I, 10)*/;
float lImin = u2f(params->Imin, 100)/**u2f(nominal->I, 10)*/;
float lImax = u2f(params->Imax, 100) * 50 / u2f(nominal->I, 10); // Imax процентов от 50 А, в о.е. от номинального
/* Общий ток */
if(measure->final.Iamp > lImax)
{
ERR_PRIVATE->iamp_max = 1;
}
else if (measure->final.Iamp < lImin)
{
ERR_PRIVATE->iamp_min = 1;
}
else
{
// ERR_PRIVATE->iamp_max = 0;
// ERR_PRIVATE->iamp_min = 0;
}
/* Ток по фазам */
if(measure->final.I[I_A] > lImax)
{
ERR_PRIVATE->ia_max = 1;
}
else if (measure->final.I[I_A] < lImin)
{
ERR_PRIVATE->ia_min = 1;
}
else
{
// ERR_PRIVATE->ia_max = 0;
// ERR_PRIVATE->ia_min = 0;
}
if(measure->final.I[I_B] > lImax)
{
ERR_PRIVATE->ib_max = 1;
}
else if (measure->final.I[I_B] < lImin)
{
ERR_PRIVATE->ib_min = 1;
}
else
{
// ERR_PRIVATE->ib_max = 0;
// ERR_PRIVATE->ib_min = 0;
}
if(measure->final.I[I_C] > lImax)
{
ERR_PRIVATE->ic_max = 1;
}
else if (measure->final.I[I_C] < lImin)
{
ERR_PRIVATE->ic_min = 1;
}
else
{
// ERR_PRIVATE->ic_max = 0;
// ERR_PRIVATE->ic_min = 0;
}
return (ERR_PRIVATE->iamp_min == 0);
}
/**
* @brief Проверяет быстрые защиты.
* @note Заполняет флаги prvt ошибок (приватные).
* Потом в @ref UPP_ErrorsHandle исходя из них заполняются ошибки для ПУИ
*/
void Protect_Fast(PowerMonitor_Measured_t *measure, float lImaxAmp)
{
// /* Переводим уставки ПУИ в удобный вид */
// float lImaxAmp = u2f(params->Imax, 100) * 50 / u2f(nominal->I, 10) *1.41; // Амплитудное значение Imax
/* Ток по фазам */
if(measure->fast.I[I_A] > lImaxAmp)
{
ERR_PRIVATE->ia_max = 1;
}
if(measure->fast.I[I_B] > lImaxAmp)
{
ERR_PRIVATE->ib_max = 1;
}
if(measure->fast.I[I_C] > lImaxAmp)
{
ERR_PRIVATE->ic_max = 1;
}
}
/**
* @brief Проверяет всякие другие защиты (частота, температура).
* @note Заполняет флаги prvt ошибок (приватные).
* Потом в @ref UPP_ErrorsHandle исходя из них заполняются ошибки для ПУИ
*/
void Protect_Misc(PowerMonitor_Measured_t *measure, UPP_PUI_Params_t *params, UPP_ParamsNominal_t *nominal)
{
/* Переводим внутренние уставки в удобный вид */
float lFnom = u2f(nominal->F, 100);
float lFmin = lFnom - lFnom*u2f(nominal->F_deviation_minus, 10000);
float lFmax = lFnom + lFnom*u2f(nominal->F_deviation_plus, 10000);
float lTwarn = PARAM_INTERNAL->temp.TemperatureWarn;
float lTerr = PARAM_INTERNAL->temp.TemperatureWarn;
/*=============== ЗАЩИТЫ ПО ЧАСТОТЕ ==================*/
if(measure->final.F[U_CA] > lFmax)
{
ERR_PRIVATE->fac_max = 1;
}
else if (measure->final.F[U_CA] < lFmin)
{
ERR_PRIVATE->fac_min = 1;
}
else
{
ERR_PRIVATE->fac_max = 0;
ERR_PRIVATE->fac_min = 0;
}
if(measure->final.F[U_AB] > lFmax)
{
ERR_PRIVATE->fba_max = 1;
}
else if (measure->final.F[U_AB] < lFmin)
{
ERR_PRIVATE->fba_min = 1;
}
else
{
ERR_PRIVATE->fba_max = 0;
ERR_PRIVATE->fba_min = 0;
}
if(measure->final.F[U_BC] > lFmax)
{
ERR_PRIVATE->fbc_max = 1;
}
else if (measure->final.F[U_BC] < lFmin)
{
ERR_PRIVATE->fbc_min = 1;
}
else
{
ERR_PRIVATE->fbc_max = 0;
ERR_PRIVATE->fbc_min = 0;
}
/*=============== ЗАЩИТЫ ПО ТЕМПЕРАТУРЕ ==================*/
if(measure->final.T[TEMP_1] > lTerr)
{
ERR_PRIVATE->temp_err = 1;
}
else if (measure->final.T[TEMP_1] > lTwarn)
{
ERR_PRIVATE->temp_warn = 1;
}
else
{
ERR_PRIVATE->temp_err = 0;
ERR_PRIVATE->temp_warn = 0;
}
}