331 lines
12 KiB
C
331 lines
12 KiB
C
/**
|
||
******************************************************************************
|
||
* @file upp_control.c
|
||
* @brief Модуль определябщий поведение УПП
|
||
******************************************************************************
|
||
* @details
|
||
******************************************************************************/
|
||
#include "upp_main.h" // всё остальное по работе с УПП
|
||
|
||
|
||
static int __CheckSimpleParamF(float *paramDist, uint16_t paramSrc, float Coef);
|
||
static int __CheckSimpleParamU32(uint32_t *paramDist, uint16_t paramSrc, float Coef);
|
||
static int __CheckSimpleParamU16(uint16_t *paramDist, uint16_t paramSrc);
|
||
static int __CheckSimpleParamU8(uint8_t *paramDist, uint16_t paramSrc, float Coef);
|
||
static void __AngleSetLimit(void);
|
||
|
||
/**
|
||
* @brief Контроль внутренних параметров УПП.
|
||
* @return HAL Status.
|
||
*/
|
||
void UPP_Control_InternalParams(void)
|
||
{
|
||
if(upp.call->go) // при запущеном УПП ничего не меняем
|
||
return;
|
||
|
||
// флаги обновились ли конфиги
|
||
static int alpha_update = 0;
|
||
static int adc_channel_update[ADC_NUMB_OF_REGULAR_CHANNELS] = {0};
|
||
static int zc_update = 0;
|
||
static int pwm_update = 0;
|
||
|
||
// временная переменная для параметров Мониторинга сети
|
||
float angle_max = upp.hangle.Config.AngleMax;
|
||
float angle_min = upp.hangle.Config.AngleMin;
|
||
float angle_pid_kp = upp.hangle.pid.Kp;
|
||
float angle_pid_ki = upp.hangle.pid.Ki;
|
||
float angle_pid_kd = upp.hangle.pid.Kd;
|
||
// временная переменная для параметров каналов АЦП
|
||
float adc_channel_max[ADC_NUMB_OF_REGULAR_CHANNELS] = {0};
|
||
uint16_t adc_channel_zero[ADC_NUMB_OF_REGULAR_CHANNELS] = {0};
|
||
// временная переменная для параметров перехода через ноль
|
||
float zc_hysteresis = upp.pm.zc.Config.Hysteresis;
|
||
uint16_t zc_debounce = upp.pm.zc.Config.DebounceSamples;
|
||
// временная переменная для параметров ШИМ
|
||
uint8_t pwm_phase_mask = upp.hpwm.Config.PhaseMask.all;
|
||
uint16_t pwm_freq = upp.hpwm.Config.Frequency;
|
||
uint8_t pwm_pulse_num = upp.hpwm.Config.PulseNumber;
|
||
// временная переменная для параметров Мониторинга сети
|
||
float pm_alpha = upp.pm.exp[0].alpha;
|
||
|
||
|
||
|
||
// Параметры регулятора Угла открытия
|
||
if(__CheckSimpleParamF(&angle_max, MB_INTERNAL.param.angle.Angle_Max, 65535))
|
||
{
|
||
alpha_update = 1;
|
||
}
|
||
if(__CheckSimpleParamF(&angle_min, MB_INTERNAL.param.angle.Angle_Min, 65535))
|
||
{
|
||
alpha_update = 1;
|
||
}
|
||
if(__CheckSimpleParamF(&angle_pid_kp, MB_INTERNAL.param.angle.PID_Kp, 10000))
|
||
{
|
||
alpha_update = 1;
|
||
}
|
||
if(__CheckSimpleParamF(&angle_pid_ki, MB_INTERNAL.param.angle.PID_Ki, 10000))
|
||
{
|
||
alpha_update = 1;
|
||
}
|
||
if(__CheckSimpleParamF(&angle_pid_kd, MB_INTERNAL.param.angle.PID_Kd, 10000))
|
||
{
|
||
alpha_update = 1;
|
||
}
|
||
|
||
|
||
|
||
// Параметры АЦП
|
||
for(int i = 0; i < ADC_NUMB_OF_REGULAR_CHANNELS; i++)
|
||
{
|
||
adc_channel_max[i] = upp.pm.adc.Coefs[i].vMax;
|
||
adc_channel_zero[i] = upp.pm.adc.Coefs[i].lZero;
|
||
|
||
// Максимальное измеряемое напряжение
|
||
if(__CheckSimpleParamF(&adc_channel_max[i], MB_INTERNAL.param.adc.ADC_Max[i], 10))
|
||
{
|
||
adc_channel_update[i] = 1;
|
||
}
|
||
// Значение АЦП при нулевом входе
|
||
if(__CheckSimpleParamU16(&adc_channel_zero[i], MB_INTERNAL.param.adc.ADC_Zero[i]))
|
||
{
|
||
adc_channel_update[i] = 1;
|
||
}
|
||
}
|
||
|
||
// Параметры алгоритма перехода через ноль
|
||
if(__CheckSimpleParamF(&zc_hysteresis, MB_INTERNAL.param.zc.Hysteresis, 10000))
|
||
{
|
||
zc_update = 1;
|
||
}
|
||
if(__CheckSimpleParamU16(&zc_debounce, MB_INTERNAL.param.zc.DebouneCouner))
|
||
{
|
||
zc_update = 1;
|
||
}
|
||
|
||
// Параметры ШИМ токов
|
||
if(__CheckSimpleParamU8(&pwm_phase_mask, MB_INTERNAL.param.pwm.PhaseMask, 1))
|
||
{
|
||
pwm_update = 1;
|
||
}
|
||
if(__CheckSimpleParamU16(&pwm_freq, MB_INTERNAL.param.pwm.Frequency))
|
||
{
|
||
pwm_update = 1;
|
||
}
|
||
if(__CheckSimpleParamU8(&pwm_pulse_num, MB_INTERNAL.param.pwm.PulseNumber, 1))
|
||
{
|
||
pwm_update = 1;
|
||
}
|
||
// Параметры мониторинга
|
||
if(__CheckSimpleParamF(&pm_alpha, MB_INTERNAL.param.pm.mean_alpha, 65535))
|
||
{
|
||
for(int i = 0; i < EXP_ALL; i++)
|
||
{
|
||
Filter_ReInit(&upp.pm.exp[i], pm_alpha);
|
||
}
|
||
}
|
||
|
||
|
||
|
||
// Обновление регулятора угла открытия
|
||
if(alpha_update)
|
||
{
|
||
Angle_SetRange(&upp.hangle, angle_min, angle_max);
|
||
Angle_PID_Init(&upp.hangle, angle_pid_kp, angle_pid_ki, angle_pid_kd);
|
||
}
|
||
// Обновление АЦП конфигов
|
||
for(int i = 0; i < ADC_NUMB_OF_REGULAR_CHANNELS; i++)
|
||
{
|
||
if(adc_channel_update[i])
|
||
{
|
||
if(ADC_ConfigChannel(&upp.pm.adc, i, adc_channel_zero[i], adc_channel_max[i], 4095) == HAL_OK)
|
||
adc_channel_update[i] = 0;
|
||
else
|
||
errors.prvt.cnt.adc_reinit_err++;
|
||
}
|
||
}
|
||
// Обновление Zero-Cross конфигов
|
||
if(zc_update)
|
||
{
|
||
if(ZC_Init(&upp.pm.zc, upp.pm.zc.Config.NumChannels, zc_hysteresis, zc_debounce) == HAL_OK)
|
||
zc_update = 0;
|
||
else
|
||
errors.prvt.cnt.zc_reinit_err++;
|
||
}
|
||
// Обновление ШИМ конфигов
|
||
if(pwm_update)
|
||
{
|
||
if(PWM_SetConfig(&upp.hpwm, pwm_phase_mask, pwm_freq, pwm_pulse_num) == HAL_OK)
|
||
{
|
||
pwm_update = 0;
|
||
__AngleSetLimit();
|
||
}
|
||
else
|
||
errors.prvt.cnt.pwm_reinit_err++;
|
||
}
|
||
if (upp.hangle.Config.AngleLimit == 0)
|
||
{
|
||
__AngleSetLimit();
|
||
}
|
||
}
|
||
|
||
|
||
/**
|
||
* @brief Установка параметров на дефолтные значения @ref UPP_DEFAULT_PARAMS.
|
||
* @param pui_default Сбросить параметры ПУИ
|
||
* @param internal_default Сбросить внутренние параметры
|
||
* @return HAL Status.
|
||
*/
|
||
void UPP_SetDefault(int pui_default, int internal_default)
|
||
{
|
||
if(pui_default)
|
||
{
|
||
MB_DATA.HoldRegs.pui_params.Iref = PUI_Iref_PERCENT_DEFAULT;
|
||
MB_DATA.HoldRegs.pui_params.Tnt = PUI_Tnt_MS_DEFAULT;
|
||
MB_DATA.HoldRegs.pui_params.Umin = PUI_Umin_PERCENT_DEFAULT;
|
||
MB_DATA.HoldRegs.pui_params.Umax = PUI_Umax_PERCENT_DEFAULT;
|
||
MB_DATA.HoldRegs.pui_params.Imax = PUI_Imax_PERCENT_DEFAULT;
|
||
MB_DATA.HoldRegs.pui_params.Imin = PUI_Imin_PERCENT_DEFAULT;
|
||
MB_DATA.HoldRegs.pui_params.TiMax = PUI_TiMax_US_DEFAULT;
|
||
MB_DATA.HoldRegs.pui_params.Tdelay = PUI_Tdelay_SECONDS_DEFAULT;
|
||
MB_DATA.HoldRegs.pui_params.Interlace = PUI_Interlace_EN_DEFAULT;
|
||
}
|
||
|
||
if(internal_default)
|
||
{
|
||
MB_INTERNAL.param.setpoints.TemperatureWarn = SETPOINT_TEMP_WARN*10;
|
||
MB_INTERNAL.param.setpoints.TemperatureErr = SETPOINT_TEMP_ERR*10;
|
||
|
||
MB_INTERNAL.param.nominal.PhaseNumber = NOM_PHASE_NUMB;
|
||
MB_INTERNAL.param.nominal.U = NOM_U_V_DEFAULT*10;
|
||
MB_INTERNAL.param.nominal.U_deviation_plus = NOM_U_DEVIATION_PLUS_PERCENT_DEFAULT*100;
|
||
MB_INTERNAL.param.nominal.U_deviation_minus = NOM_U_DEVIATION_MINUS_PERCENT_DEFAULT*100;
|
||
MB_INTERNAL.param.nominal.F = NOM_F_HZ_DEFAULT*100;
|
||
MB_INTERNAL.param.nominal.F_deviation_plus = NOM_F_DEVIATION_PLUS_PERCENT_DEFAULT*100;
|
||
MB_INTERNAL.param.nominal.F_deviation_minus = NOM_F_DEVIATION_MINUS_PERCENT_DEFAULT*100;
|
||
MB_INTERNAL.param.nominal.I = NOM_I_A_DEFAULT*10;
|
||
|
||
MB_INTERNAL.param.pm.mean_alpha = PM_EXP_ALPHA_COEF_DEFAULT*65535;
|
||
|
||
MB_INTERNAL.param.adc.ADC_Max[ADC_CHANNEL_UBA] = ADC_U_MAX_V_DEFAULT*10;
|
||
MB_INTERNAL.param.adc.ADC_Max[ADC_CHANNEL_UAC] = ADC_U_MAX_V_DEFAULT*10;
|
||
MB_INTERNAL.param.adc.ADC_Max[ADC_CHANNEL_IC] = ADC_I_MAX_A_DEFAULT*10;
|
||
MB_INTERNAL.param.adc.ADC_Max[ADC_CHANNEL_IA] = ADC_I_MAX_A_DEFAULT*10;
|
||
MB_INTERNAL.param.adc.ADC_Zero[ADC_CHANNEL_UBA] = ADC_U_ZERO_DEFAULT;
|
||
MB_INTERNAL.param.adc.ADC_Zero[ADC_CHANNEL_UAC] = ADC_U_ZERO_DEFAULT;
|
||
MB_INTERNAL.param.adc.ADC_Zero[ADC_CHANNEL_IC] = ADC_I_ZERO_DEFAULT;
|
||
MB_INTERNAL.param.adc.ADC_Zero[ADC_CHANNEL_IA] = ADC_I_ZERO_DEFAULT;
|
||
|
||
MB_INTERNAL.param.pwm.PhaseMask = 0x7; // (все три фазы)
|
||
MB_INTERNAL.param.pwm.Frequency = (float)PWM_THYR_FREQUENCY_HZ_DEFAULT;
|
||
MB_INTERNAL.param.pwm.PulseNumber = PWM_THYR_PULSE_NUMBER_DEFAULT;
|
||
|
||
MB_INTERNAL.param.zc.Hysteresis = ZERO_CROSS_HYSTERESIS_PERCENT_DEFAULT*100;
|
||
MB_INTERNAL.param.zc.DebouneCouner = ZERO_CROSS_DEBOUNCE_CNT_DEFAULT;
|
||
//__AngleSetLimit();
|
||
}
|
||
}
|
||
|
||
|
||
|
||
static void __AngleSetLimit(void)
|
||
{
|
||
// Перерасчет максимально допустимого угла
|
||
float pulses_percent_of_period = ((MB_INTERNAL.param.pwm.PulseNumber / MB_INTERNAL.param.pwm.Frequency) * 1000) / ANGLE_PERIOD_MS(NOM_F_HZ_DEFAULT);
|
||
float angle_limit = 1 - pulses_percent_of_period;
|
||
Angle_SetLimit(&upp.hangle, angle_limit);
|
||
}
|
||
|
||
|
||
|
||
/**
|
||
* @brief Сверить и обновить float параметр из uint16_t.
|
||
* @param paramDist Указатель на float параметр
|
||
* @param paramSrc Значение для сравнения с float параметром
|
||
* @param Coef Коэффициент для приведения float к uint16_t: uint16_t = float*coef, float = uint16_t/coef
|
||
* @return 0 - параметры совпадают, 1 - параметр был обновлен на paramSrc.
|
||
*/
|
||
static int __CheckSimpleParamF(float *paramDist, uint16_t paramSrc, float Coef)
|
||
{
|
||
if(paramDist == NULL)
|
||
return 0;
|
||
|
||
uint16_t expected_mb_param = *paramDist*Coef;
|
||
if(expected_mb_param != paramSrc)
|
||
{
|
||
*paramDist = (float)paramSrc/Coef;
|
||
return 1;
|
||
}
|
||
else
|
||
{
|
||
return 0;
|
||
}
|
||
}
|
||
/**
|
||
* @brief Сверить и обновить uint32_t параметр из uint16_t.
|
||
* @param paramDist Указатель на uint32_t параметр
|
||
* @param paramSrc Значение для сравнения с uint32_t параметром
|
||
* @param Coef Коэффициент для приведения uint32_t к uint16_t: uint16_t = uint32_t*coef, uint32_t = uint16_t/coef
|
||
* @return 0 - параметры совпадают, 1 - параметр был обновлен на paramSrc.
|
||
*/
|
||
static int __CheckSimpleParamU32(uint32_t *paramDist, uint16_t paramSrc, float Coef)
|
||
{
|
||
if(paramDist == NULL)
|
||
return 0;
|
||
|
||
uint16_t expected_mb_param = *paramDist*Coef;
|
||
if(expected_mb_param != paramSrc)
|
||
{
|
||
*paramDist = (uint32_t)paramSrc/Coef;
|
||
return 1;
|
||
}
|
||
else
|
||
{
|
||
return 0;
|
||
}
|
||
}
|
||
/**
|
||
* @brief Сверить и обновить uint16_t параметр из uint16_t.
|
||
* @param paramDist Указатель на uint16_t параметр
|
||
* @param paramSrc Значение для сравнения с uint16_t параметром
|
||
* @return 0 - параметры совпадают, 1 - параметр был обновлен на paramSrc.
|
||
*/
|
||
static int __CheckSimpleParamU16(uint16_t *paramDist, uint16_t paramSrc)
|
||
{
|
||
if(paramDist == NULL)
|
||
return 0;
|
||
|
||
uint16_t expected_mb_param = *paramDist;
|
||
if(expected_mb_param != paramSrc)
|
||
{
|
||
*paramDist = (uint16_t)paramSrc;
|
||
return 1;
|
||
}
|
||
else
|
||
{
|
||
return 0;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @brief Сверить и обновить uint8_t параметр из uint16_t.
|
||
* @param paramDist Указатель на uint8_t параметр
|
||
* @param paramSrc Значение для сравнения с uint32_t параметром
|
||
* @param Coef Коэффициент для приведения uint32_t к uint16_t: uint16_t = uint8_t*coef, uint8_t = uint16_t/coef
|
||
* @return 0 - параметры совпадают, 1 - параметр был обновлен на paramSrc.
|
||
*/
|
||
static int __CheckSimpleParamU8(uint8_t *paramDist, uint16_t paramSrc, float Coef)
|
||
{
|
||
if(paramDist == NULL)
|
||
return 0;
|
||
|
||
uint16_t expected_mb_param = *paramDist*Coef;
|
||
if(expected_mb_param != paramSrc)
|
||
{
|
||
*paramDist = (uint8_t)paramSrc/Coef;
|
||
return 1;
|
||
}
|
||
else
|
||
{
|
||
return 0;
|
||
}
|
||
} |