217 lines
7.3 KiB
C
217 lines
7.3 KiB
C
/**
|
||
******************************************************************************
|
||
* @file upp_errors.c
|
||
* @brief Формирование ошибок в ПУИ
|
||
******************************************************************************
|
||
* @details
|
||
******************************************************************************/
|
||
#include "upp_main.h" // УПП
|
||
#include "upp_errors.h" // всё остальное по работе с УПП
|
||
UPP_Errors_t errors;
|
||
|
||
static UPP_ErrorType_t UPP_SelectCommonError(void);
|
||
static int setError(int condition, int flag, int *timer, int delay);
|
||
void UPP_Errors_Program(void);
|
||
void UPP_Errors_Power(void);
|
||
void UPP_Errors_Ranges(void);
|
||
void UPP_Errors_LossPhase(void);
|
||
void UPP_Errors_Other(void);
|
||
|
||
|
||
|
||
void UPP_Errors_Handle(void)
|
||
{
|
||
/*====== Программные ошибки ======*/
|
||
UPP_Errors_Program();
|
||
/*====== Ошибки питания плат ======*/
|
||
UPP_Errors_Power();
|
||
/*====== Ошибки выхода за допустимые пределы ======*/
|
||
UPP_Errors_Ranges();
|
||
/*====== Потери фазы ======*/
|
||
UPP_Errors_LossPhase();
|
||
/*====== Остальные ======*/
|
||
UPP_Errors_Other();
|
||
|
||
|
||
|
||
|
||
|
||
errors.common = UPP_SelectCommonError();
|
||
}
|
||
|
||
void UPP_Errors_Program(void)
|
||
{
|
||
|
||
}
|
||
|
||
void UPP_Errors_Power(void)
|
||
{
|
||
//read discrete inputs
|
||
}
|
||
|
||
void UPP_Errors_Ranges(void)
|
||
{
|
||
/* Преобразуем уставки в нормальные тики */
|
||
float ticksTiMax = to_float(MB_DATA.HoldRegs.pui_params.TiMax, 1)/PM_SLOW_PERIOD_US;
|
||
/* Счетчики для отсчитывания задержки выставления ошибки */
|
||
static int IMaxCnt = 0;
|
||
static int UMaxCnt = 0;
|
||
static int UMinCnt = 0;
|
||
static int FMaxCnt = 0;
|
||
static int FMinCnt = 0;
|
||
static int TMaxCnt = 0;
|
||
|
||
/* Напряжения */
|
||
errors.pui.err.OverVoltage = setError(errors.prvt.f.err.uamp_max,
|
||
errors.pui.err.OverVoltage,
|
||
&UMaxCnt,
|
||
ticksTiMax);
|
||
errors.pui.err.UnderVoltage = setError(errors.prvt.f.err.uamp_min,
|
||
errors.pui.err.UnderVoltage,
|
||
&UMinCnt,
|
||
ticksTiMax);
|
||
|
||
|
||
/* Токи */
|
||
int i_max = ( errors.prvt.f.err.iamp_max ||
|
||
errors.prvt.f.err.ia_max ||
|
||
errors.prvt.f.err.ib_max ||
|
||
errors.prvt.f.err.ic_max);
|
||
errors.pui.err.OverCurrent = setError(i_max,
|
||
errors.pui.err.OverCurrent,
|
||
&IMaxCnt,
|
||
ticksTiMax);
|
||
|
||
|
||
/* Частота */
|
||
int f_max = ( errors.prvt.f.err.fac_max ||
|
||
errors.prvt.f.err.fba_max ||
|
||
errors.prvt.f.err.fbc_max);
|
||
int f_min = ( errors.prvt.f.err.fac_max ||
|
||
errors.prvt.f.err.fba_max ||
|
||
errors.prvt.f.err.fbc_max);
|
||
errors.pui.err.OverFrequency = setError(f_max,
|
||
errors.pui.err.OverFrequency,
|
||
&FMaxCnt,
|
||
ERRORS_DELAY_TICKS_DEFAULT);
|
||
|
||
errors.pui.err.UnderFrequency = setError( f_min,
|
||
errors.pui.err.UnderFrequency,
|
||
&FMinCnt,
|
||
ERRORS_DELAY_TICKS_DEFAULT);
|
||
|
||
|
||
/* Температуры */
|
||
errors.pui.err.OverTemperature = setError(errors.prvt.f.err.temp_err,
|
||
errors.pui.err.OverTemperature,
|
||
&TMaxCnt,
|
||
ERRORS_DELAY_TICKS_DEFAULT);
|
||
}
|
||
|
||
void UPP_Errors_LossPhase(void)
|
||
{
|
||
/* Счетчики для отсчитывания задержки выставления ошибки */
|
||
static int LossPhaseAllCnt = 0;
|
||
static int LossPhaseACnt = 0;
|
||
static int LossPhaseBCnt = 0;
|
||
static int LossPhaseCCnt = 0;
|
||
|
||
int loss_phases_all = ( errors.prvt.f.err.ia_min &&
|
||
errors.prvt.f.err.ib_min &&
|
||
errors.prvt.f.err.ic_min );
|
||
|
||
errors.pui.err.LossPhaseAll = setError( loss_phases_all,
|
||
errors.pui.err.LossPhaseAll,
|
||
&LossPhaseAllCnt,
|
||
ERRORS_DELAY_TICKS_DEFAULT);
|
||
|
||
/* Если хотя бы одна фаза есть проверяем фазы отдельно */
|
||
if(!errors.pui.err.LossPhaseAll)
|
||
{
|
||
errors.pui.err.LossPhaseA = setError( errors.prvt.f.err.ia_min,
|
||
errors.pui.err.LossPhaseA,
|
||
&LossPhaseACnt,
|
||
ERRORS_DELAY_TICKS_DEFAULT);
|
||
|
||
errors.pui.err.LossPhaseB = setError( errors.prvt.f.err.ib_min,
|
||
errors.pui.err.LossPhaseB,
|
||
&LossPhaseBCnt,
|
||
ERRORS_DELAY_TICKS_DEFAULT);
|
||
|
||
errors.pui.err.LossPhaseC = setError( errors.prvt.f.err.ic_min,
|
||
errors.pui.err.LossPhaseC,
|
||
&LossPhaseCCnt,
|
||
ERRORS_DELAY_TICKS_DEFAULT);
|
||
}
|
||
/* Если всех фаз нет, то отдельные не смотрим */
|
||
else
|
||
{
|
||
errors.pui.err.LossPhaseA = 0;
|
||
errors.pui.err.LossPhaseB = 0;
|
||
errors.pui.err.LossPhaseC = 0;
|
||
}
|
||
}
|
||
|
||
void UPP_Errors_Other(void)
|
||
{
|
||
static int InterlaceCnt = 0;
|
||
|
||
if(errors.prvt.f.err.longstart)
|
||
errors.pui.err.LongStart = 1;
|
||
else
|
||
errors.pui.err.LongStart = 0;
|
||
|
||
errors.pui.err.Interlace = setError(errors.prvt.f.err.interlance,
|
||
errors.pui.err.Interlace,
|
||
&InterlaceCnt,
|
||
ERRORS_DELAY_TICKS_DEFAULT);
|
||
//Interlance
|
||
}
|
||
|
||
static UPP_ErrorType_t UPP_SelectCommonError(void)
|
||
{
|
||
// Пока нет ошибки
|
||
UPP_ErrorType_t best = Err_None;
|
||
// Приоритет отсутствия ошибок
|
||
uint8_t best_prio = UPP_ErrorPriority[Err_None];
|
||
|
||
// Перебираем все возможные ошибки по enum
|
||
for (int e = Err_None + 1; e <= Err_UnderFrequency; e++)
|
||
{
|
||
// Проверяем: установлен ли соответствующий бит в pui.all
|
||
// e-1, потому что ошибка №1 = бит 0, ошибка №2 = бит 1 и т.д.
|
||
if (errors.pui.all & (1u << (e - 1)))
|
||
{
|
||
// Получаем приоритет этой ошибки
|
||
uint8_t pr = UPP_ErrorPriority[e];
|
||
|
||
// Если её приоритет лучше (меньше число) — запоминаем
|
||
if (pr < best_prio)
|
||
{
|
||
best_prio = pr;
|
||
best = (UPP_ErrorType_t)e;
|
||
}
|
||
}
|
||
}
|
||
|
||
// Возвращаем самую важную (наивысшего приоритета) ошибку
|
||
return best;
|
||
}
|
||
|
||
|
||
static int setError(int condition, int flag, int *timer, int delay)
|
||
{
|
||
if (condition) {
|
||
if (*timer < delay)
|
||
(*timer)++;
|
||
else
|
||
flag = 1;
|
||
} else {
|
||
if (*timer > 0)
|
||
(*timer)--;
|
||
else
|
||
flag = 0;
|
||
}
|
||
|
||
return flag;
|
||
} |