рефакторинг и вроде бы понял как надо управлять импульсами

надо доделать и проверить
This commit is contained in:
2025-12-04 15:01:55 +03:00
parent c0eea077d9
commit aa59f84fb7
16 changed files with 156 additions and 146 deletions

View File

@@ -35,19 +35,19 @@ void Write_UPP_Outputs(real_T* Buffer, int ind_port)
//int pwm4_pin = PIN_READ(PWM4); //int pwm4_pin = PIN_READ(PWM4);
//int pwm5_pin = PIN_READ(PWM5); //int pwm5_pin = PIN_READ(PWM5);
//int pwm6_pin = PIN_READ(PWM6); //int pwm6_pin = PIN_READ(PWM6);
//int pwm1_pin = (upp.hpwm.AllPhases[PHASE_A_POS].State == PWM_THYR_TIM_ACTIVE); int pwm1_pin = (upp.hpwm.AllPhases[PHASE_A_POS].State == PWM_THYR_TIM_ACTIVE);
//int pwm2_pin = (upp.hpwm.AllPhases[PHASE_A_NEG].State == PWM_THYR_TIM_ACTIVE); int pwm2_pin = (upp.hpwm.AllPhases[PHASE_A_NEG].State == PWM_THYR_TIM_ACTIVE);
//int pwm3_pin = (upp.hpwm.AllPhases[PHASE_B_POS].State == PWM_THYR_TIM_ACTIVE); int pwm3_pin = (upp.hpwm.AllPhases[PHASE_B_POS].State == PWM_THYR_TIM_ACTIVE);
//int pwm4_pin = (upp.hpwm.AllPhases[PHASE_B_NEG].State == PWM_THYR_TIM_ACTIVE); int pwm4_pin = (upp.hpwm.AllPhases[PHASE_B_NEG].State == PWM_THYR_TIM_ACTIVE);
//int pwm5_pin = (upp.hpwm.AllPhases[PHASE_C_POS].State == PWM_THYR_TIM_ACTIVE); int pwm5_pin = (upp.hpwm.AllPhases[PHASE_C_POS].State == PWM_THYR_TIM_ACTIVE);
//int pwm6_pin = (upp.hpwm.AllPhases[PHASE_C_NEG].State == PWM_THYR_TIM_ACTIVE); int pwm6_pin = (upp.hpwm.AllPhases[PHASE_C_NEG].State == PWM_THYR_TIM_ACTIVE);
pwm_wtf(upp.hpwm.AllPhases[PHASE_A_POS].State, upp.hpwm.AllPhases[PHASE_A_NEG].State, &pwm1_pin); //pwm_wtf(upp.hpwm.AllPhases[PHASE_A_POS].State, upp.hpwm.AllPhases[PHASE_A_NEG].State, &pwm1_pin);
pwm_wtf(upp.hpwm.AllPhases[PHASE_A_NEG].State, upp.hpwm.AllPhases[PHASE_A_POS].State, &pwm2_pin); //pwm_wtf(upp.hpwm.AllPhases[PHASE_A_NEG].State, upp.hpwm.AllPhases[PHASE_A_POS].State, &pwm2_pin);
pwm_wtf(upp.hpwm.AllPhases[PHASE_B_POS].State, upp.hpwm.AllPhases[PHASE_B_NEG].State, &pwm3_pin); //pwm_wtf(upp.hpwm.AllPhases[PHASE_B_POS].State, upp.hpwm.AllPhases[PHASE_B_NEG].State, &pwm3_pin);
pwm_wtf(upp.hpwm.AllPhases[PHASE_B_NEG].State, upp.hpwm.AllPhases[PHASE_B_POS].State, &pwm4_pin); //pwm_wtf(upp.hpwm.AllPhases[PHASE_B_NEG].State, upp.hpwm.AllPhases[PHASE_B_POS].State, &pwm4_pin);
pwm_wtf(upp.hpwm.AllPhases[PHASE_C_POS].State, upp.hpwm.AllPhases[PHASE_C_NEG].State, &pwm5_pin); //pwm_wtf(upp.hpwm.AllPhases[PHASE_C_POS].State, upp.hpwm.AllPhases[PHASE_C_NEG].State, &pwm5_pin);
pwm_wtf(upp.hpwm.AllPhases[PHASE_C_NEG].State, upp.hpwm.AllPhases[PHASE_C_POS].State, &pwm6_pin); //pwm_wtf(upp.hpwm.AllPhases[PHASE_C_NEG].State, upp.hpwm.AllPhases[PHASE_C_POS].State, &pwm6_pin);
int err = PIN_READ(RDO1); int err = PIN_READ(RDO1);
int work = PIN_READ(RDO2); int work = PIN_READ(RDO2);
int ready = PIN_READ(RDO3); int ready = PIN_READ(RDO3);

Binary file not shown.

View File

@@ -26,7 +26,6 @@
#define UPP_SIMULATE_I ///< Симулировт токи (Iref/2) а не брать с АЦП #define UPP_SIMULATE_I ///< Симулировт токи (Iref/2) а не брать с АЦП
#define UPP_DISABLE_PROTECT_BOARDPOWER ///< Отключить проверки питания плат (+24, +5 В) #define UPP_DISABLE_PROTECT_BOARDPOWER ///< Отключить проверки питания плат (+24, +5 В)
#define UPP_DISABLE_PROTECT_LOSS_PHASE ///< Отключить проверки на потерянные фазы #define UPP_DISABLE_PROTECT_LOSS_PHASE ///< Отключить проверки на потерянные фазы
//#define UPP_ANGLE_COSINE ///< Расчет угла через acos, а не линейно
/** //UPP_PARAMS_TEST /** //UPP_PARAMS_TEST
* @} * @}

View File

@@ -152,6 +152,8 @@ typedef struct {
// Проверка корректности структуры // Проверка корректности структуры
#define assert_upp(_struct_) check_null_ptr_2(_struct_, (_struct_)->f.Initialized) #define assert_upp(_struct_) check_null_ptr_2(_struct_, (_struct_)->f.Initialized)
// Проверка корректности структуры и фазы
#define assert_upp_phase(_struct_, _phase_) (check_null_ptr_2(_struct_, (_struct_)->f.Initialized) || (_phase_ >= 3))
/* Дефайны для индексов */ /* Дефайны для индексов */

View File

@@ -30,34 +30,8 @@ HAL_StatusTypeDef PowerMonitor_Init(PowerMonitor_t *hpm)
if(ADC_Init(&hpm->adc, &adc_tim, &hadc3) != HAL_OK) if(ADC_Init(&hpm->adc, &adc_tim, &hadc3) != HAL_OK)
return HAL_ERROR; return HAL_ERROR;
/* Инициализация каналов АЦП */
if(ADC_ConfigChannel(&hpm->adc, ADC_CHANNEL_UBA,
PARAM_INTERNAL.adc.ADC_Zero[ADC_CHANNEL_UBA],
u2f(PARAM_INTERNAL.adc.ADC_Max[ADC_CHANNEL_UBA], 10),
4095) != HAL_OK)
return HAL_ERROR;
if(ADC_ConfigChannel(&hpm->adc, ADC_CHANNEL_UAC,
PARAM_INTERNAL.adc.ADC_Zero[ADC_CHANNEL_UAC],
u2f(PARAM_INTERNAL.adc.ADC_Max[ADC_CHANNEL_UAC], 10),
4095) != HAL_OK)
return HAL_ERROR;
if(ADC_ConfigChannel(&hpm->adc, ADC_CHANNEL_IC,
PARAM_INTERNAL.adc.ADC_Zero[ADC_CHANNEL_IC],
u2f(PARAM_INTERNAL.adc.ADC_Max[ADC_CHANNEL_IC], 10),
4095) != HAL_OK)
return HAL_ERROR;
if(ADC_ConfigChannel(&hpm->adc, ADC_CHANNEL_IA,
PARAM_INTERNAL.adc.ADC_Zero[ADC_CHANNEL_IA],
u2f(PARAM_INTERNAL.adc.ADC_Max[ADC_CHANNEL_IA], 10),
4095) != HAL_OK)
return HAL_ERROR;
/* Инициализация алгоритма перехода через ноль */ /* Инициализация алгоритма перехода через ноль */
if(ZC_Init(&hpm->zc, 3, u2f(PARAM_INTERNAL.zc.Hysteresis, 100), PARAM_INTERNAL.zc.DebouneCouner) != HAL_OK) if(ZC_Init(&hpm->zc, 3, 0, 0) != HAL_OK)
return HAL_ERROR; return HAL_ERROR;
/* Инициализация каналов алгоритма перехода через ноль */ /* Инициализация каналов алгоритма перехода через ноль */
@@ -69,21 +43,6 @@ HAL_StatusTypeDef PowerMonitor_Init(PowerMonitor_t *hpm)
return HAL_ERROR; return HAL_ERROR;
/* Инициализация RMS фильтра медленного алга */
for(int i = 0; i < RMS_ALL; i++)
{
if(FilterRMS_Init(&hpm->rms[i], PARAM_INTERNAL.pm.rms_window_size))
return HAL_ERROR;
Filter_Start(&hpm->rms[i]);
}
/* Инициализация экпоненциального фильтра медленного алга */
for(int i = 0; i < RMS_EXP_ALL; i++)
{
if(FilterExp_Init(&hpm->rms_exp[i], u2f(PARAM_INTERNAL.pm.rms_exp_alpha, 65535)))
return HAL_ERROR;
Filter_Start(&hpm->rms_exp[i]);
}
/* Инициализация среднего фильтра медленного алга */ /* Инициализация среднего фильтра медленного алга */
for(int i = 0; i < ADC_NUMB_OF_REGULAR_CHANNELS; i++) for(int i = 0; i < ADC_NUMB_OF_REGULAR_CHANNELS; i++)
{ {

View File

@@ -32,19 +32,11 @@ HAL_StatusTypeDef Angle_Init(Angle_Handle_t *hangle)
Angle_Reset(hangle, UPP_PHASE_B); Angle_Reset(hangle, UPP_PHASE_B);
Angle_Reset(hangle, UPP_PHASE_C); Angle_Reset(hangle, UPP_PHASE_C);
// Инициализация углов
float angle_max = u2f(PARAM_INTERNAL.angle.Angle_Max, 65535);
float angle_min = u2f(PARAM_INTERNAL.angle.Angle_Min, 65535);
hangle->f.Initialized = 1; hangle->f.Initialized = 1;
hangle->Config.PeriodLimit = 1; hangle->Config.PeriodLimit = 1;
// Инициализация ПИД
float kp = u2f(PARAM_INTERNAL.angle.PID_Kp, 10000);
float ki = u2f(PARAM_INTERNAL.angle.PID_Ki, 10000);
float kd = u2f(PARAM_INTERNAL.angle.PID_Kd, 10000);
float ref_alpha = PUI_Tnt_CalcAlpha(u2f(PARAM_PUI.Tnt, 1000), PM_SLOW_PERIOD_US);
return Angle_PID_Init(hangle, kp, ki, kd, ref_alpha); return HAL_OK;
} }
@@ -89,14 +81,20 @@ void Angle_PID(Angle_Handle_t *hangle, float setpoint, float measurement)
float err = hangle->Iref - hangle->Imeas; float err = hangle->Iref - hangle->Imeas;
/* ПИД регулирование */ /* ПИД регулирование */
float open_control = arm_pid_f32(&hangle->pid, err); // 0 - открыть максимально поздно, 1 - открыть макситмально рано float open_level = arm_pid_f32(&hangle->pid, err); // 0 - открыть максимально поздно, 1 - открыть макситмально рано
/* Ограничиваем диапазон */ /* Ограничиваем диапазон */
if (open_control > 1) open_control = 1; if (open_level > 1) open_level = 1;
if(open_control < 0) open_control = 0; if(open_level < 0) open_level = 0;
/* Приводим уровень открытия к косинусу [-1:1]*/
float OpenLevelForCos = (open_level*2)-1;
float alpha_rad = acosf(OpenLevelForCos); // угол в радианах
float alpha = alpha_rad/PI* hangle->Config.PeriodLimit; // угол открытия тиристора в о.е. от максимально заданного
/* Выставляем заданный уровень открытия */ /* Выставляем заданный уровень открытия */
Angle_SetAngle(hangle, open_control); Angle_SetAlpha(hangle, alpha);
} }
/** /**
@@ -118,7 +116,8 @@ void Angle_PID_Reset(Angle_Handle_t *hangle)
Filter_Start(&hangle->refFilter); Filter_Start(&hangle->refFilter);
Filter_Process(&hangle->refFilter, 0); Filter_Process(&hangle->refFilter, 0);
Angle_SetAngle(hangle, 0); Angle_SetAlpha(hangle, 1); // максимально закрываем
Angle_Reset(hangle, UPP_PHASE_A); Angle_Reset(hangle, UPP_PHASE_A);
Angle_Reset(hangle, UPP_PHASE_B); Angle_Reset(hangle, UPP_PHASE_B);
Angle_Reset(hangle, UPP_PHASE_C); Angle_Reset(hangle, UPP_PHASE_C);
@@ -128,39 +127,26 @@ void Angle_PID_Reset(Angle_Handle_t *hangle)
/** /**
* @brief Выставление степени открытия тиристоров. * @brief Выставление степени открытия тиристоров.
* @param hangle Указатель на таймер * @param hangle Указатель на таймер
* @param OpenLevel Насколько открыть тиристор: * @param Alpha Угол открытия тиристора в о.е. от 180 градусов:
- 0 - максимально закрыт, - 0 - максимально закрыт,
- 1 - максимально открыт - 1 - максимально открыт
* @return HAL Status. * @return HAL Status.
*/ */
HAL_StatusTypeDef Angle_SetAngle(Angle_Handle_t *hangle, float OpenLevel) HAL_StatusTypeDef Angle_SetAlpha(Angle_Handle_t *hangle, float Alpha)
{ {
if(assert_upp(hangle)) if(assert_upp(hangle))
return HAL_ERROR; return HAL_ERROR;
/* Приводим уровень открытия к косинусу [-1:1]*/
#ifdef UPP_ANGLE_COSINE
float OpenLevelForCos = (OpenLevel*2)-1;
float alpha_rad = acosf(OpenLevelForCos); // угол в радианах
float alpha = alpha_rad/PI* hangle->Config.PeriodLimit; // время открытие в процентах от периода - когда открыть
#else
float alpha = (1-OpenLevel) * hangle->Config.PeriodLimit; // время открытие в процентах от периода - когда открыть
#endif
if(alpha > hangle->Config.AngleMax) if(Alpha > hangle->Config.AngleMax)
alpha = hangle->Config.AngleMax; Alpha = hangle->Config.AngleMax;
if(alpha < hangle->Config.AngleMin) if(Alpha < hangle->Config.AngleMin)
alpha = hangle->Config.AngleMin; Alpha = hangle->Config.AngleMin;
// if(alpha > hangle->Config.PeriodLimit)
// {
// alpha = hangle->Config.PeriodLimit;
// }
// float alpha_degree = alpha*180;// угол в градусах // сколько надо выжидать исходя из заданного угла
// hangle->alpha_degree = alpha_degree; hangle->alpha_real = Alpha + (30.0/180.0); // 30 градусов - сдвиг между линейными и фазными напряжениями
hangle->alpha = Alpha;
hangle->alpha = alpha;
@@ -175,26 +161,11 @@ HAL_StatusTypeDef Angle_SetAngle(Angle_Handle_t *hangle, float OpenLevel)
*/ */
HAL_StatusTypeDef Angle_Start(Angle_Handle_t *hangle, UPP_Phase_t Phase, float PeriodMs) HAL_StatusTypeDef Angle_Start(Angle_Handle_t *hangle, UPP_Phase_t Phase, float PeriodMs)
{ {
if(assert_upp(hangle)) if(assert_upp_phase(hangle, Phase))
return HAL_ERROR; return HAL_ERROR;
// Если канал дурацкий - возвращаем ошибку
if(Phase >= 3)
{
return HAL_ERROR;
}
// Дополнительно проверяем на соответствие альфа диапазону
if(hangle->alpha > hangle->Config.AngleMax)
{
hangle->alpha = hangle->Config.AngleMax;
}
if(hangle->alpha < hangle->Config.AngleMin)
{
hangle->alpha = hangle->Config.AngleMin;
}
// сколько тиков надо выждать для угла // сколько тиков надо выждать для угла
uint32_t timer_ticks = TIM_MillisToTick(PeriodMs*hangle->alpha, ANGLE_TIM2_FREQ_MHZ); uint32_t timer_ticks = TIM_MillisToTick(PeriodMs*hangle->alpha_real, ANGLE_TIM2_FREQ_MHZ);
// сколько тиков будет в таймере когда угол отсчитается (пойдет в CCRx регистр) // сколько тиков будет в таймере когда угол отсчитается (пойдет в CCRx регистр)
uint32_t ccr_ticks = __HAL_TIM_GET_COUNTER(hangle->htim) + timer_ticks; uint32_t ccr_ticks = __HAL_TIM_GET_COUNTER(hangle->htim) + timer_ticks;
@@ -259,15 +230,9 @@ HAL_StatusTypeDef Angle_Start(Angle_Handle_t *hangle, UPP_Phase_t Phase, float P
*/ */
HAL_StatusTypeDef Angle_Reset(Angle_Handle_t *hangle, UPP_Phase_t Phase) HAL_StatusTypeDef Angle_Reset(Angle_Handle_t *hangle, UPP_Phase_t Phase)
{ {
if(assert_upp(hangle)) if(assert_upp_phase(hangle, Phase))
return HAL_ERROR; return HAL_ERROR;
// Если канал дурацкий - возвращаем ошибку
if(Phase >= 3)
{
return HAL_ERROR;
}
switch(Phase) switch(Phase)
{ {
case UPP_PHASE_A: case UPP_PHASE_A:

View File

@@ -28,7 +28,12 @@ typedef struct
float Iref; ///< текущее задание тока в о.е. [0..1] float Iref; ///< текущее задание тока в о.е. [0..1]
float Imeas; ///< измеренное значение тока в о.е. [0..1] float Imeas; ///< измеренное значение тока в о.е. [0..1]
float alpha; ///< текущий угол открытия в о.е. [0..1] (% от периода) float alpha; ///< текущий угол открытия в о.е. [0..1] от 180 градусов
float alpha_real; /*!< @brief Фактический отсчитываемый угол открытия в о.е. [0..1] от 180 градусов
@details Этот угол отличается от @ref alpha дополнительными задержками и компенсациями:
- 30 градусов - смещение между линейными и фазными напряжение (мы смотрим линейные, а коммутируем фазные) */
arm_pid_instance_f32 pid; ///< ПИД регулятор для управления углом arm_pid_instance_f32 pid; ///< ПИД регулятор для управления углом
FilterExp_t refFilter; ///< Фильтр для плавного нарастания регулирования FilterExp_t refFilter; ///< Фильтр для плавного нарастания регулирования
@@ -50,7 +55,7 @@ HAL_StatusTypeDef Angle_PID_Init(Angle_Handle_t *hangle, float kp, float ki, flo
/* Управление углом через ПИД регулятор */ /* Управление углом через ПИД регулятор */
void Angle_PID(Angle_Handle_t *hangle, float setpoint, float measurement); void Angle_PID(Angle_Handle_t *hangle, float setpoint, float measurement);
/* Выставление текущего угла открытия тиристоров. */ /* Выставление текущего угла открытия тиристоров. */
HAL_StatusTypeDef Angle_SetAngle(Angle_Handle_t *hangle, float Angle); HAL_StatusTypeDef Angle_SetAlpha(Angle_Handle_t *hangle, float Angle);
/* Установка угла открытия в таймер. */ /* Установка угла открытия в таймер. */
HAL_StatusTypeDef Angle_Start(Angle_Handle_t *hangle, UPP_Phase_t Phase, float PeriodMs); HAL_StatusTypeDef Angle_Start(Angle_Handle_t *hangle, UPP_Phase_t Phase, float PeriodMs);

View File

@@ -59,11 +59,6 @@ HAL_StatusTypeDef PWM_Init(PWM_Handle_t *hpwm)
PWM_SetHalfWave(hpwm, UPP_PHASE_B, UPP_WAVE_UNKNOWED); PWM_SetHalfWave(hpwm, UPP_PHASE_B, UPP_WAVE_UNKNOWED);
PWM_SetHalfWave(hpwm, UPP_PHASE_C, UPP_WAVE_UNKNOWED); PWM_SetHalfWave(hpwm, UPP_PHASE_C, UPP_WAVE_UNKNOWED);
PWM_SetConfig(hpwm, PARAM_INTERNAL.pwm.PhaseMask,
PARAM_INTERNAL.pwm.Frequency,
u2f(PARAM_INTERNAL.pwm.Duty, 100),
PARAM_INTERNAL.pwm.PulseNumber);
HAL_TIM_PWM_Start(&hpwm1, PWM_CHANNEL_1); HAL_TIM_PWM_Start(&hpwm1, PWM_CHANNEL_1);
HAL_TIM_PWM_Start(&hpwm1, PWM_CHANNEL_2); HAL_TIM_PWM_Start(&hpwm1, PWM_CHANNEL_2);
HAL_TIM_PWM_Start(&hpwm1, PWM_CHANNEL_3); HAL_TIM_PWM_Start(&hpwm1, PWM_CHANNEL_3);
@@ -88,16 +83,11 @@ HAL_StatusTypeDef PWM_Init(PWM_Handle_t *hpwm)
*/ */
HAL_StatusTypeDef PWM_Start(PWM_Handle_t *hpwm, UPP_Phase_t Phase) HAL_StatusTypeDef PWM_Start(PWM_Handle_t *hpwm, UPP_Phase_t Phase)
{ {
if(assert_upp(hpwm)) if(assert_upp_phase(hpwm, Phase))
return HAL_ERROR; return HAL_ERROR;
// Если уже какой-то канал запущен - не запускаем // Если уже какой-то канал запущен - не запускаем
if(hpwm->f.Running) if(hpwm->f.Running)
return HAL_BUSY; return HAL_BUSY;
// Если канал дурацкий - возвращаем ошибку
if(Phase >= 3)
{
return HAL_ERROR;
}
if (hpwm->Phase[Phase] == NULL || hpwm->Phase[Phase] == &hpwm->AllPhases[PHASE_UNKNOWN]) if (hpwm->Phase[Phase] == NULL || hpwm->Phase[Phase] == &hpwm->AllPhases[PHASE_UNKNOWN])
return HAL_ERROR; return HAL_ERROR;
@@ -149,7 +139,7 @@ HAL_StatusTypeDef PWM_Start(PWM_Handle_t *hpwm, UPP_Phase_t Phase)
*/ */
HAL_StatusTypeDef PWM_Stop(PWM_Handle_t *hpwm, UPP_Phase_t Phase, uint8_t force_stop_all) HAL_StatusTypeDef PWM_Stop(PWM_Handle_t *hpwm, UPP_Phase_t Phase, uint8_t force_stop_all)
{ {
if(assert_upp(hpwm)) if(assert_upp_phase(hpwm, Phase))
return HAL_ERROR; return HAL_ERROR;
// Если force_stop_all - сбрасываем ВСЕ КАНАЛЫ // Если force_stop_all - сбрасываем ВСЕ КАНАЛЫ
@@ -170,11 +160,6 @@ HAL_StatusTypeDef PWM_Stop(PWM_Handle_t *hpwm, UPP_Phase_t Phase, uint8_t force_
// Если НЕ force_stop_all - сбрасываем ТОЛЬКО заданный канал // Если НЕ force_stop_all - сбрасываем ТОЛЬКО заданный канал
else else
{ {
// Если канал дурацкий - возвращаем ошибку
if(Phase >= 3)
{
return HAL_ERROR;
}
if (hpwm->Phase[Phase] == NULL || hpwm->Phase[Phase] == &hpwm->AllPhases[PHASE_UNKNOWN]) if (hpwm->Phase[Phase] == NULL || hpwm->Phase[Phase] == &hpwm->AllPhases[PHASE_UNKNOWN])
return HAL_ERROR; return HAL_ERROR;
@@ -251,18 +236,12 @@ HAL_StatusTypeDef PWM_SetConfig(PWM_Handle_t *hpwm, uint8_t PhaseMask, uint16_t
*/ */
HAL_StatusTypeDef PWM_SetHalfWave(PWM_Handle_t *hpwm, UPP_Phase_t Phase, UPP_HalfWave_t halfwave) HAL_StatusTypeDef PWM_SetHalfWave(PWM_Handle_t *hpwm, UPP_Phase_t Phase, UPP_HalfWave_t halfwave)
{ {
if(assert_upp(hpwm)) if(assert_upp_phase(hpwm, Phase))
return HAL_ERROR; return HAL_ERROR;
// Сбрасываем текущий канал // Сбрасываем текущий канал
PWM_Stop(hpwm, Phase, 0); PWM_Stop(hpwm, Phase, 0);
// Если канал дурацкий - выставляем заглушку
if(Phase >= 3)
{
hpwm->Phase[Phase] = &hpwm->AllPhases[PHASE_UNKNOWN];
return HAL_ERROR;
}
// Выставляем канал // Выставляем канал
switch(halfwave) switch(halfwave)
{ {

View File

@@ -51,6 +51,10 @@ int UPP_App_Init(void)
return 1; return 1;
} }
if(UPP_Params_Init() != HAL_OK)
{
return 1;
}
return 0; return 0;
} }

View File

@@ -270,6 +270,89 @@ void UPP_Params_ControlInternal(void)
/**
* @brief Инициализация параметров УПП.
* @return HAL Status.
*/
HAL_StatusTypeDef UPP_Params_Init(void)
{
/*====== ИНИЦИАЛИЗАЦИЯ МОДУЛЯ angle_control ======*/
// Инициализация ПИД
if(Angle_PID_Init(&upp.hangle,
u2f(PARAM_INTERNAL.angle.PID_Kp, 10000),
u2f(PARAM_INTERNAL.angle.PID_Ki, 10000),
u2f(PARAM_INTERNAL.angle.PID_Kd, 10000),
PUI_Tnt_CalcAlpha(u2f(PARAM_PUI.Tnt, 1000), PM_SLOW_PERIOD_US)) != HAL_OK)
return HAL_ERROR;
// Инициализация углов
if(Angle_SetRange(&upp.hangle,
u2f(PARAM_INTERNAL.angle.Angle_Min, 65535),
u2f(PARAM_INTERNAL.angle.Angle_Max, 65535)) != HAL_OK)
return HAL_ERROR;
/*===== ИНИЦИАЛИЗАЦИЯ МОДУЛЯ power_monitor ======*/
/* Инициализация каналов АЦП */
if(ADC_ConfigChannel(&upp.pm.adc, ADC_CHANNEL_UBA,
PARAM_INTERNAL.adc.ADC_Zero[ADC_CHANNEL_UBA],
u2f(PARAM_INTERNAL.adc.ADC_Max[ADC_CHANNEL_UBA], 10),
4095) != HAL_OK)
return HAL_ERROR;
if(ADC_ConfigChannel(&upp.pm.adc, ADC_CHANNEL_UAC,
PARAM_INTERNAL.adc.ADC_Zero[ADC_CHANNEL_UAC],
u2f(PARAM_INTERNAL.adc.ADC_Max[ADC_CHANNEL_UAC], 10),
4095) != HAL_OK)
return HAL_ERROR;
if(ADC_ConfigChannel(&upp.pm.adc, ADC_CHANNEL_IC,
PARAM_INTERNAL.adc.ADC_Zero[ADC_CHANNEL_IC],
u2f(PARAM_INTERNAL.adc.ADC_Max[ADC_CHANNEL_IC], 10),
4095) != HAL_OK)
return HAL_ERROR;
if(ADC_ConfigChannel(&upp.pm.adc, ADC_CHANNEL_IA,
PARAM_INTERNAL.adc.ADC_Zero[ADC_CHANNEL_IA],
u2f(PARAM_INTERNAL.adc.ADC_Max[ADC_CHANNEL_IA], 10),
4095) != HAL_OK)
return HAL_ERROR;
/* Инициализация алгоритма перехода через ноль */
if(ZC_Init(&upp.pm.zc, 3, u2f(PARAM_INTERNAL.zc.Hysteresis, 100), PARAM_INTERNAL.zc.DebouneCouner) != HAL_OK)
return HAL_ERROR;
/* Инициализация RMS фильтра медленного алга */
for(int i = 0; i < RMS_ALL; i++)
{
if(FilterRMS_Init(&upp.pm.rms[i], PARAM_INTERNAL.pm.rms_window_size))
return HAL_ERROR;
Filter_Start(&upp.pm.rms[i]);
}
/* Инициализация экпоненциального фильтра медленного алга */
for(int i = 0; i < RMS_EXP_ALL; i++)
{
if(FilterExp_Init(&upp.pm.rms_exp[i], u2f(PARAM_INTERNAL.pm.rms_exp_alpha, 65535)))
return HAL_ERROR;
Filter_Start(&upp.pm.rms_exp[i]);
}
/*====== ИНИЦИАЛИЗАЦИЯ МОДУЛЯ pwm_thyristors ======*/
if(PWM_SetConfig(&upp.hpwm, PARAM_INTERNAL.pwm.PhaseMask,
PARAM_INTERNAL.pwm.Frequency,
u2f(PARAM_INTERNAL.pwm.Duty, 100),
PARAM_INTERNAL.pwm.PulseNumber) != HAL_OK)
return HAL_ERROR;
return HAL_OK;
}
/** /**
* @brief Контроль параметров УПП на корректные значения. * @brief Контроль параметров УПП на корректные значения.
* @return HAL Status. * @return HAL Status.

View File

@@ -101,6 +101,8 @@ void UPP_Params_Control(void);
void UPP_Params_ControlPUI(void); void UPP_Params_ControlPUI(void);
/* Контроль внутренних параметров УПП. */ /* Контроль внутренних параметров УПП. */
void UPP_Params_ControlInternal(void); void UPP_Params_ControlInternal(void);
/* Инициализация параметров УПП. */
HAL_StatusTypeDef UPP_Params_Init(void);
/* Контроль параметров УПП на корректные значения. */ /* Контроль параметров УПП на корректные значения. */
void UPP_Params_Saturate(void); void UPP_Params_Saturate(void);
/* Установка параметров на дефолтные значения */ /* Установка параметров на дефолтные значения */

View File

@@ -0,0 +1,12 @@
open_level = 0:0.01:1; % Степень регулирования выходного напряжения (epsilon) от 0 до 1
OpenLevelForCos = (open_level.*2)-1;
alpha_rad = acos(OpenLevelForCos); % угол в радианах
alpha = alpha_rad/pi; % угол открытия тиристора в о.е. от максимально заданного
plot(alpha, open_level)
grid on;
xlabel('\alpha, о.е. (от \pi)');
ylabel('\epsilon, о.е.');
title('Регулировочная характеристика \epsilon');
legend('ε = cos(α)');