diff --git a/MATLAB/app_wrapper/app_io.c b/MATLAB/app_wrapper/app_io.c index 780a0bf..3a9aad0 100644 --- a/MATLAB/app_wrapper/app_io.c +++ b/MATLAB/app_wrapper/app_io.c @@ -7,7 +7,7 @@ #include "app_wrapper.h" float dbg[16]; - +extern float iref_dbg; #define PIN_READ(_verbname_) (_verbname_##_GPIO_Port->ODR & (_verbname_##_Pin)) ? 1 : 0 void Write_Thyristors(real_T* Buffer, int ind_port) @@ -33,7 +33,7 @@ void Write_PowerMonitor(real_T* Buffer, int ind_port) int nn = 0; for (int i = 0; i < 3; i++) { //0-2 - WriteOutputArray(upp.pm.measured.U[i], ind_port, nn++); + WriteOutputArray(upp.pm.measured.fast.U[i], ind_port, nn++); } for (int i = 0; i < 3; i++) { //3-5 @@ -41,23 +41,23 @@ void Write_PowerMonitor(real_T* Buffer, int ind_port) } for (int i = 0; i < 3; i++) { //6-8 - WriteOutputArray(upp.pm.measured.F[i], ind_port, nn++); + WriteOutputArray(upp.pm.measured.final.F[i], ind_port, nn++); } for (int i = 0; i < 3; i++) { //9-11 - WriteOutputArray(upp.pm.measured.I[i], ind_port, nn++); + WriteOutputArray(upp.pm.measured.fast.I[i], ind_port, nn++); } for (int i = 0; i < 2; i++) { //12-13 - WriteOutputArray(upp.pm.measured.T[i], ind_port, nn++); + WriteOutputArray(upp.pm.measured.final.T[i], ind_port, nn++); } { //14-19 - WriteOutputArray(upp.pm.measured.Uvec, ind_port, nn++); - WriteOutputArray(upp.pm.measured.Ivec, ind_port, nn++); - WriteOutputArray(upp.pm.measured.Imean[0], ind_port, nn++); - WriteOutputArray(upp.pm.measured.Imean[1], ind_port, nn++); - WriteOutputArray(upp.pm.measured.Imean[2], ind_port, nn++); - WriteOutputArray(upp.pm.measured.Fmean, ind_port, nn++); + WriteOutputArray(upp.pm.measured.final.Uamp, ind_port, nn++); + WriteOutputArray(upp.pm.measured.final.Iamp, ind_port, nn++); + WriteOutputArray(upp.pm.measured.final.I[0], ind_port, nn++); + WriteOutputArray(upp.pm.measured.final.I[1], ind_port, nn++); + WriteOutputArray(upp.pm.measured.final.I[2], ind_port, nn++); + WriteOutputArray(upp.pm.measured.final.Fmean, ind_port, nn++); } } @@ -74,8 +74,14 @@ void app_readInputs(const real_T* Buffer) { ADC_Set_Channel_Value(ADC3, 8, ReadInputArray(0,4)); ADC_Set_Channel_Value(ADC3, 10, ReadInputArray(0,5)); - alpha_dbg = ReadInputArray(1, 0); + iref_dbg = ReadInputArray(1, 0); upp.call->go = ReadInputArray(1, 1); + + MB_INTERNAL.param.angle.Angle_Max = ReadInputArray(1, 2)*65535; + MB_INTERNAL.param.angle.Angle_Min = ReadInputArray(1, 3)*65535; + MB_INTERNAL.param.angle.PID_Kp = ReadInputArray(1, 4) * 10000; + MB_INTERNAL.param.angle.PID_Ki = ReadInputArray(1, 5) * 10000; + MB_INTERNAL.param.angle.PID_Kd = ReadInputArray(1, 6) * 10000; // USER APP INPUT END } @@ -92,20 +98,24 @@ void app_writeOutputBuffer(real_T* Buffer) { int nn = 0; + WriteOutputArray(iref_dbg, 2, nn++); + WriteOutputArray(upp.pm.measured.final.Iamp, 2, nn++); + WriteOutputArray(upp.hangle.alpha, 2, nn++); //WriteOutputArray(upp.hangle.htim->Instance->CNT, 2, nn++); - WriteOutputArray((long long)(upp.hangle.htim->Instance->CCR1) - upp.hangle.htim->Instance->CNT, 2, nn++); - WriteOutputArray((long long)(upp.hangle.htim->Instance->CCR2) - upp.hangle.htim->Instance->CNT, 2, nn++); - WriteOutputArray((long long)(upp.hangle.htim->Instance->CCR3) - upp.hangle.htim->Instance->CNT, 2, nn++); + + //WriteOutputArray((long long)(upp.hangle.htim->Instance->CCR1) - upp.hangle.htim->Instance->CNT, 2, nn++); + //WriteOutputArray((long long)(upp.hangle.htim->Instance->CCR2) - upp.hangle.htim->Instance->CNT, 2, nn++); + //WriteOutputArray((long long)(upp.hangle.htim->Instance->CCR3) - upp.hangle.htim->Instance->CNT, 2, nn++); //WriteOutputArray(dbg[0], 2, nn++); //WriteOutputArray(dbg[1], 2, nn++); //WriteOutputArray(dbg[2], 2, nn++); - WriteOutputArray(upp.hpwm.AllPhases[PHASE_A_POS].State, 2, nn++); - WriteOutputArray(upp.hpwm.AllPhases[PHASE_A_NEG].State, 2, nn++); - WriteOutputArray(upp.hpwm.AllPhases[PHASE_B_POS].State, 2, nn++); - WriteOutputArray(upp.hpwm.AllPhases[PHASE_B_NEG].State, 2, nn++); - WriteOutputArray(upp.hpwm.AllPhases[PHASE_C_POS].State, 2, nn++); - WriteOutputArray(upp.hpwm.AllPhases[PHASE_C_NEG].State, 2, nn++); + //WriteOutputArray(upp.hpwm.AllPhases[PHASE_A_POS].State, 2, nn++); + //WriteOutputArray(upp.hpwm.AllPhases[PHASE_A_NEG].State, 2, nn++); + //WriteOutputArray(upp.hpwm.AllPhases[PHASE_B_POS].State, 2, nn++); + //WriteOutputArray(upp.hpwm.AllPhases[PHASE_B_NEG].State, 2, nn++); + //WriteOutputArray(upp.hpwm.AllPhases[PHASE_C_POS].State, 2, nn++); + //WriteOutputArray(upp.hpwm.AllPhases[PHASE_C_NEG].State, 2, nn++); // USER APP OUTPUT END } \ No newline at end of file diff --git a/MATLAB/upp_r2023.slx b/MATLAB/upp_r2023.slx index 87e6520..d76bf53 100644 Binary files a/MATLAB/upp_r2023.slx and b/MATLAB/upp_r2023.slx differ diff --git a/UPP/Core/Configs/upp_config.h b/UPP/Core/Configs/upp_config.h index 709f35b..97f0a05 100644 --- a/UPP/Core/Configs/upp_config.h +++ b/UPP/Core/Configs/upp_config.h @@ -18,24 +18,32 @@ #define assert_upp(_struct_) check_null_ptr_2(_struct_, (_struct_)->f.Initialized) /* Дефайны для индексов */ +/* Линейные напряжения */ #define U_BA 0 #define U_AC 1 #define U_BC 2 +/* Токи фаз */ #define I_C 0 #define I_A 1 #define I_B 2 +/* Температуры */ #define TEMP_1 0 #define TEMP_2 1 + /** * @addtogroup UPP_DEFAULT_PARAMS Default params for external flash * @ingroup UPP_CONFIG * @brief Дефолтные параметры для внешней памяти. Они применятся по команде или по ошибке * @{ */ -/* Параметри мониторинга сети */ -#define PM_EXP_ALPHA_COEF_DEFAULT 0.01 + + +/* Номинальные параметры */ +#define SETPOINT_TEMP_WARN 70 +#define SETPOINT_TEMP_ERR 85 + /* Номинальные параметры */ #define NOM_PHASE_NUMB 3 @@ -58,6 +66,12 @@ #define PUI_Tdelay_SECONDS_DEFAULT 30 #define PUI_Interlace_EN_DEFAULT 5000 +/* Дефолтное коливчество тиков для задержки выставления ошибки */ +#define ERRORS_DELAY_TICKS_DEFAULT 10 + +/* Параметри мониторинга сети */ +#define PM_EXP_ALPHA_COEF_DEFAULT 0.01 + /* Параметры АЦП */ #define ADC_U_MAX_V_DEFAULT 1216.0 #define ADC_I_MAX_A_DEFAULT 53.0 @@ -88,6 +102,7 @@ #define PM_SLOW_PERIOD_CNT 50 ///< Период обновления медленных расчетов тиках @ref PM_ADC_PERIOD_US #define PM_TEMP_SLOW_PERIOD_CNT 200 ///< Период обновления датчиков температуры в тиках @ref PM_SLOW_PERIOD_CNT + /* Частоты таймеров в МГц*/ #define ADC_TIM8_FREQ_MZH 180 ///< Частота тиков таймера АЦП #define PWM_TIM1_FREQ_MHZ 180 ///< Частота тиков таймера ШИМ (1-4 каналы) diff --git a/UPP/Core/Configs/upp_defs.h b/UPP/Core/Configs/upp_defs.h index b1ce9bd..cd82f8c 100644 --- a/UPP/Core/Configs/upp_defs.h +++ b/UPP/Core/Configs/upp_defs.h @@ -59,6 +59,8 @@ typedef enum { Err_OverVoltage = 13, ///< Напряжение сети выше допустимого (см. Umах в @ref UPP_PUI_Params_t) Err_OverTemperature = 14, ///< Температура выше допустимой (плюс 85 °C) Err_UnderVoltage = 15, ///< Напряжение сети ниже допустимого (см. Umin в @ref UPP_PUI_Params_t) + Err_OverFrequency = 22, ///< Частота сети выше допустимой + Err_UnderFrequency = 23, ///< Частота сети ниже допустимой /* Ошибки по обрывам фаз */ Err_LossPhaseAll = 16, ///< Обрыв трёх фаз (см. Imin в @ref UPP_PUI_Params_t) @@ -69,8 +71,6 @@ typedef enum { /* Другие ошибки */ Err_LongStart = 20, ///< Затянутый пуск (ток не спадает за установленное время) (см. Tdelay в @ref UPP_PUI_Params_t) Err_Interlace = 21, ///< Неправильный порядок чередования фаз (см. Interlace в @ref UPP_PUI_Params_t) - Err_OverFrequency = 22, ///< Частота сети выше допустимой - Err_UnderFrequency = 23, ///< Частота сети ниже допустимой } UPP_ErrorType_t; @@ -148,6 +148,7 @@ typedef struct { * @brief Дефайны УПП которые используютяс исключительно внутри программы * @{ */ +#define PM_SLOW_PERIOD_US (PM_ADC_PERIOD_US*PM_SLOW_PERIOD_CNT) #define ANGLE_PERIOD_MS(_freq_) (((float)1/(_freq_*2))*1000) /** diff --git a/UPP/Core/PowerMonitor/phases_transform.c b/UPP/Core/PowerMonitor/phases_transform.c index cf6ab63..e9cb632 100644 --- a/UPP/Core/PowerMonitor/phases_transform.c +++ b/UPP/Core/PowerMonitor/phases_transform.c @@ -11,7 +11,6 @@ /** * @brief Рассчитать результирующий вектор трехфазной системы по фазным величинам. * @return Длина вектора (модуль). - * @note Вызывается в DMA2_Stream0_IRQHandler() для обработки всего, что пришло по DMA. */ float vector_abs_phase_calc(float phase1, float phase2) { @@ -30,7 +29,6 @@ float vector_abs_phase_calc(float phase1, float phase2) /** * @brief Рассчитать результирующий вектор трехфазной системы по линейным величинам. * @return Длина вектора (модуль). - * @note Вызывается в DMA2_Stream0_IRQHandler() для обработки всего, что пришло по DMA. */ float vector_abs_linear_calc(float phase1, float phase2) { @@ -46,4 +44,40 @@ float vector_abs_linear_calc(float phase1, float phase2) return 0; } +/** + * @brief Рассчитать фазные напряжения из линейных (звезда) + * @param Ulin Линейные напряжения [Uba Uac Ubc] + * @param Uph Фазные напряжения [Ua Ub Uc] + */ +void linear_to_phase_star(float *Ulin, float *Uph) +{ + if(Ulin == NULL || Uph == NULL) + return; + // Соответствие макросам: Ulin[0] = UBA, Ulin[1] = UAC, Ulin[2] = UBC + float Uba = Ulin[0]; + float Uac = Ulin[1]; + float Ubc = Ulin[2]; + + // Формулы для звезды (сумма фаз = 0) + Uph[0] = (Uba - Ubc)/3.0f; // Ua + Uph[1] = (Ubc - Uac)/3.0f; // Ub + Uph[2] = (Uac - Uba)/3.0f; // Uc +} + +/** + * @brief Рассчитать фазные напряжения из линейных (треугольник) + * @param Ulin Линейные напряжения [Uba Uac Ubc] + * @param Uph Фазные напряжения [Ua Ub Uc] + */ +void linear_to_phase_delta(float *Ulin, float *Uph) +{ + if(Ulin == NULL || Uph == NULL) + return; + + // Соответствие макросам: Ulin[0] = UBA, Ulin[1] = UAC, Ulin[2] = UBC + // Для треугольника фазные напряжения равны линейным + Uph[0] = Ulin[0]; // Ua = Uba + Uph[1] = Ulin[2]; // Ub = Ubc + Uph[2] = Ulin[1]; // Uc = Uac +} diff --git a/UPP/Core/PowerMonitor/phases_transform.h b/UPP/Core/PowerMonitor/phases_transform.h index 5d78003..c031840 100644 --- a/UPP/Core/PowerMonitor/phases_transform.h +++ b/UPP/Core/PowerMonitor/phases_transform.h @@ -12,5 +12,8 @@ float vector_abs_phase_calc(float phase1, float phase2); /* Рассчитать результирующий вектор трехфазной системы по линейным величинам. */ float vector_abs_linear_calc(float phase1, float phase2); - +/* Рассчитать фазные напряжения из линейных (звезда) */ +void linear_to_phase_star(float *Ulin, float *UphUc); +/* Рассчитать фазные напряжения из линейных (треугольник) */ +void linear_to_phase_delta(float *Ulin, float *Uph); #endif /* _PHASES_TRANSFORM_H_ */ diff --git a/UPP/Core/PowerMonitor/power_monitor.c b/UPP/Core/PowerMonitor/power_monitor.c index aeb06ec..5f11c17 100644 --- a/UPP/Core/PowerMonitor/power_monitor.c +++ b/UPP/Core/PowerMonitor/power_monitor.c @@ -6,12 +6,21 @@ * @details ******************************************************************************/ #include "power_monitor.h" +#include "power_protect.h" #include "phases_transform.h" #include "adc.h" #include "tim.h" +#define U_BC_calc(_u1_, _u2_) (-((_u1_) + (_u2_))) +#define I_B_calc(_i1_, _i2_) (-((_i1_) + (_i2_))) + static void __SynchAvgFilters(PowerMonitor_t *hpm); +/** + * @brief Инициализация мониторинга сети. + * @param hpm Указатель на структуру мониторинга сети + * @details Инициализирует: АЦП, Алгоритм перехода через ноль, Фильтры + */ HAL_StatusTypeDef PowerMonitor_Init(PowerMonitor_t *hpm) { if(hpm == NULL) @@ -24,31 +33,31 @@ HAL_StatusTypeDef PowerMonitor_Init(PowerMonitor_t *hpm) /* Инициализация каналов АЦП */ if(ADC_ConfigChannel(&hpm->adc, ADC_CHANNEL_UBA, MB_INTERNAL.param.adc.ADC_Zero[ADC_CHANNEL_UBA], - MB_INTERNAL.param.adc.ADC_Max[ADC_CHANNEL_UBA], + to_float(MB_INTERNAL.param.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], - MB_INTERNAL.param.adc.ADC_Max[ADC_CHANNEL_UAC], + to_float(MB_INTERNAL.param.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], - MB_INTERNAL.param.adc.ADC_Max[ADC_CHANNEL_IC], + to_float(MB_INTERNAL.param.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], - MB_INTERNAL.param.adc.ADC_Max[ADC_CHANNEL_IA], + to_float(MB_INTERNAL.param.adc.ADC_Max[ADC_CHANNEL_IA], 10), 4095) != HAL_OK) return HAL_ERROR; /* Инициализация алгоритма перехода через ноль */ - if(ZC_Init(&hpm->zc, 3, (float)MB_INTERNAL.param.zc.Hysteresis/100, MB_INTERNAL.param.zc.DebouneCouner) != HAL_OK) + if(ZC_Init(&hpm->zc, 3, to_float(MB_INTERNAL.param.zc.Hysteresis, 100), MB_INTERNAL.param.zc.DebouneCouner) != HAL_OK) return HAL_ERROR; /* Инициализация каналов алгоритма перехода через ноль */ @@ -63,7 +72,7 @@ HAL_StatusTypeDef PowerMonitor_Init(PowerMonitor_t *hpm) /* Инициализация экпоненциального фильтра медленного алга */ for(int i = 0; i < EXP_ALL; i++) { - if(FilterExp_Init(&hpm->exp[i], (float)MB_INTERNAL.param.pm.mean_alpha/65535)) + if(FilterExp_Init(&hpm->exp[i], to_float(MB_INTERNAL.param.pm.mean_alpha,65535))) return HAL_ERROR; Filter_Start(&hpm->exp[i]); } @@ -88,6 +97,11 @@ HAL_StatusTypeDef PowerMonitor_Init(PowerMonitor_t *hpm) } +/** + * @brief Запустить мониторинг сети. + * @param hpm Указатель на структуру мониторинга сети + * @details Запускает АЦП с периодом @ref PM_ADC_PERIOD_US + */ HAL_StatusTypeDef PowerMonitor_Start(PowerMonitor_t *hpm) { if(hpm == NULL) @@ -100,51 +114,68 @@ HAL_StatusTypeDef PowerMonitor_Start(PowerMonitor_t *hpm) } -void PowerMonitor_SlowHandle(PowerMonitor_t *hpm) +/** + * @brief Медленные расчеты АЦП. + * @param hpm Указатель на структуру мониторинга сети + * @details Вызывается в main после накопления @ref PM_SLOW_PERIOD_CNT выборок АЦП. + * Делаются всякие расчеты для более подробного мониторинга сети и защит. + * Сам АЦП считывается в @ref PowerMonitor_FastCalc + */ +void PowerMonitor_SlowCalc(PowerMonitor_t *hpm) { if(hpm == NULL) return; - if(!hpm->f.runSlow) - return; PowerMonitor_Measured_t *meas = &hpm->measured; /* Обработка температур */ float t1 = hpm->adc.Data[ADC_CHANNEL_TEMP1]; float t2 = hpm->adc.Data[ADC_CHANNEL_TEMP2]; - meas->T[TEMP_1] = Filter_Process(&hpm->avg[ADC_CHANNEL_TEMP1], t1); - meas->T[TEMP_2] = Filter_Process(&hpm->avg[ADC_CHANNEL_TEMP2], t2); + meas->final.T[TEMP_1] = Filter_Process(&hpm->avg[ADC_CHANNEL_TEMP1], t1); + meas->final.T[TEMP_2] = Filter_Process(&hpm->avg[ADC_CHANNEL_TEMP2], t2); /* Расчет третьей фазы */ - meas->Uslow[U_BC] = -meas->Uslow[U_BA] - meas->Uslow[U_AC]; - meas->Islow[I_B] = -meas->Islow[I_A] - meas->Islow[I_C]; - + meas->slow.U[U_BC] = U_BC_calc(meas->slow.U[U_BA], meas->slow.U[U_AC]); + meas->slow.I[I_B] = I_B_calc(meas->slow.I[I_A], meas->slow.I[I_C]); + /* Расчет всякого для трех фаз отдельно */ float fmean = 0; // средняя частота по трем фазам float iphase_mean = 0; // средний ток каждой фазы + float uphase_mean = 0; // среднее напряжение каждой фазы for(int i = 0; i < 3; i++) { /* Получение частоты фазы */ - meas->F[i] = ZC_GetFrequency(&hpm->zc, i) / 2; - fmean += meas->F[i]; + meas->final.F[i] = ZC_GetFrequency(&hpm->zc, i) / 2; + fmean += meas->final.F[i]; + + /* Средниее напряжение фазы */ + uphase_mean = fabsf(meas->slow.U[i]); + meas->final.U[i] = Filter_Process(&hpm->exp[EXP_UBA+i], uphase_mean); /* Средний ток фазы */ - iphase_mean = fabsf(meas->Islow[i]); - meas->Imean[i] = Filter_Process(&hpm->exp[EXP_IC+i], iphase_mean); + iphase_mean = fabsf(meas->slow.I[i]); + meas->final.I[i] = Filter_Process(&hpm->exp[EXP_IC+i], iphase_mean); } /* Получение средней частоты по трем фазам */ - fmean /= 3; - meas->Fmean = Filter_Process(&hpm->exp[EXP_F], fmean); + + meas->final.Fmean = fmean / 3; - /* Расчет результирущих векторов трехфазной сети */ - float uvec = vector_abs_linear_calc(meas->Uslow[U_BA], meas->Uslow[U_AC]); - float ivec = vector_abs_phase_calc(meas->Islow[I_A], meas->Islow[I_C]); - meas->Uvec = Filter_Process(&hpm->exp[EXP_U], uvec); - meas->Ivec = Filter_Process(&hpm->exp[EXP_I], ivec); - hpm->f.runSlow = 0; + /* Расчет амплитуд трехфазной сети */ + float uamp = vector_abs_linear_calc(meas->slow.U[U_BA], meas->slow.U[U_AC]); + float iamp = vector_abs_phase_calc(meas->slow.I[I_A], meas->slow.I[I_C]); + meas->final.Uamp = Filter_Process(&hpm->exp[EXP_U], uamp); + meas->final.Iamp = Filter_Process(&hpm->exp[EXP_I], iamp); + } -void PowerMonitor_Handle(PowerMonitor_t *hpm) +/** + * @brief Считывание АЦП и быстрые расчеты. + * @param hpm Указатель на структуру мониторинга сети + * @details Вызывается в прерывании АЦП по получению данных. + * Далее данные считываются и делаются базовые преобразования + * Более подробные расчеты в @ref PowerMonitor_SlowCalc + */ +void PowerMonitor_FastCalc(PowerMonitor_t *hpm) { if(hpm == NULL) return; @@ -153,31 +184,32 @@ void PowerMonitor_Handle(PowerMonitor_t *hpm) /* Заполняем величины Напряжений/Токов */ PowerMonitor_Measured_t *meas = &hpm->measured; - meas->U[U_BA] = hpm->adc.Data[ADC_CHANNEL_UBA]; - meas->U[U_AC] = hpm->adc.Data[ADC_CHANNEL_UAC]; - meas->U[U_BC] = -meas->U[U_BA] - meas->U[U_AC]; - meas->I[I_C] = hpm->adc.Data[ADC_CHANNEL_IC]; - meas->I[I_A] = hpm->adc.Data[ADC_CHANNEL_IA]; - meas->I[I_B] = -meas->I[I_A] - meas->I[I_C]; + meas->real.U[U_BA] = hpm->adc.Data[ADC_CHANNEL_UBA]; + meas->real.U[U_AC] = hpm->adc.Data[ADC_CHANNEL_UAC]; + meas->real.U[U_BC] = U_BC_calc(meas->real.U[U_BA], meas->real.U[U_AC]); + + meas->real.I[I_C] = hpm->adc.Data[ADC_CHANNEL_IC]; + meas->real.I[I_A] = hpm->adc.Data[ADC_CHANNEL_IA]; + meas->real.I[I_B] = I_B_calc(meas->real.I[I_A], meas->real.I[I_C]); /* Преобразуем в относительные единицы (о.е.) */ for(int i = 0; i < 3; i++) { - meas->Ufast[i] = 10*meas->U[i]/MB_INTERNAL.param.nominal.U; - meas->Ifast[i] = 10*meas->I[i]/MB_INTERNAL.param.nominal.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; } /* Ищем переход через ноль */ - ZC_ProcessAllChannels(&hpm->zc, meas->Ufast, usTick); + ZC_ProcessAllChannels(&hpm->zc, meas->fast.U, usTick); /* Вообще фильтры должны рабтоать синхронно, но на всякий синхронизация */ __SynchAvgFilters(hpm); - /* Накопление Average для медленной фильтрации */ - meas->Uslow[U_BA] = Filter_Process(&hpm->avg[ADC_CHANNEL_UBA], meas->Ufast[U_BA]); - meas->Uslow[U_AC] = Filter_Process(&hpm->avg[ADC_CHANNEL_UAC], meas->Ufast[U_AC]); - meas->Islow[I_C] = Filter_Process(&hpm->avg[ADC_CHANNEL_IC], meas->Ifast[I_C]); - meas->Islow[I_A] = Filter_Process(&hpm->avg[ADC_CHANNEL_IA], meas->Ifast[I_A]); + /* Average для медленной фильтрации */ + meas->slow.U[U_BA] = Filter_Process(&hpm->avg[ADC_CHANNEL_UBA], meas->fast.U[U_BA]); + meas->slow.U[U_AC] = Filter_Process(&hpm->avg[ADC_CHANNEL_UAC], meas->fast.U[U_AC]); + meas->slow.I[I_C] = Filter_Process(&hpm->avg[ADC_CHANNEL_IC], meas->fast.I[I_C]); + meas->slow.I[I_A] = Filter_Process(&hpm->avg[ADC_CHANNEL_IA], meas->fast.I[I_A]); /* Запускаем медленную обработку через slow_period прерываний */ @@ -186,7 +218,6 @@ void PowerMonitor_Handle(PowerMonitor_t *hpm) /* Берем 0 фильтр, просто так, потому что они все должны работать синхронно */ if(Filter_isDataReady(&hpm->avg[0])) { - hpm->isr_cnt = 0; if(!hpm->f.runSlow) { @@ -204,6 +235,46 @@ void PowerMonitor_Handle(PowerMonitor_t *hpm) } } + +/** + * @brief Проверяет защиты питания и температур. + * @param measure Указатель на структуру с измеренными значениями + * @param Running Флаг: + * - 1 - УПП в работе, + * - 0 - УПП ожидает команды + * @return 1 - была обнаружена ощибка, 0 - все ок + */ +int PowerMonitor_Protect(PowerMonitor_t *hpm, uint8_t Running) +{ + if(hpm == NULL) + 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; + + /*=============== ЗАЩИТЫ ПО НАПРЯЖЕНИЮ ==================*/ + hpm->f.isU = Protect_Voltages(measure, protect, nominal); + + /* Если УПП в работе */ + if(Running) + { + /*=============== ЗАЩИТЫ ПО ТОКУ ==================*/ + hpm->f.isI = Protect_Currents(measure, protect, nominal); + } + + /*=============== ЗАЩИТЫ ВСЯКИЕ ДРУГИЕ ==================*/ + Protect_Misc(measure, protect, nominal); + + + if(errors.prvt.f.all) + return 1; + else + return 0; +} + + + /* Синхронизация фильтров. Но вообще не должна никогда отрабатывать */ static void __SynchAvgFilters(PowerMonitor_t *hpm) { diff --git a/UPP/Core/PowerMonitor/power_monitor.h b/UPP/Core/PowerMonitor/power_monitor.h index 6d0d54a..2b9ef4a 100644 --- a/UPP/Core/PowerMonitor/power_monitor.h +++ b/UPP/Core/PowerMonitor/power_monitor.h @@ -11,58 +11,72 @@ #include "zero_cross.h" /* Индексы экспоненциальных фильтров */ -#define EXP_ALL 6 +#define EXP_ALL 8 #define EXP_U 0 -#define EXP_I 1 -#define EXP_IC 2 -#define EXP_IA 3 -#define EXP_IB 4 -#define EXP_F 5 +#define EXP_UBA 1 +#define EXP_UAC 2 +#define EXP_UBC 3 +#define EXP_I 4 +#define EXP_IC 5 +#define EXP_IA 6 +#define EXP_IB 7 +/** + * @brief Флаги Мониторинга сети + */ typedef struct { unsigned runSlow:1; ///< Запустить медленный алгоритм в while(1) unsigned isU:1; ///< Есть ли напряжение unsigned isI:1; ///< Есть ли ток - - unsigned protectUmax:1; ///< Отработка защиты по макс. напряжению - unsigned protectUmin:1; ///< Отработка защиты по мак с. напряжению - unsigned protectImax:1; ///< Отработка защиты по макс. току - unsigned protectImin:1; ///< Отработка защиты по мин. току }PowerMonitor_Flags_t; +/** + * @brief Измеренные и приведенные значения с АЦП + */ typedef struct { - /* Усредненные величины (о.е.) */ - float Uvec; ///< Результирующий вектор Напряжения по трем фазам - float Ivec; ///< Результирующий вектор Тока по трем фазам - float Imean[3]; ///< Средний Ток по трем фазам - float Fmean; ///< Средняя Частота по трем фазам + /** @brief Усредненные величины (о.е.) */ + struct + { + float Uamp; ///< Результирующий вектор Напряжения по трем фазам + float Iamp; ///< Результирующий вектор Тока по трем фазам + float U[3]; ///< Среднее Наряжение по трем фазам + float I[3]; ///< Средний Ток по трем фазам + float Fmean; ///< Средняя Частота по трем фазам + float F[3]; ///< Частота от Zero Cross (обновляется в main) + float T[2]; ///< Температура (обновляется в main) + }final; - /* Быстрые величины (в о.е.) - обновляются в каждом прерывании АЦП */ - float Ufast[3]; ///< Напряжение - float Ifast[3]; ///< Ток - - /* Медленные величины (в о.е.) - обновляются в main в @ref PowerMonitor_SlowHandle */ - float Uslow[3]; ///< Напряжение - float Islow[3]; ///< Ток - - /* Реальные величины - обновляются кто где, и содержат значения в В/А/Цельсиях */ - float U[3]; ///< Напряжение (обновляется в прерывании АЦП) - float I[3]; ///< Ток (обновляется в прерывании АЦП) - float F[3]; ///< Частота от Zero Cross (обновляется в main) - float T[2]; ///< Температура (обновляется в main) + /** @brief Быстрые величины (в о.е.) - обновляются в каждом прерывании АЦП @ref PowerMonitor_FastCalc */ + struct + { + float U[3]; ///< Напряжение + float I[3]; ///< Ток + }fast; + /** @brief Медленные величины (в о.е.) - обновляются в main в @ref PowerMonitor_SlowCalc */ + struct + { + float U[3]; ///< Напряжение + float I[3]; ///< Ток + }slow; + + /** @brief Реальные величины - обновляются кто где, и содержат значения в В/А */ + struct + { + float U[3]; ///< Напряжение (обновляется в прерывании АЦП) + float I[3]; ///< Ток (обновляется в прерывании АЦП) + }real; }PowerMonitor_Measured_t; -typedef struct -{ -}PowerMonitor_Filters_t; - +/** + * @brief Структура для мониторинга сети + */ typedef struct { ADC_Periodic_t adc; ///< Хендл периодического АЦП @@ -70,22 +84,24 @@ typedef struct PowerMonitor_Measured_t measured; ///< Измеренные/рассчитанные величины - FilterExp_t exp[EXP_ALL]; ///< Фильтры для mean - FilterAverage_t avg[ADC_NUMB_OF_CHANNELS]; ///< Фильтры для avg + FilterExp_t exp[EXP_ALL]; ///< Фильтры для сглаживания мговенного значения Напряжения/Токов + FilterAverage_t avg[ADC_NUMB_OF_CHANNELS]; ///< Фильтры для сглаживания медленных величин АЦП PowerMonitor_Flags_t f; ///< Флаги мониторинга - - - uint32_t slow_period; - uint32_t isr_cnt; + uint32_t isr_cnt; }PowerMonitor_t; extern PowerMonitor_t pm; - +/* Инициализация мониторинга сети */ HAL_StatusTypeDef PowerMonitor_Init(PowerMonitor_t *hpm); +/* Запустить мониторинг сети */ HAL_StatusTypeDef PowerMonitor_Start(PowerMonitor_t *hpm); -void PowerMonitor_SlowHandle(PowerMonitor_t *hpm); -void PowerMonitor_Handle(PowerMonitor_t *hpm); +/* Медленные расчеты АЦП */ +void PowerMonitor_SlowCalc(PowerMonitor_t *hpm); +/* Считывание АЦП и быстрые расчеты */ +void PowerMonitor_FastCalc(PowerMonitor_t *hpm); +/* Проверяет защиты питания и температур */ +int PowerMonitor_Protect(PowerMonitor_t *hpm, uint8_t Running); #endif /* _POWER_MONITOR_H_ */ diff --git a/UPP/Core/PowerMonitor/power_protect.c b/UPP/Core/PowerMonitor/power_protect.c index 99d8aeb..b67dae8 100644 --- a/UPP/Core/PowerMonitor/power_protect.c +++ b/UPP/Core/PowerMonitor/power_protect.c @@ -5,4 +5,199 @@ ****************************************************************************** * @details ******************************************************************************/ -#include "power_protect.h" \ No newline at end of file +#include "power_protect.h" + + +/** + * @brief Проверяет защиты по напряжению. + * @note Заполняет флаги prvt ошибок (приватные). + * Потом в @ref UPP_ErrorsHandle исходя из них заполняются ошибки для ПУИ + * @return 1 - напряжение есть, 0 - напряжения нет + */ +int Protect_Voltages(PowerMonitor_Measured_t *measure, UPP_PUI_Params_t *protect, UPP_ParamsNominal_t *nominal) +{ + /* Переводим уставки ПУИ в удобный вид */ + float lUmin = to_float(protect->Umin, 100)/**to_float(nominal->U, 10)*/; + float lUmax = to_float(protect->Umax, 100)/**to_float(nominal->U, 10)*/; + float lPhaseSequence = to_float(nominal->PhaseSequence, 100); + + /* Общее напряжение */ + if(measure->final.Uamp > lUmax) + { + errors.prvt.f.err.uamp_max = 1; + } + else if (measure->final.Uamp < lUmin) + { + errors.prvt.f.err.uamp_min = 1; + } + else + { + errors.prvt.f.err.uamp_max = 0; + errors.prvt.f.err.uamp_min = 0; + } + + /* Последовательность фаз */ + int realPhaseSequence = 0; + if(realPhaseSequence != lPhaseSequence) + { + errors.prvt.f.err.interlance = 1; + } + else + { + errors.prvt.f.err.interlance = 0; + } + + return (errors.prvt.f.err.uamp_min == 0); +} + +/** + * @brief Проверяет защиты по току. + * @note Заполняет флаги prvt ошибок (приватные). + * Потом в @ref UPP_ErrorsHandle исходя из них заполняются ошибки для ПУИ + */ +int Protect_Currents(PowerMonitor_Measured_t *measure, UPP_PUI_Params_t *protect, UPP_ParamsNominal_t *nominal) +{ + /* Переводим уставки ПУИ в удобный вид */ + float lIref = to_float(protect->Iref, 100)/**to_float(nominal->I, 10)*/; + float lImax = to_float(protect->Imax, 100)/**to_float(nominal->I, 10)*/; + float lImin = to_float(protect->Imin, 100)/**to_float(nominal->I, 10)*/; + + /* Общий ток */ + if(measure->final.Iamp > lImax) + { + errors.prvt.f.err.iamp_max = 1; + } + else if (measure->final.Iamp < lImin) + { + errors.prvt.f.err.iamp_min = 1; + } + else + { + errors.prvt.f.err.iamp_max = 0; + errors.prvt.f.err.iamp_min = 0; + } + + /* Ток по фазам */ + if(measure->final.I[I_A] > lImax) + { + errors.prvt.f.err.ia_max = 1; + } + else if (measure->final.I[I_A] < lImin) + { + errors.prvt.f.err.ia_min = 1; + } + else + { + errors.prvt.f.err.ia_max = 0; + errors.prvt.f.err.ia_min = 0; + } + + if(measure->final.I[I_B] > lImax) + { + errors.prvt.f.err.ib_max = 1; + } + else if (measure->final.I[I_B] < lImin) + { + errors.prvt.f.err.ib_min = 1; + } + else + { + errors.prvt.f.err.ib_max = 0; + errors.prvt.f.err.ib_min = 0; + } + + if(measure->final.I[I_C] > lImax) + { + errors.prvt.f.err.ic_max = 1; + } + else if (measure->final.I[I_C] < lImin) + { + errors.prvt.f.err.ic_min = 1; + } + else + { + errors.prvt.f.err.ic_max = 0; + errors.prvt.f.err.ic_min = 0; + } + + return (errors.prvt.f.err.iamp_min == 0); +} + + + +/** + * @brief Проверяет всякие другие защиты (частота, температура). + * @note Заполняет флаги prvt ошибок (приватные). + * Потом в @ref UPP_ErrorsHandle исходя из них заполняются ошибки для ПУИ + */ +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 lTwarn = to_float(MB_INTERNAL.param.setpoints.TemperatureWarn, 100); + float lTerr = to_float(MB_INTERNAL.param.setpoints.TemperatureWarn, 100); + + + /*=============== ЗАЩИТЫ ПО ЧАСТОТЕ ==================*/ + if(measure->final.F[U_AC] > lFmax) + { + errors.prvt.f.err.fac_max = 1; + } + else if (measure->final.F[U_AC] < lFmin) + { + errors.prvt.f.err.fac_min = 1; + } + else + { + errors.prvt.f.err.fac_max = 0; + errors.prvt.f.err.fac_min = 0; + } + + if(measure->final.F[U_BA] > lFmax) + { + errors.prvt.f.err.fba_max = 1; + } + else if (measure->final.F[U_BA] < lFmin) + { + errors.prvt.f.err.fba_min = 1; + } + else + { + errors.prvt.f.err.fba_max = 0; + errors.prvt.f.err.fba_min = 0; + } + + if(measure->final.F[U_BC] > lFmax) + { + errors.prvt.f.err.fbc_max = 1; + } + else if (measure->final.F[U_BC] < lFmin) + { + errors.prvt.f.err.fbc_min = 1; + } + else + { + errors.prvt.f.err.fbc_max = 0; + errors.prvt.f.err.fbc_min = 0; + } + + + + /*=============== ЗАЩИТЫ ПО ТЕМПЕРАТУРЕ ==================*/ + if(measure->final.T[TEMP_1] > lTerr) + { + errors.prvt.f.err.temp_err = 1; + } + else if (measure->final.T[TEMP_1] > lTwarn) + { + errors.prvt.f.err.temp_warn = 1; + } + else + { + errors.prvt.f.err.temp_err = 0; + errors.prvt.f.err.temp_warn = 0; + } +} diff --git a/UPP/Core/PowerMonitor/power_protect.h b/UPP/Core/PowerMonitor/power_protect.h index a378e78..c19502b 100644 --- a/UPP/Core/PowerMonitor/power_protect.h +++ b/UPP/Core/PowerMonitor/power_protect.h @@ -6,6 +6,13 @@ *****************************************************************************/ #ifndef _POWER_PROTECT_H_ #define _POWER_PROTECT_H_ -#include "main.h" +#include "power_monitor.h" + +/* Проверяет защиты по напряжению. */ +int Protect_Voltages(PowerMonitor_Measured_t *measure, UPP_PUI_Params_t *protect, UPP_ParamsNominal_t *nominal); +/* Проверяет защиты по току. */ +int Protect_Currents(PowerMonitor_Measured_t *measure, UPP_PUI_Params_t *protect, UPP_ParamsNominal_t *nominal); +/* Проверяет всякие другие защиты (частота, температура). */ +void Protect_Misc(PowerMonitor_Measured_t *measure, UPP_PUI_Params_t *protect, UPP_ParamsNominal_t *nominal); #endif /* _POWER_PROTECT_H_ */ diff --git a/UPP/Core/Src/stm32f4xx_it.c b/UPP/Core/Src/stm32f4xx_it.c index cf5eee0..2d83618 100644 --- a/UPP/Core/Src/stm32f4xx_it.c +++ b/UPP/Core/Src/stm32f4xx_it.c @@ -23,8 +23,6 @@ /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include "upp_main.h" -#include "pwm_thyristors.h" -#include "angle_control.h" /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ diff --git a/UPP/Core/UPP/angle_control.c b/UPP/Core/UPP/angle_control.c index 781a050..c76cee4 100644 --- a/UPP/Core/UPP/angle_control.c +++ b/UPP/Core/UPP/angle_control.c @@ -21,19 +21,90 @@ 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); + Angle_PID_Init(hangle, kp, ki, kd); + // Инициализация каналов HAL_TIM_OC_Start_IT(hangle->htim, ANGLE_CHANNEL_1); HAL_TIM_OC_Start_IT(hangle->htim, ANGLE_CHANNEL_2); HAL_TIM_OC_Start_IT(hangle->htim, ANGLE_CHANNEL_3); + // Сброс всех каналов Angle_Reset(hangle, UPP_PHASE_A); Angle_Reset(hangle, UPP_PHASE_B); Angle_Reset(hangle, UPP_PHASE_C); + + // Инициализация углов + float angle_max = to_float(MB_INTERNAL.param.angle.Angle_Max, 65535); + float angle_min = to_float(MB_INTERNAL.param.angle.Angle_Min, 65535); + + hangle->f.Initialized = 1; return HAL_OK; } + +/** + * @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; + + /* Вычисляем выход PID */ + float angle = arm_pid_f32(&hangle->pid, err); // делта подаём как ошибку + + /* Ограничиваем диапазон и сохраняем в alpha */ + 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 Указатель на таймер + * @param kp, ki kd Коэффициенты регулятора + */ +void Angle_PID_Init(Angle_Handle_t *hangle, float kp, float ki, float kd) +{ + if(assert_upp(hangle)) + return; + + hangle->pid.Kp = kp; + hangle->pid.Ki = ki; + hangle->pid.Kd = kd; + arm_pid_init_f32(&hangle->pid, 1); +} + /** * @brief Инициализация углов открытия. * @param hangle Указатель на таймер @@ -67,6 +138,28 @@ HAL_StatusTypeDef Angle_SetRange(Angle_Handle_t *hangle, float AngleMin, float A return HAL_OK; } + +/** + * @brief Выставление текущего угла открытия тиристоров. + * @param hangle Указатель на таймер + * @param AngleLimit Лимит AngleMax, рассчитывается от параметров ШИМ + * @param AngleMin Минимально возможный угол открытия + * @param AngleMax Максимально возможный угол открытия + * @return HAL Status. + */ +HAL_StatusTypeDef Angle_SetAngle(Angle_Handle_t *hangle, float Angle) +{ + if(assert_upp(hangle)) + return HAL_ERROR; + + if(Angle > hangle->Config.AngleLimit) + Angle = hangle->Config.AngleLimit; + + hangle->alpha = Angle; + + return HAL_OK; +} + /** * @brief Инициализация предельного угла открытия. * @param hangle Указатель на таймер @@ -129,7 +222,7 @@ UPP_Phase_t Angle_Handle(Angle_Handle_t *hangle) * @param Phase Для какой фазы надо установить угол открытия * @return HAL Status. */ -HAL_StatusTypeDef Angle_Start(Angle_Handle_t *hangle, UPP_Phase_t Phase, float Angle, float PeriodMs) +HAL_StatusTypeDef Angle_Start(Angle_Handle_t *hangle, UPP_Phase_t Phase, float PeriodMs) { if(assert_upp(hangle)) return HAL_ERROR; @@ -139,16 +232,16 @@ HAL_StatusTypeDef Angle_Start(Angle_Handle_t *hangle, UPP_Phase_t Phase, float A { return HAL_ERROR; } - if(Angle > hangle->Config.AngleMax) + if(hangle->alpha > hangle->Config.AngleMax) { - Angle = hangle->Config.AngleMax; + hangle->alpha = hangle->Config.AngleMax; } - if(Angle < hangle->Config.AngleMin) + if(hangle->alpha < hangle->Config.AngleMin) { - Angle = hangle->Config.AngleMin; + hangle->alpha = hangle->Config.AngleMin; } - uint32_t timer_ticks = TIM_MillisToTick(PeriodMs*Angle, ANGLE_TIM2_FREQ_MHZ); + uint32_t timer_ticks = TIM_MillisToTick(PeriodMs*hangle->alpha, ANGLE_TIM2_FREQ_MHZ); uint32_t ccr_ticks = __HAL_TIM_GET_COUNTER(hangle->htim) + timer_ticks; switch(Phase) diff --git a/UPP/Core/UPP/angle_control.h b/UPP/Core/UPP/angle_control.h index 2b62a01..527394a 100644 --- a/UPP/Core/UPP/angle_control.h +++ b/UPP/Core/UPP/angle_control.h @@ -8,6 +8,9 @@ #define _ANGLE_CONTROL_H_ #include "main.h" +/** + * @brief Конфигурация алгоритма управления углом открытия + */ typedef struct { float AngleLimit; ///< Лимит AngleMax, рассчитывается от параметров ШИМ @@ -15,25 +18,39 @@ typedef struct float AngleMax; ///< Максимально возможный угол открытия }Angle_Config_t; +/** + * @brief Структура для управления углом открытия + */ typedef struct { - TIM_HandleTypeDef *htim; - Angle_Config_t Config; + TIM_HandleTypeDef *htim; ///< Указатель на таймер для расчета угла + Angle_Config_t Config; ///< Конфигурации алгоритма расчета угла открытия тиристоров + + float alpha; ///< текущий угол открытия + arm_pid_instance_f32 pid; ///< ПИД регулятор для управления углом struct { - unsigned Initialized : 1; + unsigned Initialized : 1; ///< Структура инициализирована unsigned Running : 3; ///< Сколько каналов запущено сейчас - } f; + } 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); +/* Выставление текущего угла открытия тиристоров. */ +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 Angle, float PeriodMs); +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); diff --git a/UPP/Core/UPP/pwm_thyristors.c b/UPP/Core/UPP/pwm_thyristors.c index 25a7abc..b978b5e 100644 --- a/UPP/Core/UPP/pwm_thyristors.c +++ b/UPP/Core/UPP/pwm_thyristors.c @@ -6,7 +6,6 @@ * @details ******************************************************************************/ #include "pwm_thyristors.h" -#include "angle_control.h" #include "tim.h" static HAL_StatusTypeDef __PWM_SetOutputState(PWM_Channel_t *hCh, uint32_t state); diff --git a/UPP/Core/UPP/upp_control.c b/UPP/Core/UPP/upp_control.c index e949a30..6f675cc 100644 --- a/UPP/Core/UPP/upp_control.c +++ b/UPP/Core/UPP/upp_control.c @@ -24,10 +24,17 @@ void UPP_Control_InternalParams(void) 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}; @@ -42,6 +49,32 @@ void UPP_Control_InternalParams(void) 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; @@ -85,7 +118,7 @@ void UPP_Control_InternalParams(void) // Параметры мониторинга if(__CheckSimpleParamF(&pm_alpha, MB_INTERNAL.param.pm.mean_alpha, 65535)) { - for(int i = 0; i < 3; i++) + for(int i = 0; i < EXP_ALL; i++) { Filter_ReInit(&upp.pm.exp[i], pm_alpha); } @@ -93,6 +126,12 @@ void UPP_Control_InternalParams(void) + // Обновление регулятора угла открытия + if(alpha_update) + { + Angle_SetRange(&upp.hangle, angle_max, 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++) { @@ -152,7 +191,10 @@ void UPP_SetDefault(int pui_default, int internal_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; diff --git a/UPP/Core/UPP/upp_control.h b/UPP/Core/UPP/upp_control.h index 1cbcc53..5836033 100644 --- a/UPP/Core/UPP/upp_control.h +++ b/UPP/Core/UPP/upp_control.h @@ -10,6 +10,8 @@ #define _UPP_CONTROL_H #include "upp_defs.h" +#define to_float(_u16_, _coef_) ((float)_u16_/_coef_) + typedef struct { unsigned set_default_pui:1; ///< Выставить настройки ПУИ в дефолтные @@ -23,53 +25,66 @@ typedef struct }UPP_FuncCalls_t; +typedef struct +{ + uint16_t PhaseSequence; ///< Последовательность фаз todo + uint16_t PhaseNumber; ///< [Количество] + uint16_t U; ///< [В x 10] + uint16_t U_deviation_plus; ///< [Проценты x 100] + uint16_t U_deviation_minus; ///< [Проценты x 100] + uint16_t F; ///< [Гц x 100] + uint16_t F_deviation_plus; ///< [Проценты x 100] + uint16_t F_deviation_minus; ///< [Проценты x 100] + uint16_t I; ///< [Амперы x 10] +}UPP_ParamsNominal_t; + +typedef struct +{ + uint16_t TemperatureWarn; ///< Предупредительный порог температуры [Градусы x 100] + uint16_t TemperatureErr; ///< Аварийный порог температуры [Градусы x 100] +}UPP_ParamsSetpoints_t; + typedef struct { struct { - uint16_t mean_alpha; ///< Коэф альфа x10000 для эксп. фильтра Umean, Imean, Fmean + uint16_t mean_alpha; ///< Коэф альфа для усредняющего эксп. фильтра [0..1 x 65535] }pm; - struct - { - uint16_t PhaseNumber; ///< Количество - uint16_t U; ///< В x 10 - uint16_t U_deviation_plus; ///< Проценты x 100 - uint16_t U_deviation_minus; ///< Проценты x 100 - uint16_t F; ///< Гц x 100 - uint16_t F_deviation_plus; ///< Проценты x 100 - uint16_t F_deviation_minus; ///< Проценты x 100 - uint16_t I; ///< Амперы x 10 - }nominal; + UPP_ParamsNominal_t nominal; + UPP_ParamsSetpoints_t setpoints; /* Параметры АЦП */ struct { - uint16_t ADC_Max[4]; ///< В x 10 - uint16_t ADC_Zero[4]; ///< Кванты АЦП + uint16_t ADC_Max[4]; ///< Величина в единицах измерения при АЦП = 4095 [В или А x 10] + uint16_t ADC_Zero[4]; ///< Кванты АЦП когда на входе ноль }adc; /* Параметры ШИМ */ struct { uint16_t PhaseMask; ///< Битовяя маска на какие фазы подавать ШИМ: 0 бит - a, 1 бит - b, 2 бит - c - uint16_t Frequency; ///< Частота ШИМ для пачки импульсов на тиристоры - uint16_t PulseNumber; ///< Количесво импульсов в пачке + uint16_t Frequency; ///< Частота ШИМ для пачки импульсов на тиристоры [Герцы] + uint16_t PulseNumber; ///< Количесво импульсов в пачке [Количество] }pwm; /* Параметры Угла */ struct { - uint16_t Hysteresis; ///< Гистерезис для определения перехода через ноль - uint16_t DebouneCouner; ///< Защита от дребезга: через сколько тактов снова начать фиксировать переход через ноль + uint16_t Hysteresis; ///< Гистерезис для определения перехода через ноль [Проценты x 100] + uint16_t DebouneCouner; ///< Защита от дребезга: через сколько тактов снова начать фиксировать переход через ноль [Количество] }zc; /* Параметры Угла */ struct { - uint16_t Angle_Max; ///< Максимальный угол открытия тиристора - uint16_t Angle_Min; ///< Минимальный угол открытия тиристора + uint16_t Angle_Max; ///< Максимальный угол открытия тиристора [0..1 x 65535] + uint16_t Angle_Min; ///< Минимальный угол открытия тиристора [0..1 x 65535] + uint16_t PID_Kp; ///< Пропорциональный коэфициент ПИ регулятора угла [x 1000] + uint16_t PID_Ki; ///< Интегральный коэфициент ПИ регулятора угла [x 1000] + uint16_t PID_Kd; ///< Интегральный коэфициент ПИ регулятора угла [x 1000] }angle; diff --git a/UPP/Core/UPP/upp_errors.c b/UPP/Core/UPP/upp_errors.c index 02ebc29..ad9b482 100644 --- a/UPP/Core/UPP/upp_errors.c +++ b/UPP/Core/UPP/upp_errors.c @@ -1,13 +1,173 @@ /** ****************************************************************************** * @file upp_errors.c -* @brief Ошибки УПП и их обработка +* @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) { // Пока нет ошибки @@ -38,7 +198,20 @@ static UPP_ErrorType_t UPP_SelectCommonError(void) return best; } -void UPP_ErrorsHandle(void) + +static int setError(int condition, int flag, int *timer, int delay) { - errors.common = UPP_SelectCommonError(); + if (condition) { + if (*timer < delay) + (*timer)++; + else + flag = 1; + } else { + if (*timer > 0) + (*timer)--; + else + flag = 0; + } + + return flag; } \ No newline at end of file diff --git a/UPP/Core/UPP/upp_errors.h b/UPP/Core/UPP/upp_errors.h index ac04ca6..dfafbab 100644 --- a/UPP/Core/UPP/upp_errors.h +++ b/UPP/Core/UPP/upp_errors.h @@ -64,36 +64,37 @@ typedef struct struct { /* Програмные ошибки */ - unsigned Internal_1:1; ///< Внутренняя неисправность УПП 1 - unsigned Internal_2:1; ///< Внутренняя неисправность УПП 2 - unsigned Internal_3:1; ///< Внутренняя неисправность УПП 3 - unsigned Internal_4:1; ///< Внутренняя неисправность УПП 4 - unsigned Internal_5:1; ///< Внутренняя неисправность УПП 5 - unsigned Internal_6:1; ///< Внутренняя неисправность УПП 6 + unsigned Internal_1:1; ///< Ошибка 1: Внутренняя неисправность УПП 1 + unsigned Internal_2:1; ///< Ошибка 2: Внутренняя неисправность УПП 2 + unsigned Internal_3:1; ///< Ошибка 3: Внутренняя неисправность УПП 3 + unsigned Internal_4:1; ///< Ошибка 4: Внутренняя неисправность УПП 4 + unsigned Internal_5:1; ///< Ошибка 5: Внутренняя неисправность УПП 5 + unsigned Internal_6:1; ///< Ошибка 6: Внутренняя неисправность УПП 6 /* Ошибки по питанию */ - unsigned Power_Digit_5V:1; ///< Неисправность цифрового источника питания (5 В) - unsigned Power_24V:1; ///< Неисправность источника питания 24 В - unsigned Power_Analog_5V:1; ///< Неисправность аналогового источника питания микроконтроллера (± 5 В) - unsigned Power_SCI_5V:1; ///< Неисправность источника питания последовательных интерфейсов микроконтроллера (5 В) - unsigned Power_DIO_24V:1; ///< Неисправность источника питания дискретных входов/выходов (24 В) + unsigned Power_Digit_5V:1; ///< Ошибка 7: Неисправность цифрового источника питания (5 В) + unsigned Power_24V:1; ///< Ошибка 8: Неисправность источника питания 24 В + unsigned Power_Analog_5V:1; ///< Ошибка 9: Неисправность аналогового источника питания микроконтроллера (± 5 В) + unsigned Power_SCI_5V:1; ///< Ошибка 10: Неисправность источника питания последовательных интерфейсов микроконтроллера (5 В) + unsigned Power_DIO_24V:1; ///< Ошибка 11: Неисправность источника питания дискретных входов/выходов (24 В) /* Ошибки по допустимым пределам Наряжений/Токов/Температуры */ - unsigned OverCurrent:1; ///< Ток выше допустимого (см. Imax и TiMax в @ref UPP_PUI_Params_t) - unsigned OverVoltage:1; ///< Напряжение сети выше допустимого (см. Umах в @ref UPP_PUI_Params_t) - unsigned OverTemperature:1; ///< Температура выше допустимой (плюс 85 °C) - unsigned UnderVoltage:1; ///< Напряжение сети ниже допустимого (см. Umin в @ref UPP_PUI_Params_t) + unsigned OverCurrent:1; ///< Ошибка 12: Ток выше допустимого (см. Imax и TiMax в @ref UPP_PUI_Params_t) + unsigned OverVoltage:1; ///< Ошибка 13: Напряжение сети выше допустимого (см. Umах в @ref UPP_PUI_Params_t) + unsigned OverTemperature:1; ///< Ошибка 14: Температура выше допустимой (плюс 85 °C) + unsigned UnderVoltage:1; ///< Ошибка 15: Напряжение сети ниже допустимого (см. Umin в @ref UPP_PUI_Params_t) /* Ошибки по обрывам фаз */ - unsigned LossPhaseA:1; ///< Обрыв фазы A (см. Imin в @ref UPP_PUI_Params_t) - unsigned LossPhaseB:1; ///< Обрыв фазы B (см. Imin в @ref UPP_PUI_Params_t) - unsigned LossPhaseC:1; ///< Обрыв фазы C (см. Imin в @ref UPP_PUI_Params_t) + unsigned LossPhaseAll:1; ///< Ошибка 16: Обрыв трёх фаз (см. Imin в @ref UPP_PUI_Params_t) + unsigned LossPhaseA:1; ///< Ошибка 17: Обрыв фазы A (см. Imin в @ref UPP_PUI_Params_t) + unsigned LossPhaseB:1; ///< Ошибка 18: Обрыв фазы B (см. Imin в @ref UPP_PUI_Params_t) + unsigned LossPhaseC:1; ///< Ошибка 19: Обрыв фазы C (см. Imin в @ref UPP_PUI_Params_t) /* Другие ошибки */ - unsigned LongStart:1; ///< Затянутый пуск (ток не спадает за установленное время) (см. Tdelay в @ref UPP_PUI_Params_t) - unsigned Interlace:1; ///< Неправильный порядок чередования фаз (см. Interlace в @ref UPP_PUI_Params_t) - unsigned OverFrequency:1; ///< Частота сети выше допустимой - unsigned UnderFrequency:1; ///< Частота сети ниже допустимой + unsigned LongStart:1; ///< Ошибка 20: Затянутый пуск (ток не спадает за установленное время) (см. Tdelay в @ref UPP_PUI_Params_t) + unsigned Interlace:1; ///< Ошибка 21: Неправильный порядок чередования фаз (см. Interlace в @ref UPP_PUI_Params_t) + unsigned OverFrequency:1; ///< Ошибка 22: Частота сети выше допустимой + unsigned UnderFrequency:1; ///< Ошибка 23: Частота сети ниже допустимой }err; }pui; @@ -104,6 +105,39 @@ typedef struct uint64_t all; struct { + unsigned uamp_max:1; + unsigned uamp_min:1; + unsigned iamp_max:1; + unsigned iamp_min:1; + + unsigned ic_max:1; + unsigned ic_min:1; + unsigned ib_max:1; + unsigned ib_min:1; + unsigned ia_max:1; + unsigned ia_min:1; + + unsigned uba_max:1; + unsigned uba_min:1; + unsigned uac_max:1; + unsigned uac_min:1; + unsigned ubc_max:1; + unsigned ubc_min:1; + + unsigned fba_max:1; + unsigned fba_min:1; + unsigned fac_max:1; + unsigned fac_min:1; + unsigned fbc_max:1; + unsigned fbc_min:1; + + + unsigned temp_warn:1; + unsigned temp_err:1; + + unsigned longstart:1; + unsigned interlance:3; + unsigned slow_calc_overrun:1; }err; }f; @@ -120,6 +154,6 @@ typedef struct }UPP_Errors_t; extern UPP_Errors_t errors; -void UPP_ErrorsHandle(void); +void UPP_Errors_Handle(void); #endif //_UPP_ERRORS_H \ No newline at end of file diff --git a/UPP/Core/UPP/upp_main.c b/UPP/Core/UPP/upp_main.c index 6ca39aa..c039738 100644 --- a/UPP/Core/UPP/upp_main.c +++ b/UPP/Core/UPP/upp_main.c @@ -9,7 +9,7 @@ #include "tim.h" UPP_t upp; -float alpha_dbg = 0.5; +float iref_dbg = 0; // ОСНОВНОЙ ЦИКЛ main.c /** @@ -52,73 +52,84 @@ int UPP_PreWhile(void) */ int UPP_While(void) { - // если ошибка вызываем СТОП - if(errors.pui.all) + if(upp.pm.f.runSlow) { - upp.call->stop = 1; - } - // иначе снимаем СТОП + // если ошибка вызываем СТОП + if(errors.pui.all) + { + upp.call->stop = 0; + } + // иначе снимаем СТОП + else + { + upp.call->stop = 0; + } + if (upp.call->stop) + upp.workmode = WM_Error; + + // Сброс на дефолтные по запросу + if(upp.call->set_default_pui) + { + UPP_SetDefault(1, 0); + } + if(upp.call->set_default_internal) + { + UPP_SetDefault(0, 1); + } + + PowerMonitor_SlowCalc(&upp.pm); + + + // Если СТОП - переходим в ошибку + // Автомат состояний УПП + switch(upp.workmode) + { + case WM_Ready: + // если пришла команда на запуск + if (upp.call->go) + { + upp.workmode = WM_Running; + Angle_PID_Reset(&upp.hangle); + upp.StartTick = local_time(); + } + break; + + case WM_Running: + // если пришла команда на остановку + if (!upp.call->go) + upp.workmode = WM_Ready; + + // Регулирование тиристоров + Angle_PID(&upp.hangle, iref_dbg, upp.pm.measured.final.Iamp); + + // если слишком долгий запуск + if((local_time() - upp.StartTick) > (upp.PUI.params->Tdelay*1000)) + { + errors.pui.err.LongStart = 1; + } + break; + + case WM_Error: + if(errors.common == Err_None) + upp.workmode = WM_Ready; + + PWM_Stop(&upp.hpwm, 0, 1); // Останавливаем ВЕСЬ ШИМ + break; + + case WM_Done: + PWM_Stop(&upp.hpwm, 0, 1); // Останавливаем ВЕСЬ ШИМ + break; + + default: + break; + } + + upp.pm.f.runSlow = 0; + }//if(upp.pm.f.runSlow) else { - upp.call->stop = 0; - } - // Сброс на дефолтные по запросу - if(upp.call->set_default_pui) - { - UPP_SetDefault(1, 0); - } - if(upp.call->set_default_internal) - { - UPP_SetDefault(0, 1); - } - - - - - PowerMonitor_SlowHandle(&upp.pm); - // Если СТОП - переходим в ошибку - if (upp.call->stop) - upp.workmode = WM_Error; - // Автомат состояний УПП - switch(upp.workmode) - { - case WM_Ready: - // если пришла команда на запуск - if (upp.call->go) - { - upp.workmode = WM_Running; - upp.StartTick = local_time(); - } - break; - case WM_Running: - // если пришла команда на остановку - if (!upp.call->go) - upp.workmode = WM_Ready; - - // если слишком долгий запуск - if((local_time() - upp.StartTick) > (upp.PUI.params->Tdelay*1000)) - { - errors.pui.err.LongStart = 1; - } - break; - - case WM_Error: - if(errors.common == Err_None) - upp.workmode = WM_Ready; - - PWM_Stop(&upp.hpwm, 0, 1); // Останавливаем ВЕСЬ ШИМ - break; - - case WM_Done: - PWM_Stop(&upp.hpwm, 0, 1); // Останавливаем ВЕСЬ ШИМ - break; - - default: - break; } - - return 0; } @@ -131,7 +142,7 @@ void UPP_Tick(void) { if(upp.workmode == WM_Not_Init) return; - UPP_ErrorsHandle(); + UPP_Errors_Handle(); UPP_Control_InternalParams(); } @@ -143,7 +154,7 @@ void UPP_ADC_Handle(void) { BenchTime_Start(BT_ADC, angletim.Instance->CNT, HAL_MAX_DELAY); - PowerMonitor_Handle(&upp.pm); + PowerMonitor_FastCalc(&upp.pm); for(int phase = 0; phase < 3; phase++) { @@ -157,7 +168,7 @@ void UPP_ADC_Handle(void) UPP_HalfWave_t curr_halfwave = ZC_GetHalfWave(&upp.pm.zc, phase); PWM_SetHalfWave(&upp.hpwm, phase, curr_halfwave); // Начинаем отсчитывать угол - Angle_Start(&upp.hangle, phase, alpha_dbg, 10); + Angle_Start(&upp.hangle, phase, 10); } } } diff --git a/UPP/Core/UPP/upp_main.h b/UPP/Core/UPP/upp_main.h index 976e2f3..c5c45c8 100644 --- a/UPP/Core/UPP/upp_main.h +++ b/UPP/Core/UPP/upp_main.h @@ -17,8 +17,6 @@ #include "upp_status.h" // статус упп #include "upp_control.h" // управление упп -extern float alpha_dbg; - typedef struct {