diff --git a/MATLAB/MCU_STM32_Matlab/Drivers/STM32_SIMULINK/stm32_matlab_tim.c b/MATLAB/MCU_STM32_Matlab/Drivers/STM32_SIMULINK/stm32_matlab_tim.c index 4c2c92a..4e4ea46 100644 --- a/MATLAB/MCU_STM32_Matlab/Drivers/STM32_SIMULINK/stm32_matlab_tim.c +++ b/MATLAB/MCU_STM32_Matlab/Drivers/STM32_SIMULINK/stm32_matlab_tim.c @@ -18,24 +18,33 @@ void TIM_Simulation(TIM_TypeDef *TIMx, struct TIM_Sim *TIMS) // Выбор режима работы таймера -switch (TIMx->SMCR & TIM_SMCR_SMS) // TIMER MODE -{ - // обычный счет - case(TIM_SLAVEMODE_DISABLE):// NORMAL MODE counting - TIMx_Count(TIMx, TIMS); - Channels_Simulation(TIMx, TIMS); // CaptureCompare and PWM channels simulation - Write_TRGO(TIMx, TIMS); - break; + switch (TIMx->SMCR & TIM_SMCR_SMS) // TIMER MODE + { + // обычный счет + case(TIM_SLAVEMODE_DISABLE):// NORMAL MODE counting + TIMx_Count(TIMx, TIMS); + Channels_Simulation(TIMx, TIMS); // CaptureCompare and PWM channels simulation + Write_TRGO(TIMx, TIMS); + break; - // включение слейв таймера по ивенту - case(TIM_SLAVEMODE_TRIGGER): // SLAVE MODE: TRIGGER MODE - Slave_Mode_Check_Source(TIMx, TIMS); - TIMx_Count(TIMx, TIMS); - Channels_Simulation(TIMx, TIMS); // CaptureCompare and PWM channels simulation - Write_TRGO(TIMx, TIMS); - break; -} + // включение слейв таймера по ивенту + case(TIM_SLAVEMODE_TRIGGER): // SLAVE MODE: TRIGGER MODE + Slave_Mode_Check_Source(TIMx, TIMS); + TIMx_Count(TIMx, TIMS); + Channels_Simulation(TIMx, TIMS); // CaptureCompare and PWM channels simulation + Write_TRGO(TIMx, TIMS); + break; + } + + // EGR + TIM_EGR_Simulation(TIMx); + + // Прерывание если какое-то выставлено + if (TIMx->SR & (TIM_SR_UIF | TIM_SR_CC1IF | TIM_SR_CC2IF | TIM_SR_CC3IF | TIM_SR_CC4IF)) + { + TIM_Call_IRQHandller(TIMx); // call HANDLER + } } /* Счет таймера за один такт */ @@ -68,7 +77,9 @@ void Overflow_Check(TIM_TypeDef* TIMx, struct TIM_Sim* TIMS) if(TIMS->tx_step > TIMS->RELOAD) TIMS->tx_cnt = 0; - TIM_Call_IRQHandller(TIMx); // call HANDLER + if (TIMx->DIER & TIM_DIER_UIE) { + TIMx->SR |= TIM_SR_UIF; + } } } } @@ -134,12 +145,10 @@ void CC_PWM_Ch1_Simulation(TIM_TypeDef *TIMx, struct TIM_Sim *TIMS) if (((TIMS->tx_cnt - TIMS->tx_step) < TIMx->CCR1) && (TIMS->tx_cnt >= TIMx->CCR1)) { TIMx->SR |= TIM_SR_CC1IF; - TIM_Call_IRQHandller(TIMx); } else if (((TIMS->tx_cnt - TIMS->tx_step) > TIMx->CCR1) && (TIMS->tx_cnt <= TIMx->CCR1)) { TIMx->SR |= TIM_SR_CC1IF; - TIM_Call_IRQHandller(TIMx); } } } @@ -188,12 +197,10 @@ void CC_PWM_Ch2_Simulation(TIM_TypeDef *TIMx, struct TIM_Sim *TIMS) if (((TIMS->tx_cnt - TIMS->tx_step) < TIMx->CCR2) && (TIMS->tx_cnt >= TIMx->CCR2)) { TIMx->SR |= TIM_SR_CC2IF; - TIM_Call_IRQHandller(TIMx); } else if (((TIMS->tx_cnt - TIMS->tx_step) > TIMx->CCR2) && (TIMS->tx_cnt <= TIMx->CCR2)) { TIMx->SR |= TIM_SR_CC2IF; - TIM_Call_IRQHandller(TIMx); } } } @@ -242,12 +249,10 @@ void CC_PWM_Ch3_Simulation(TIM_TypeDef *TIMx, struct TIM_Sim *TIMS) if (((TIMS->tx_cnt - TIMS->tx_step) < TIMx->CCR3) && (TIMS->tx_cnt >= TIMx->CCR3)) { TIMx->SR |= TIM_SR_CC3IF; - TIM_Call_IRQHandller(TIMx); } else if (((TIMS->tx_cnt - TIMS->tx_step) > TIMx->CCR3) && (TIMS->tx_cnt <= TIMx->CCR3)) { TIMx->SR |= TIM_SR_CC3IF; - TIM_Call_IRQHandller(TIMx); } } } @@ -296,12 +301,10 @@ void CC_PWM_Ch4_Simulation(TIM_TypeDef *TIMx, struct TIM_Sim *TIMS) if (((TIMS->tx_cnt - TIMS->tx_step) < TIMx->CCR4) && (TIMS->tx_cnt >= TIMx->CCR4)) { TIMx->SR |= TIM_SR_CC4IF; - TIM_Call_IRQHandller(TIMx); } else if (((TIMS->tx_cnt - TIMS->tx_step) > TIMx->CCR4) && (TIMS->tx_cnt <= TIMx->CCR4)) { TIMx->SR |= TIM_SR_CC4IF; - TIM_Call_IRQHandller(TIMx); } } } @@ -456,6 +459,42 @@ void Write_TRGO(TIM_TypeDef* TIMx, struct TIM_Sim* TIMS) //--------------------MISC (temporary) FUNCTIONS--------------------// +void TIM_EGR_Simulation(TIM_TypeDef* TIMx, struct TIM_Sim* TIMS) +{ + // Update + if (TIMx->EGR & TIM_EGR_UG) { + TIMx->EGR &= ~TIM_EGR_UG; + if (TIMx->DIER & TIM_DIER_UIE) { + TIMx->SR |= TIM_SR_UIF; + } + } + // Channels + if (TIMx->EGR & TIM_EGR_CC1G) { + TIMx->EGR &= ~TIM_EGR_CC1G; + if (TIMx->DIER & TIM_IT_CC1) { + TIMx->SR |= TIM_SR_CC1IF; + } + } + if (TIMx->EGR & TIM_EGR_CC2G) { + TIMx->EGR &= ~TIM_EGR_CC2G; + if (TIMx->DIER & TIM_IT_CC2) { + TIMx->SR |= TIM_SR_CC2IF; + } + } + if (TIMx->EGR & TIM_EGR_CC3G) { + TIMx->EGR &= ~TIM_EGR_CC3G; + if (TIMx->DIER & TIM_IT_CC3) { + TIMx->SR |= TIM_SR_CC3IF; + } + } + if (TIMx->EGR & TIM_EGR_CC4G) { + TIMx->EGR &= ~TIM_EGR_CC4G; + if (TIMx->DIER & TIM_IT_CC4) { + TIMx->SR |= TIM_SR_CC4IF; + } + } +} + /* Определение источника для запуска таймера в SLAVE MODE */ void Slave_Mode_Check_Source(TIM_TypeDef* TIMx, struct TIM_Sim* TIMS) { diff --git a/MATLAB/MCU_STM32_Matlab/Drivers/STM32_SIMULINK/stm32_matlab_tim.h b/MATLAB/MCU_STM32_Matlab/Drivers/STM32_SIMULINK/stm32_matlab_tim.h index bca554e..9314aec 100644 --- a/MATLAB/MCU_STM32_Matlab/Drivers/STM32_SIMULINK/stm32_matlab_tim.h +++ b/MATLAB/MCU_STM32_Matlab/Drivers/STM32_SIMULINK/stm32_matlab_tim.h @@ -108,6 +108,8 @@ void Write_TRGO(TIM_TypeDef* TIMx, struct TIM_Sim* TIMS); //--------------------MISC (temporary) FUNCTIONS--------------------// + +void TIM_Call_IRQHandller(TIM_TypeDef* TIMx); /* Определение источника для запуска таймера в SLAVE MODE */ void Slave_Mode_Check_Source(TIM_TypeDef* TIMx, struct TIM_Sim* TIMS); //------------------------------------------------------------------// diff --git a/MATLAB/upp_r2023.slx b/MATLAB/upp_r2023.slx index aa05084..0af3141 100644 Binary files a/MATLAB/upp_r2023.slx and b/MATLAB/upp_r2023.slx differ diff --git a/UPP/Core/Configs/modbus_data.h b/UPP/Core/Configs/modbus_data.h index 985af13..34d385c 100644 --- a/UPP/Core/Configs/modbus_data.h +++ b/UPP/Core/Configs/modbus_data.h @@ -52,7 +52,7 @@ #define _MODBUS_DATA_H_ #include "upp_defs.h" -#include "upp_control.h" +#include "upp_params.h" #include "stdint.h" diff --git a/UPP/Core/Configs/upp_config.h b/UPP/Core/Configs/upp_config.h index 97f0a05..af6a373 100644 --- a/UPP/Core/Configs/upp_config.h +++ b/UPP/Core/Configs/upp_config.h @@ -97,6 +97,12 @@ * @brief Параметры устанавливаемые на этапе компиляции. Без перепрошивки их не поменять * @{ */ + +//#if defined(STM32F417xx) + +//#endif + + /* Периоды вызова всякого */ #define PM_ADC_PERIOD_US 10 ///< Период опроса АЦП в мкс #define PM_SLOW_PERIOD_CNT 50 ///< Период обновления медленных расчетов тиках @ref PM_ADC_PERIOD_US @@ -109,4 +115,7 @@ #define PWM_TIM3_FREQ_MHZ 90 ///< Частота тиков таймера ШИМ (5-6 каналы) #define ANGLE_TIM2_FREQ_MHZ 90 ///< Частота тиков таймера отсчета угла открытия тиристоров +/** //UPP_COMPILED_PARAMS + * @} + */ #endif //_UPP_CONFIG_H_ diff --git a/UPP/Core/Configs/upp_defs.h b/UPP/Core/Configs/upp_defs.h index cd82f8c..dad89f5 100644 --- a/UPP/Core/Configs/upp_defs.h +++ b/UPP/Core/Configs/upp_defs.h @@ -151,6 +151,9 @@ typedef struct { #define PM_SLOW_PERIOD_US (PM_ADC_PERIOD_US*PM_SLOW_PERIOD_CNT) #define ANGLE_PERIOD_MS(_freq_) (((float)1/(_freq_*2))*1000) +#define PARAM_INTERNAL MB_INTERNAL.param +#define PARAM_PUI MB_DATA.HoldRegs.pui_params + /** * @brief Состояния полуволны */ diff --git a/UPP/Core/PowerMonitor/power_monitor.c b/UPP/Core/PowerMonitor/power_monitor.c index 5f11c17..489d7a5 100644 --- a/UPP/Core/PowerMonitor/power_monitor.c +++ b/UPP/Core/PowerMonitor/power_monitor.c @@ -32,32 +32,32 @@ HAL_StatusTypeDef PowerMonitor_Init(PowerMonitor_t *hpm) /* Инициализация каналов АЦП */ if(ADC_ConfigChannel(&hpm->adc, ADC_CHANNEL_UBA, - MB_INTERNAL.param.adc.ADC_Zero[ADC_CHANNEL_UBA], - to_float(MB_INTERNAL.param.adc.ADC_Max[ADC_CHANNEL_UBA], 10), + PARAM_INTERNAL.adc.ADC_Zero[ADC_CHANNEL_UBA], + to_float(PARAM_INTERNAL.adc.ADC_Max[ADC_CHANNEL_UBA], 10), 4095) != HAL_OK) return HAL_ERROR; if(ADC_ConfigChannel(&hpm->adc, ADC_CHANNEL_UAC, - MB_INTERNAL.param.adc.ADC_Zero[ADC_CHANNEL_UAC], - to_float(MB_INTERNAL.param.adc.ADC_Max[ADC_CHANNEL_UAC], 10), + PARAM_INTERNAL.adc.ADC_Zero[ADC_CHANNEL_UAC], + to_float(PARAM_INTERNAL.adc.ADC_Max[ADC_CHANNEL_UAC], 10), 4095) != HAL_OK) return HAL_ERROR; if(ADC_ConfigChannel(&hpm->adc, ADC_CHANNEL_IC, - MB_INTERNAL.param.adc.ADC_Zero[ADC_CHANNEL_IC], - to_float(MB_INTERNAL.param.adc.ADC_Max[ADC_CHANNEL_IC], 10), + PARAM_INTERNAL.adc.ADC_Zero[ADC_CHANNEL_IC], + to_float(PARAM_INTERNAL.adc.ADC_Max[ADC_CHANNEL_IC], 10), 4095) != HAL_OK) return HAL_ERROR; if(ADC_ConfigChannel(&hpm->adc, ADC_CHANNEL_IA, - MB_INTERNAL.param.adc.ADC_Zero[ADC_CHANNEL_IA], - to_float(MB_INTERNAL.param.adc.ADC_Max[ADC_CHANNEL_IA], 10), + PARAM_INTERNAL.adc.ADC_Zero[ADC_CHANNEL_IA], + to_float(PARAM_INTERNAL.adc.ADC_Max[ADC_CHANNEL_IA], 10), 4095) != HAL_OK) return HAL_ERROR; /* Инициализация алгоритма перехода через ноль */ - if(ZC_Init(&hpm->zc, 3, to_float(MB_INTERNAL.param.zc.Hysteresis, 100), MB_INTERNAL.param.zc.DebouneCouner) != HAL_OK) + if(ZC_Init(&hpm->zc, 3, to_float(PARAM_INTERNAL.zc.Hysteresis, 100), PARAM_INTERNAL.zc.DebouneCouner) != HAL_OK) return HAL_ERROR; /* Инициализация каналов алгоритма перехода через ноль */ @@ -72,7 +72,7 @@ HAL_StatusTypeDef PowerMonitor_Init(PowerMonitor_t *hpm) /* Инициализация экпоненциального фильтра медленного алга */ for(int i = 0; i < EXP_ALL; i++) { - if(FilterExp_Init(&hpm->exp[i], to_float(MB_INTERNAL.param.pm.mean_alpha,65535))) + if(FilterExp_Init(&hpm->exp[i], to_float(PARAM_INTERNAL.pm.mean_alpha,65535))) return HAL_ERROR; Filter_Start(&hpm->exp[i]); } @@ -195,8 +195,8 @@ void PowerMonitor_FastCalc(PowerMonitor_t *hpm) /* Преобразуем в относительные единицы (о.е.) */ for(int i = 0; i < 3; i++) { - meas->fast.U[i] = 10*meas->real.U[i]/MB_INTERNAL.param.nominal.U; - meas->fast.I[i] = 10*meas->real.I[i]/MB_INTERNAL.param.nominal.I; + meas->fast.U[i] = 10*meas->real.U[i]/PARAM_INTERNAL.nominal.U; + meas->fast.I[i] = 10*meas->real.I[i]/PARAM_INTERNAL.nominal.I; } /* Ищем переход через ноль */ @@ -250,8 +250,8 @@ int PowerMonitor_Protect(PowerMonitor_t *hpm, uint8_t Running) return 1; PowerMonitor_Measured_t *measure = &hpm->measured; - UPP_PUI_Params_t *protect = &MB_DATA.HoldRegs.pui_params; - UPP_ParamsNominal_t *nominal = &MB_INTERNAL.param.nominal; + UPP_PUI_Params_t *protect = &PARAM_PUI; + UPP_ParamsNominal_t *nominal = &PARAM_INTERNAL.nominal; /*=============== ЗАЩИТЫ ПО НАПРЯЖЕНИЮ ==================*/ hpm->f.isU = Protect_Voltages(measure, protect, nominal); diff --git a/UPP/Core/PowerMonitor/power_monitor.h b/UPP/Core/PowerMonitor/power_monitor.h index 2b9ef4a..c0e97a9 100644 --- a/UPP/Core/PowerMonitor/power_monitor.h +++ b/UPP/Core/PowerMonitor/power_monitor.h @@ -92,11 +92,13 @@ typedef struct }PowerMonitor_t; extern PowerMonitor_t pm; +// ====== ИНИЦИАЛИЗАЦИЯ ========== /* Инициализация мониторинга сети */ HAL_StatusTypeDef PowerMonitor_Init(PowerMonitor_t *hpm); /* Запустить мониторинг сети */ HAL_StatusTypeDef PowerMonitor_Start(PowerMonitor_t *hpm); +// ====== РАСЧЕТЫ ========== /* Медленные расчеты АЦП */ void PowerMonitor_SlowCalc(PowerMonitor_t *hpm); /* Считывание АЦП и быстрые расчеты */ diff --git a/UPP/Core/PowerMonitor/power_protect.c b/UPP/Core/PowerMonitor/power_protect.c index b67dae8..2bf7206 100644 --- a/UPP/Core/PowerMonitor/power_protect.c +++ b/UPP/Core/PowerMonitor/power_protect.c @@ -133,12 +133,12 @@ int Protect_Currents(PowerMonitor_Measured_t *measure, UPP_PUI_Params_t *protect void Protect_Misc(PowerMonitor_Measured_t *measure, UPP_PUI_Params_t *protect, UPP_ParamsNominal_t *nominal) { /* Переводим внутренние уставки в удобный вид */ - float lFnom = to_float(MB_INTERNAL.param.nominal.F, 100); - float lFmin = lFnom - lFnom*to_float(MB_INTERNAL.param.nominal.F_deviation_minus, 100); - float lFmax = lFnom + lFnom*to_float(MB_INTERNAL.param.nominal.F_deviation_plus, 100); + float lFnom = to_float(PARAM_INTERNAL.nominal.F, 100); + float lFmin = lFnom - lFnom*to_float(PARAM_INTERNAL.nominal.F_deviation_minus, 100); + float lFmax = lFnom + lFnom*to_float(PARAM_INTERNAL.nominal.F_deviation_plus, 100); - float lTwarn = to_float(MB_INTERNAL.param.setpoints.TemperatureWarn, 100); - float lTerr = to_float(MB_INTERNAL.param.setpoints.TemperatureWarn, 100); + float lTwarn = to_float(PARAM_INTERNAL.setpoints.TemperatureWarn, 100); + float lTerr = to_float(PARAM_INTERNAL.setpoints.TemperatureWarn, 100); /*=============== ЗАЩИТЫ ПО ЧАСТОТЕ ==================*/ diff --git a/UPP/Core/PowerMonitor/zero_cross.h b/UPP/Core/PowerMonitor/zero_cross.h index cb75130..ae0ab6f 100644 --- a/UPP/Core/PowerMonitor/zero_cross.h +++ b/UPP/Core/PowerMonitor/zero_cross.h @@ -124,32 +124,36 @@ typedef struct { uint32_t LastTick; ///< Послднее время вызова } ZeroCross_Handle_t; +// ====== ИНИЦИАЛИЗАЦИЯ ========== /* Инициализация детектора нуля с индивидуальными настройками */ HAL_StatusTypeDef ZC_Init(ZeroCross_Handle_t *zc, uint8_t num_channels, float hysteresis, uint16_t debounce_samples); - /* Настройка канала детектора */ HAL_StatusTypeDef ZC_ConfigChannel(ZeroCross_Handle_t *zc, uint8_t channel, ZC_EdgeType_t edgeType); +// ====== УПРАВЛЕНИЕ ========== +/* Включение/выключение мониторинга */ +void ZC_EnableMonitoring(ZeroCross_Handle_t *zc, uint8_t enable); +/* Сброс статистики канала */ +void ZC_Reset(ZeroCross_Handle_t *zc, uint8_t channel); + + +// ====== РАСЧЕТЫ ========== /* Обработка значения отдельного канала */ void ZC_ProcessChannel(ZeroCross_Handle_t *zc, uint8_t channel, float value, uint32_t timestamp); - /* Пакетная обработка всех каналов */ void ZC_ProcessAllChannels(ZeroCross_Handle_t *zc, float *values, uint32_t timestamp); +// ====== API ========== /* Полученить флаг - переход произошел. */ int ZC_isOccurred(ZeroCross_Handle_t *zc, uint8_t channel); /* Получение частоты сигнала */ float ZC_GetFrequency(ZeroCross_Handle_t *zc, uint8_t channel); /* Получение полуволны (после последнего zero-cross) */ UPP_HalfWave_t ZC_GetHalfWave(ZeroCross_Handle_t *zc, uint8_t channel); -/* Включение/выключение мониторинга */ -void ZC_EnableMonitoring(ZeroCross_Handle_t *zc, uint8_t enable); -/* Сброс статистики канала */ -void ZC_Reset(ZeroCross_Handle_t *zc, uint8_t channel); #endif /* _ZERO_CROSS_H_ */ diff --git a/UPP/Core/UPP/angle_control.c b/UPP/Core/UPP/angle_control.c index 1fd8a2e..ef16bb1 100644 --- a/UPP/Core/UPP/angle_control.c +++ b/UPP/Core/UPP/angle_control.c @@ -22,9 +22,9 @@ HAL_StatusTypeDef Angle_Init(Angle_Handle_t *hangle) hangle->htim = &angletim; // Инициализация ПИД - float kp = to_float(MB_INTERNAL.param.angle.PID_Kp, 10000); - float ki = to_float(MB_INTERNAL.param.angle.PID_Ki, 10000); - float kd = to_float(MB_INTERNAL.param.angle.PID_Kd, 10000); + float kp = to_float(PARAM_INTERNAL.angle.PID_Kp, 10000); + float ki = to_float(PARAM_INTERNAL.angle.PID_Ki, 10000); + float kd = to_float(PARAM_INTERNAL.angle.PID_Kd, 10000); Angle_PID_Init(hangle, kp, ki, kd); // Инициализация каналов @@ -39,8 +39,8 @@ HAL_StatusTypeDef Angle_Init(Angle_Handle_t *hangle) // Инициализация углов - float angle_max = to_float(MB_INTERNAL.param.angle.Angle_Max, 65535); - float angle_min = to_float(MB_INTERNAL.param.angle.Angle_Min, 65535); + float angle_max = to_float(PARAM_INTERNAL.angle.Angle_Max, 65535); + float angle_min = to_float(PARAM_INTERNAL.angle.Angle_Min, 65535); hangle->f.Initialized = 1; @@ -48,50 +48,6 @@ HAL_StatusTypeDef Angle_Init(Angle_Handle_t *hangle) } -/** - * @brief Управление углом через ПИД регулятор. - * @param hangle Указатель на таймер - * @param setpoint Уставка куда регулировать - * @param measurement Измеренные регулируемые величины - */ -void Angle_PID(Angle_Handle_t *hangle, float setpoint, float measurement) -{ - if(assert_upp(hangle)) - return; - - - /* Ошибка регулирования = уставка - измеренное */ - float err = setpoint - measurement; - - /* ПИД регулирование */ - float reverse_angle = arm_pid_f32(&hangle->pid, err); // 0 - открыть максимально поздно, 1 - открыть макситмально рано - - /* Ограничиваем диапазон и сохраняем в alpha */ - float angle = hangle->Config.AngleMax - reverse_angle; - if (angle > hangle->Config.AngleMax) angle = hangle->Config.AngleMax; - if(angle < hangle->Config.AngleMin) angle = hangle->Config.AngleMin; - - Angle_SetAngle(hangle, angle); -} - -/** - * @brief Сброс ПИД регулятора. - * @param hangle Указатель на таймер - */ -void Angle_PID_Reset(Angle_Handle_t *hangle) -{ - if(assert_upp(hangle)) - return; - - /* Вычисляем выход PID */ - arm_pid_reset_f32(&hangle->pid); - - Angle_SetAngle(hangle, hangle->Config.AngleLimit); - Angle_Reset(hangle, UPP_PHASE_A); - Angle_Reset(hangle, UPP_PHASE_B); - Angle_Reset(hangle, UPP_PHASE_C); -} - /** * @brief Инициализация ПИД регулятора. * @param hangle Указатель на таймер @@ -109,118 +65,89 @@ void Angle_PID_Init(Angle_Handle_t *hangle, float kp, float ki, float kd) } /** - * @brief Инициализация углов открытия. + * @brief Управление углом через ПИД регулятор. * @param hangle Указатель на таймер - * @param AngleLimit Лимит AngleMax, рассчитывается от параметров ШИМ - * @param AngleMin Минимально возможный угол открытия - * @param AngleMax Максимально возможный угол открытия - * @return HAL Status. + * @param setpoint Уставка куда регулировать + * @param measurement Измеренные регулируемые величины */ -HAL_StatusTypeDef Angle_SetRange(Angle_Handle_t *hangle, float AngleMin, float AngleMax) +void Angle_PID(Angle_Handle_t *hangle, float setpoint, float measurement) { if(assert_upp(hangle)) - return HAL_ERROR; - if(hangle->f.Running) - return HAL_BUSY; - if(AngleMax < 0 || AngleMax > 1) - return HAL_ERROR; - if(AngleMin < 0 || AngleMin > 1) - return HAL_ERROR; + return; + + /* Ошибка регулирования = уставка - измеренное */ + float err = setpoint - measurement; - if(AngleMax > hangle->Config.AngleLimit) - AngleMax = hangle->Config.AngleLimit; - if(AngleMin > hangle->Config.AngleLimit) - AngleMin = hangle->Config.AngleLimit; - - if(AngleMin >= AngleMax) - return HAL_ERROR; - - hangle->Config.AngleMax = AngleMax; - hangle->Config.AngleMin = AngleMin; - - return HAL_OK; + /* ПИД регулирование */ + float open_control = arm_pid_f32(&hangle->pid, err); // 0 - открыть максимально поздно, 1 - открыть макситмально рано + + /* Ограничиваем диапазон */ + if (open_control > 1) open_control = 1; + if(open_control < 0) open_control = 0; + + /* Выставляем заданный уровень открытия */ + Angle_SetAngle(hangle, open_control); } - /** - * @brief Выставление текущего угла открытия тиристоров. + * @brief Сброс ПИД регулятора. * @param hangle Указатель на таймер - * @param AngleLimit Лимит AngleMax, рассчитывается от параметров ШИМ - * @param AngleMin Минимально возможный угол открытия - * @param AngleMax Максимально возможный угол открытия - * @return HAL Status. */ -HAL_StatusTypeDef Angle_SetAngle(Angle_Handle_t *hangle, float Angle) +void Angle_PID_Reset(Angle_Handle_t *hangle) { if(assert_upp(hangle)) - return HAL_ERROR; + return; - if(Angle > hangle->Config.AngleLimit) - Angle = hangle->Config.AngleLimit; - - hangle->alpha = Angle; - - return HAL_OK; + /* Вычисляем выход PID */ + arm_pid_reset_f32(&hangle->pid); + + Angle_SetAngle(hangle, 0); + Angle_Reset(hangle, UPP_PHASE_A); + Angle_Reset(hangle, UPP_PHASE_B); + Angle_Reset(hangle, UPP_PHASE_C); } + /** - * @brief Инициализация предельного угла открытия. + * @brief Выставление степени открытия тиристоров. * @param hangle Указатель на таймер - * @param AngleLimit Лимит AngleMax, рассчитывается от параметров ШИМ - * @param AngleMin Минимально возможный угол открытия - * @param AngleMax Максимально возможный угол открытия + * @param OpenLevel Насколько открыть тиристор: + - 0 - полностбю закрыт, + - 1 - полностью открыт * @return HAL Status. */ -HAL_StatusTypeDef Angle_SetLimit(Angle_Handle_t *hangle, float AngleLimit) +HAL_StatusTypeDef Angle_SetAngle(Angle_Handle_t *hangle, float OpenLevel) { if(assert_upp(hangle)) return HAL_ERROR; - if(hangle->f.Running) - return HAL_BUSY; + + /* Приводим уровень открытия к косинусу [-1:1]*/ + float OpenLevelForCos = (OpenLevel*2)-1; + + float alpha_rad = acosf(OpenLevelForCos); // угол в радианах + float alpha = alpha_rad/PI; // время открытие в процентах от периода - когда открыть + + if(alpha > hangle->Config.AngleMax) + alpha = hangle->Config.AngleMax; + if(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 = alpha; - if(AngleLimit < 0 || AngleLimit > 1) - return HAL_ERROR; - hangle->Config.AngleLimit = AngleLimit; return HAL_OK; } -/** - * @brief Хендл таймера для рассчета угла открытия. - * @param hangle Указатель на таймер - * @return HAL Status. - */ -UPP_Phase_t Angle_Handle(Angle_Handle_t *hangle) -{ - if(assert_upp(hangle)) - return UPP_PHASE_UNKNOWN; - - - switch(hangle->htim->Channel) - { - case HAL_TIM_ACTIVE_CHANNEL_1: - return UPP_PHASE_A; - break; - - case HAL_TIM_ACTIVE_CHANNEL_2: - return UPP_PHASE_B; - break; - - case HAL_TIM_ACTIVE_CHANNEL_3: - return UPP_PHASE_C; - break; - - default: - return UPP_PHASE_UNKNOWN; - break; - } - - - return UPP_PHASE_UNKNOWN; -} /** - * @brief Установка угла открытия в таймер. + * @brief Запуск отсчета угла открытия. * @param hangle Указатель на таймер * @param Phase Для какой фазы надо установить угол открытия * @return HAL Status. @@ -235,6 +162,7 @@ HAL_StatusTypeDef Angle_Start(Angle_Handle_t *hangle, UPP_Phase_t Phase, float P { return HAL_ERROR; } + // Дополнительно проверяем на соответствие альфа диапазону if(hangle->alpha > hangle->Config.AngleMax) { hangle->alpha = hangle->Config.AngleMax; @@ -244,25 +172,47 @@ HAL_StatusTypeDef Angle_Start(Angle_Handle_t *hangle, UPP_Phase_t Phase, float P hangle->alpha = hangle->Config.AngleMin; } + // сколько тиков надо выждать для угла uint32_t timer_ticks = TIM_MillisToTick(PeriodMs*hangle->alpha, ANGLE_TIM2_FREQ_MHZ); + // сколько тиков будет в таймере когда угол отсчитается (пойдет в CCRx регистр) uint32_t ccr_ticks = __HAL_TIM_GET_COUNTER(hangle->htim) + timer_ticks; + // Выставялем switch(Phase) { case UPP_PHASE_A: __HAL_TIM_SET_COMPARE(hangle->htim, ANGLE_CHANNEL_1, ccr_ticks); + // Если слишком маленький timer_tick и счетчик уже перевалил за ccr, но не сгенерил прервыание: + if (__HAL_TIM_GET_COMPARE(hangle->htim, ANGLE_CHANNEL_1) <= __HAL_TIM_GET_COUNTER(hangle->htim)) + { + // включаем прерывание вручную + HAL_TIM_GenerateEvent(hangle->htim, TIM_EVENTSOURCE_CC1); + } + __HAL_TIM_ENABLE_IT(hangle->htim, TIM_IT_CC1); hangle->f.Running++; break; case UPP_PHASE_B: __HAL_TIM_SET_COMPARE(hangle->htim, ANGLE_CHANNEL_2, ccr_ticks); + // Если слишком маленький timer_tick и счетчик уже перевалил за ccr, но не сгенерил прервыание: + if (__HAL_TIM_GET_COMPARE(hangle->htim, ANGLE_CHANNEL_2) <= __HAL_TIM_GET_COUNTER(hangle->htim)) + { + // включаем прерывание вручную + HAL_TIM_GenerateEvent(hangle->htim, TIM_EVENTSOURCE_CC2); + } __HAL_TIM_ENABLE_IT(hangle->htim, TIM_IT_CC2); hangle->f.Running++; break; case UPP_PHASE_C: __HAL_TIM_SET_COMPARE(hangle->htim, ANGLE_CHANNEL_3, ccr_ticks); + // Если слишком маленький timer_tick и счетчик уже перевалил за ccr, но не сгенерил прервыание: + if (__HAL_TIM_GET_COMPARE(hangle->htim, ANGLE_CHANNEL_3) <= __HAL_TIM_GET_COUNTER(hangle->htim)) + { + // включаем прерывание вручную + HAL_TIM_GenerateEvent(hangle->htim, TIM_EVENTSOURCE_CC3); + } __HAL_TIM_ENABLE_IT(hangle->htim, TIM_IT_CC3); hangle->f.Running++; break; @@ -319,4 +269,99 @@ HAL_StatusTypeDef Angle_Reset(Angle_Handle_t *hangle, UPP_Phase_t Phase) break; } return HAL_OK; -} \ No newline at end of file +} + + + + +/** + * @brief Инициализация предельного угла открытия. + * @param hangle Указатель на таймер + * @param PeriodLimit Лимит AngleMax, рассчитывается от параметров ШИМ + * @param AngleMin Минимально возможный угол открытия + * @param AngleMax Максимально возможный угол открытия + * @return HAL Status. + */ +HAL_StatusTypeDef Angle_SetLimit(Angle_Handle_t *hangle, float PeriodLimit) +{ + if(assert_upp(hangle)) + return HAL_ERROR; + if(hangle->f.Running) + return HAL_BUSY; + + if(PeriodLimit < 0 || PeriodLimit > 1) + return HAL_ERROR; + + hangle->Config.PeriodLimit = PeriodLimit; + + return HAL_OK; +} + + +/** + * @brief Инициализация углов открытия. + * @param hangle Указатель на таймер + * @param PeriodLimit Лимит AngleMax, рассчитывается от параметров ШИМ + * @param AngleMin Минимально возможный угол открытия + * @param AngleMax Максимально возможный угол открытия + * @return HAL Status. + */ +HAL_StatusTypeDef Angle_SetRange(Angle_Handle_t *hangle, float AngleMin, float AngleMax) +{ + if(assert_upp(hangle)) + return HAL_ERROR; + if(hangle->f.Running) + return HAL_BUSY; + if(AngleMax < 0 || AngleMax > 1) + return HAL_ERROR; + if(AngleMin < 0 || AngleMin > 1) + return HAL_ERROR; + + if(AngleMax > hangle->Config.PeriodLimit) + AngleMax = hangle->Config.PeriodLimit; + if(AngleMin > hangle->Config.PeriodLimit) + AngleMin = hangle->Config.PeriodLimit; + + if(AngleMin >= AngleMax) + return HAL_ERROR; + + hangle->Config.AngleMax = AngleMax; + hangle->Config.AngleMin = AngleMin; + + return HAL_OK; +} + + + +/** + * @brief Хендл таймера для рассчета угла открытия. + * @param hangle Указатель на таймер + * @return HAL Status. + * @details Просто возвращает фазу, у которой закончился отсчет угла + */ +UPP_Phase_t Angle_Handle(Angle_Handle_t *hangle) +{ + if(assert_upp(hangle)) + return UPP_PHASE_UNKNOWN; + + + switch(hangle->htim->Channel) + { + case HAL_TIM_ACTIVE_CHANNEL_1: + return UPP_PHASE_A; + break; + + case HAL_TIM_ACTIVE_CHANNEL_2: + return UPP_PHASE_B; + break; + + case HAL_TIM_ACTIVE_CHANNEL_3: + return UPP_PHASE_C; + break; + + default: + return UPP_PHASE_UNKNOWN; + break; + } + return UPP_PHASE_UNKNOWN; +} diff --git a/UPP/Core/UPP/angle_control.h b/UPP/Core/UPP/angle_control.h index 527394a..89e3902 100644 --- a/UPP/Core/UPP/angle_control.h +++ b/UPP/Core/UPP/angle_control.h @@ -13,9 +13,9 @@ */ typedef struct { - float AngleLimit; ///< Лимит AngleMax, рассчитывается от параметров ШИМ - float AngleMin; ///< Минимально возможный угол открытия - float AngleMax; ///< Максимально возможный угол открытия + float PeriodLimit; ///< Лимит периода, выше которого нельзя выставить рассчитывается от параметров ШИМ + float AngleMin; ///< Минимально возможный угол открытия + float AngleMax; ///< Максимально возможный угол открытия }Angle_Config_t; /** @@ -23,10 +23,12 @@ typedef struct */ typedef struct { - TIM_HandleTypeDef *htim; ///< Указатель на таймер для расчета угла - Angle_Config_t Config; ///< Конфигурации алгоритма расчета угла открытия тиристоров + TIM_HandleTypeDef *htim; ///< Указатель на таймер для расчета угла + Angle_Config_t Config; ///< Конфигурации алгоритма расчета угла открытия тиристоров + + //float alpha_degree; ///< текущий угол открытия в градусах [0..180] + float alpha; ///< текущий угол открытия в процентах от периода [0..1] - float alpha; ///< текущий угол открытия arm_pid_instance_f32 pid; ///< ПИД регулятор для управления углом struct { @@ -35,25 +37,32 @@ typedef struct } f; ///< Флаги }Angle_Handle_t; + +// ====== ИНИЦИАЛИЗАЦИЯ ========== /* Инициализация Таймера для рассчета угла открытия. */ HAL_StatusTypeDef Angle_Init(Angle_Handle_t *hangle); -/* Управление углом через ПИД регулятор */ -void Angle_PID(Angle_Handle_t *hangle, float setpoint, float measurement); -/* Сброс ПИД регулятора. */ -void Angle_PID_Reset(Angle_Handle_t *hangle); /* Инициализация ПИД регулятора. */ void Angle_PID_Init(Angle_Handle_t *hangle, float kp, float ki, float kd); + +// ====== УПРАВЛЕНИЕ ========== +/* Управление углом через ПИД регулятор */ +void Angle_PID(Angle_Handle_t *hangle, float setpoint, float measurement); /* Выставление текущего угла открытия тиристоров. */ HAL_StatusTypeDef Angle_SetAngle(Angle_Handle_t *hangle, float Angle); -/* Инициализация углов открытия. */ -HAL_StatusTypeDef Angle_SetRange(Angle_Handle_t *hangle, float AngleMin, float AngleMax); -/* Инициализация предельного угла открытия. */ -HAL_StatusTypeDef Angle_SetLimit(Angle_Handle_t *hangle, float AngleLimit); /* Установка угла открытия в таймер. */ HAL_StatusTypeDef Angle_Start(Angle_Handle_t *hangle, UPP_Phase_t Phase, float PeriodMs); + +// ====== СБРОС ========== /* Сброс угла открытия у таймера. */ HAL_StatusTypeDef Angle_Reset(Angle_Handle_t *hangle, UPP_Phase_t Phase); +/* Сброс ПИД регулятора. */ +void Angle_PID_Reset(Angle_Handle_t *hangle); +// ====== СЕРВИС ========== +/* Инициализация предельного угла открытия. */ +HAL_StatusTypeDef Angle_SetLimit(Angle_Handle_t *hangle, float PeriodLimit); +/* Инициализация углов открытия. */ +HAL_StatusTypeDef Angle_SetRange(Angle_Handle_t *hangle, float AngleMin, float AngleMax); /* Хендл таймера для рассчета угла открытия. */ UPP_Phase_t Angle_Handle(Angle_Handle_t *hangle); #endif /* _ANGLE_CONTROL_H_ */ diff --git a/UPP/Core/UPP/pwm_thyristors.c b/UPP/Core/UPP/pwm_thyristors.c index b978b5e..383645b 100644 --- a/UPP/Core/UPP/pwm_thyristors.c +++ b/UPP/Core/UPP/pwm_thyristors.c @@ -58,7 +58,7 @@ HAL_StatusTypeDef PWM_Init(PWM_Handle_t *hpwm) PWM_SetHalfWave(hpwm, UPP_PHASE_B, UPP_WAVE_UNKNOWED); PWM_SetHalfWave(hpwm, UPP_PHASE_C, UPP_WAVE_UNKNOWED); - PWM_SetConfig(hpwm, MB_INTERNAL.param.pwm.PhaseMask, MB_INTERNAL.param.pwm.Frequency, MB_INTERNAL.param.pwm.PulseNumber); + PWM_SetConfig(hpwm, PARAM_INTERNAL.pwm.PhaseMask, PARAM_INTERNAL.pwm.Frequency, PARAM_INTERNAL.pwm.PulseNumber); HAL_TIM_PWM_Start(&hpwm1, PWM_CHANNEL_1); HAL_TIM_PWM_Start(&hpwm1, PWM_CHANNEL_2); @@ -77,7 +77,7 @@ HAL_StatusTypeDef PWM_Init(PWM_Handle_t *hpwm) * @param hpwm Указатель на хендл ШИМ тиристоров * @param Phase На какой фазе надо запустить ШИМ * @return HAL Status. - * @details Переводит автомат канала ШИМ в состояние запуска ШИМ. + * @details Переводит автомат состояний канала ШИМ в состояние запуска ШИМ. */ HAL_StatusTypeDef PWM_Start(PWM_Handle_t *hpwm, UPP_Phase_t Phase) { @@ -184,14 +184,14 @@ HAL_StatusTypeDef PWM_Handle(PWM_Handle_t *hpwm) case PWM_THYR_TIM_START: // начать ШИМ (пачка импульсов) __PWM_SetOutputState(hPhase, PWM_ENABLE); - hPhase->PulseCnt = hpwm->Config.PulseNumber; + hPhase->PulseCnt = hpwm->Config.PulseNumber - 1; // 1 импульс уже прошел hPhase->State = PWM_THYR_TIM_ACTIVE; hpwm->f.Running++; break; case PWM_THYR_TIM_ACTIVE: // управление пачкой импульсов ШИМ hPhase->PulseCnt--; - if (hPhase->PulseCnt <= 0) + if (hPhase->PulseCnt <= 1) // если остался один импльс в след раз идем в PWM_THYR_TIM_DONE { hPhase->PulseCnt = 0; hPhase->State = PWM_THYR_TIM_DONE; diff --git a/UPP/Core/UPP/pwm_thyristors.h b/UPP/Core/UPP/pwm_thyristors.h index 8780a92..5e01dae 100644 --- a/UPP/Core/UPP/pwm_thyristors.h +++ b/UPP/Core/UPP/pwm_thyristors.h @@ -85,9 +85,12 @@ typedef struct { } f; } PWM_Handle_t; -/* ---- API ---- */ + +// ====== ИНИЦИАЛИЗАЦИЯ ========== /* Инициализация ШИМ тиристоров. */ HAL_StatusTypeDef PWM_Init(PWM_Handle_t *hpwm); + +// ====== УПРАВЛЕНИЕ ========== /* Запуск ШИМ. */ HAL_StatusTypeDef PWM_Start(PWM_Handle_t *hpwm, UPP_Phase_t Phase); /* Остановить ШИМ. */ @@ -97,6 +100,7 @@ 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_Handle(PWM_Handle_t *hpwm); #endif /* _PWM_THYRISTORS_H */ diff --git a/UPP/Core/UPP/upp_errors.c b/UPP/Core/UPP/upp_errors.c index ad9b482..1ad798e 100644 --- a/UPP/Core/UPP/upp_errors.c +++ b/UPP/Core/UPP/upp_errors.c @@ -52,7 +52,7 @@ void UPP_Errors_Power(void) void UPP_Errors_Ranges(void) { /* Преобразуем уставки в нормальные тики */ - float ticksTiMax = to_float(MB_DATA.HoldRegs.pui_params.TiMax, 1)/PM_SLOW_PERIOD_US; + float ticksTiMax = to_float(PARAM_PUI.TiMax, 1)/PM_SLOW_PERIOD_US; /* Счетчики для отсчитывания задержки выставления ошибки */ static int IMaxCnt = 0; static int UMaxCnt = 0; diff --git a/UPP/Core/UPP/upp_main.c b/UPP/Core/UPP/upp_main.c index c039738..54158dc 100644 --- a/UPP/Core/UPP/upp_main.c +++ b/UPP/Core/UPP/upp_main.c @@ -21,7 +21,7 @@ int UPP_Init(void) BenchTime_Init(); // Подключение указателей upp.errors = &errors; - upp.PUI.params = &MB_DATA.HoldRegs.pui_params; + upp.PUI.params = &PARAM_PUI; upp.PUI.values = &MB_DATA.InRegs.pui; upp.call = &MB_INTERNAL.FuncCalls; @@ -40,7 +40,7 @@ int UPP_Init(void) */ int UPP_PreWhile(void) { - UPP_Control_InternalParams(); + UPP_Params_InternalControl(); Angle_SetRange(&upp.hangle, 0.0, 0.8); PowerMonitor_Start(&upp.pm); return 0; @@ -143,7 +143,7 @@ void UPP_Tick(void) if(upp.workmode == WM_Not_Init) return; UPP_Errors_Handle(); - UPP_Control_InternalParams(); + UPP_Params_InternalControl(); } diff --git a/UPP/Core/UPP/upp_main.h b/UPP/Core/UPP/upp_main.h index c5c45c8..d134455 100644 --- a/UPP/Core/UPP/upp_main.h +++ b/UPP/Core/UPP/upp_main.h @@ -15,7 +15,7 @@ #include "angle_control.h" // Управление углом открытия #include "upp_status.h" // статус упп -#include "upp_control.h" // управление упп +#include "upp_params.h" // управление упп typedef struct diff --git a/UPP/Core/UPP/upp_control.c b/UPP/Core/UPP/upp_params.c similarity index 67% rename from UPP/Core/UPP/upp_control.c rename to UPP/Core/UPP/upp_params.c index 67d727d..54cef43 100644 --- a/UPP/Core/UPP/upp_control.c +++ b/UPP/Core/UPP/upp_params.c @@ -1,6 +1,6 @@ /** ****************************************************************************** -* @file upp_control.c +* @file upp_params.c * @brief Модуль определябщий поведение УПП ****************************************************************************** * @details @@ -18,7 +18,7 @@ static void __AngleSetLimit(void); * @brief Контроль внутренних параметров УПП. * @return HAL Status. */ -void UPP_Control_InternalParams(void) +void UPP_Params_InternalControl(void) { if(upp.call->go) // при запущеном УПП ничего не меняем return; @@ -51,23 +51,23 @@ void UPP_Control_InternalParams(void) // Параметры регулятора Угла открытия - if(__CheckSimpleParamF(&angle_max, MB_INTERNAL.param.angle.Angle_Max, 65535)) + if(__CheckSimpleParamF(&angle_max, PARAM_INTERNAL.angle.Angle_Max, 65535)) { alpha_update = 1; } - if(__CheckSimpleParamF(&angle_min, MB_INTERNAL.param.angle.Angle_Min, 65535)) + if(__CheckSimpleParamF(&angle_min, PARAM_INTERNAL.angle.Angle_Min, 65535)) { alpha_update = 1; } - if(__CheckSimpleParamF(&angle_pid_kp, MB_INTERNAL.param.angle.PID_Kp, 10000)) + if(__CheckSimpleParamF(&angle_pid_kp, PARAM_INTERNAL.angle.PID_Kp, 10000)) { alpha_update = 1; } - if(__CheckSimpleParamF(&angle_pid_ki, MB_INTERNAL.param.angle.PID_Ki, 10000)) + if(__CheckSimpleParamF(&angle_pid_ki, PARAM_INTERNAL.angle.PID_Ki, 10000)) { alpha_update = 1; } - if(__CheckSimpleParamF(&angle_pid_kd, MB_INTERNAL.param.angle.PID_Kd, 10000)) + if(__CheckSimpleParamF(&angle_pid_kd, PARAM_INTERNAL.angle.PID_Kd, 10000)) { alpha_update = 1; } @@ -81,42 +81,42 @@ void UPP_Control_InternalParams(void) adc_channel_zero[i] = upp.pm.adc.Coefs[i].lZero; // Максимальное измеряемое напряжение - if(__CheckSimpleParamF(&adc_channel_max[i], MB_INTERNAL.param.adc.ADC_Max[i], 10)) + if(__CheckSimpleParamF(&adc_channel_max[i], PARAM_INTERNAL.adc.ADC_Max[i], 10)) { adc_channel_update[i] = 1; } // Значение АЦП при нулевом входе - if(__CheckSimpleParamU16(&adc_channel_zero[i], MB_INTERNAL.param.adc.ADC_Zero[i])) + if(__CheckSimpleParamU16(&adc_channel_zero[i], PARAM_INTERNAL.adc.ADC_Zero[i])) { adc_channel_update[i] = 1; } } // Параметры алгоритма перехода через ноль - if(__CheckSimpleParamF(&zc_hysteresis, MB_INTERNAL.param.zc.Hysteresis, 10000)) + if(__CheckSimpleParamF(&zc_hysteresis, PARAM_INTERNAL.zc.Hysteresis, 10000)) { zc_update = 1; } - if(__CheckSimpleParamU16(&zc_debounce, MB_INTERNAL.param.zc.DebouneCouner)) + if(__CheckSimpleParamU16(&zc_debounce, PARAM_INTERNAL.zc.DebouneCouner)) { zc_update = 1; } // Параметры ШИМ токов - if(__CheckSimpleParamU8(&pwm_phase_mask, MB_INTERNAL.param.pwm.PhaseMask, 1)) + if(__CheckSimpleParamU8(&pwm_phase_mask, PARAM_INTERNAL.pwm.PhaseMask, 1)) { pwm_update = 1; } - if(__CheckSimpleParamU16(&pwm_freq, MB_INTERNAL.param.pwm.Frequency)) + if(__CheckSimpleParamU16(&pwm_freq, PARAM_INTERNAL.pwm.Frequency)) { pwm_update = 1; } - if(__CheckSimpleParamU8(&pwm_pulse_num, MB_INTERNAL.param.pwm.PulseNumber, 1)) + if(__CheckSimpleParamU8(&pwm_pulse_num, PARAM_INTERNAL.pwm.PulseNumber, 1)) { pwm_update = 1; } // Параметры мониторинга - if(__CheckSimpleParamF(&pm_alpha, MB_INTERNAL.param.pm.mean_alpha, 65535)) + if(__CheckSimpleParamF(&pm_alpha, PARAM_INTERNAL.pm.mean_alpha, 65535)) { for(int i = 0; i < EXP_ALL; i++) { @@ -162,7 +162,7 @@ void UPP_Control_InternalParams(void) else errors.prvt.cnt.pwm_reinit_err++; } - if (upp.hangle.Config.AngleLimit == 0) + if ((upp.hangle.Config.PeriodLimit == 0) || (upp.hangle.Config.PeriodLimit >= 0.999)) { __AngleSetLimit(); } @@ -179,59 +179,60 @@ 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; + PARAM_PUI.Iref = PUI_Iref_PERCENT_DEFAULT; + PARAM_PUI.Tnt = PUI_Tnt_MS_DEFAULT; + PARAM_PUI.Umin = PUI_Umin_PERCENT_DEFAULT; + PARAM_PUI.Umax = PUI_Umax_PERCENT_DEFAULT; + PARAM_PUI.Imax = PUI_Imax_PERCENT_DEFAULT; + PARAM_PUI.Imin = PUI_Imin_PERCENT_DEFAULT; + PARAM_PUI.TiMax = PUI_TiMax_US_DEFAULT; + PARAM_PUI.Tdelay = PUI_Tdelay_SECONDS_DEFAULT; + PARAM_PUI.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; + PARAM_INTERNAL.setpoints.TemperatureWarn = SETPOINT_TEMP_WARN*10; + PARAM_INTERNAL.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; + PARAM_INTERNAL.nominal.PhaseNumber = NOM_PHASE_NUMB; + PARAM_INTERNAL.nominal.U = NOM_U_V_DEFAULT*10; + PARAM_INTERNAL.nominal.U_deviation_plus = NOM_U_DEVIATION_PLUS_PERCENT_DEFAULT*100; + PARAM_INTERNAL.nominal.U_deviation_minus = NOM_U_DEVIATION_MINUS_PERCENT_DEFAULT*100; + PARAM_INTERNAL.nominal.F = NOM_F_HZ_DEFAULT*100; + PARAM_INTERNAL.nominal.F_deviation_plus = NOM_F_DEVIATION_PLUS_PERCENT_DEFAULT*100; + PARAM_INTERNAL.nominal.F_deviation_minus = NOM_F_DEVIATION_MINUS_PERCENT_DEFAULT*100; + PARAM_INTERNAL.nominal.I = NOM_I_A_DEFAULT*10; - MB_INTERNAL.param.pm.mean_alpha = PM_EXP_ALPHA_COEF_DEFAULT*65535; + PARAM_INTERNAL.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; + PARAM_INTERNAL.adc.ADC_Max[ADC_CHANNEL_UBA] = ADC_U_MAX_V_DEFAULT*10; + PARAM_INTERNAL.adc.ADC_Max[ADC_CHANNEL_UAC] = ADC_U_MAX_V_DEFAULT*10; + PARAM_INTERNAL.adc.ADC_Max[ADC_CHANNEL_IC] = ADC_I_MAX_A_DEFAULT*10; + PARAM_INTERNAL.adc.ADC_Max[ADC_CHANNEL_IA] = ADC_I_MAX_A_DEFAULT*10; + PARAM_INTERNAL.adc.ADC_Zero[ADC_CHANNEL_UBA] = ADC_U_ZERO_DEFAULT; + PARAM_INTERNAL.adc.ADC_Zero[ADC_CHANNEL_UAC] = ADC_U_ZERO_DEFAULT; + PARAM_INTERNAL.adc.ADC_Zero[ADC_CHANNEL_IC] = ADC_I_ZERO_DEFAULT; + PARAM_INTERNAL.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; + PARAM_INTERNAL.pwm.PhaseMask = 0x7; // (все три фазы) + PARAM_INTERNAL.pwm.Frequency = (float)PWM_THYR_FREQUENCY_HZ_DEFAULT; + PARAM_INTERNAL.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; + PARAM_INTERNAL.zc.Hysteresis = ZERO_CROSS_HYSTERESIS_PERCENT_DEFAULT*100; + PARAM_INTERNAL.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; +{ // Сколько пачка ипульсов занимает процентов от всего периода + float pulses_percent_of_period = (((float)PARAM_INTERNAL.pwm.PulseNumber / PARAM_INTERNAL.pwm.Frequency) * 1000) / ANGLE_PERIOD_MS(NOM_F_HZ_DEFAULT); + // Вычитаем этот процент из 1 - получаем максимально безопасный угол + float angle_limit = 1 - pulses_percent_of_period*1.5; // добавляем запас в половину пачки импульсов Angle_SetLimit(&upp.hangle, angle_limit); } diff --git a/UPP/Core/UPP/upp_control.h b/UPP/Core/UPP/upp_params.h similarity index 96% rename from UPP/Core/UPP/upp_control.h rename to UPP/Core/UPP/upp_params.h index 5836033..d57e813 100644 --- a/UPP/Core/UPP/upp_control.h +++ b/UPP/Core/UPP/upp_params.h @@ -1,13 +1,13 @@ /** ****************************************************************************** -* @file upp_control.h +* @file upp_params.h * @brief Модуль определябщий поведение УПП ****************************************************************************** * @details ******************************************************************************/ -#ifndef _UPP_CONTROL_H -#define _UPP_CONTROL_H +#ifndef _UPP_PARAMS_H +#define _UPP_PARAMS_H #include "upp_defs.h" #define to_float(_u16_, _coef_) ((float)_u16_/_coef_) @@ -93,8 +93,8 @@ typedef struct /* Контроль внутренних параметров УПП. */ -void UPP_Control_InternalParams(void); +void UPP_Params_InternalControl(void); /* Установка параметров на дефолтные значения */ void UPP_SetDefault(int pui_default, int internal_default); -#endif //_UPP_CONTROL_H \ No newline at end of file +#endif //_UPP_PARAMS_H \ No newline at end of file diff --git a/UPP/MDK-ARM/UPP.uvoptx b/UPP/MDK-ARM/UPP.uvoptx index fd4f4c5..a772821 100644 --- a/UPP/MDK-ARM/UPP.uvoptx +++ b/UPP/MDK-ARM/UPP.uvoptx @@ -411,30 +411,6 @@ 0 0 0 - ..\Core\UPP\upp_control.c - upp_control.c - 0 - 0 - - - 2 - 18 - 5 - 0 - 0 - 0 - ..\Core\UPP\upp_control.h - upp_control.h - 0 - 0 - - - 2 - 19 - 1 - 0 - 0 - 0 ..\Core\UPP\upp_status.c upp_status.c 0 @@ -442,7 +418,7 @@ 2 - 20 + 18 5 0 0 @@ -454,7 +430,7 @@ 2 - 21 + 19 1 0 0 @@ -466,7 +442,7 @@ 2 - 22 + 20 5 0 0 @@ -476,6 +452,30 @@ 0 0 + + 2 + 21 + 1 + 0 + 0 + 0 + ..\Core\UPP\upp_params.c + upp_params.c + 0 + 0 + + + 2 + 22 + 5 + 0 + 0 + 0 + ..\Core\UPP\upp_params.h + upp_params.h + 0 + 0 + diff --git a/UPP/MDK-ARM/UPP.uvprojx b/UPP/MDK-ARM/UPP.uvprojx index 24baab7..3da23b5 100644 --- a/UPP/MDK-ARM/UPP.uvprojx +++ b/UPP/MDK-ARM/UPP.uvprojx @@ -470,16 +470,6 @@ 5 ..\Core\UPP\angle_control.h - - upp_control.c - 1 - ..\Core\UPP\upp_control.c - - - upp_control.h - 5 - ..\Core\UPP\upp_control.h - upp_status.c 1 @@ -500,6 +490,16 @@ 5 ..\Core\UPP\upp_errors.h + + upp_params.c + 1 + ..\Core\UPP\upp_params.c + + + upp_params.h + 5 + ..\Core\UPP\upp_params.h +