diff --git a/MATLAB/MCU_STM32_Matlab/Drivers/STM32_SIMULINK/stm32_matlab_adc.h b/MATLAB/MCU_STM32_Matlab/Drivers/STM32_SIMULINK/stm32_matlab_adc.h index a0f7b24..c837ef3 100644 --- a/MATLAB/MCU_STM32_Matlab/Drivers/STM32_SIMULINK/stm32_matlab_adc.h +++ b/MATLAB/MCU_STM32_Matlab/Drivers/STM32_SIMULINK/stm32_matlab_adc.h @@ -9,7 +9,7 @@ #endif #ifdef STM32F4 -#define ADC_NOISE_LSB 10 // Шум в LSB (квантах АЦП) +#define ADC_NOISE_LSB 3 // Шум в LSB (квантах АЦП) #endif /////////////////////////////---STRUCTURES---/////////////////////////// diff --git a/MATLAB/MCU_Wrapper/mcu_wrapper_conf.h b/MATLAB/MCU_Wrapper/mcu_wrapper_conf.h index ab4f3d5..8108130 100644 --- a/MATLAB/MCU_Wrapper/mcu_wrapper_conf.h +++ b/MATLAB/MCU_Wrapper/mcu_wrapper_conf.h @@ -59,7 +59,7 @@ #define OUT_PORT_NUMB 3 #define THYR_PORT_1_WIDTH 6 -#define PM_PORT_2_WIDTH 16 +#define PM_PORT_2_WIDTH 32 #define OUT_PORT_3_WIDTH 16 // INPUT/OUTPUTS PARAMS END diff --git a/MATLAB/app_wrapper/app_io.c b/MATLAB/app_wrapper/app_io.c index 97e301b..cd56554 100644 --- a/MATLAB/app_wrapper/app_io.c +++ b/MATLAB/app_wrapper/app_io.c @@ -32,25 +32,31 @@ void Write_PowerMonitor(real_T* Buffer, int ind_port) { int nn = 0; for (int i = 0; i < 3; i++) - { - WriteOutputArray(upp.pm.U[i], ind_port, nn++); + { //0-2 + WriteOutputArray(upp.pm.measured.Ureal[i], ind_port, nn++); } for (int i = 0; i < 3; i++) - { + { //3-5 WriteOutputArray(upp.pm.zc.Channel[i].HalfWave, ind_port, nn++); } for (int i = 0; i < 3; i++) - { - WriteOutputArray(upp.pm.F[i], ind_port, nn++); + { //6-8 + WriteOutputArray(upp.pm.measured.F[i], ind_port, nn++); } for (int i = 0; i < 3; i++) - { - WriteOutputArray(upp.pm.I[i], ind_port, nn++); + { //9-11 + WriteOutputArray(upp.pm.measured.Ireal[i], ind_port, nn++); } for (int i = 0; i < 2; i++) - { - WriteOutputArray(upp.pm.T[i], ind_port, nn++); + { //12-13 + WriteOutputArray(upp.pm.measured.T[i], ind_port, nn++); } + { //14-16 + WriteOutputArray(upp.pm.measured.U_mean, ind_port, nn++); + WriteOutputArray(upp.pm.measured.I_mean, ind_port, nn++); + WriteOutputArray(upp.pm.measured.F_mean, ind_port, nn++); + } + } /** * @brief Функция для записи входов в приложение МК diff --git a/MATLAB/upp_init.m b/MATLAB/upp_init.m index 7618676..15834cb 100644 --- a/MATLAB/upp_init.m +++ b/MATLAB/upp_init.m @@ -1,7 +1,7 @@ clear all Ts = 5e-6; -Vnom = 380; +Vnom = 690; Fnom = 50; Temperature1 = 2.22; % 20 градусов diff --git a/MATLAB/upp_r2023.slx b/MATLAB/upp_r2023.slx index 1685338..d0868f1 100644 Binary files a/MATLAB/upp_r2023.slx and b/MATLAB/upp_r2023.slx differ diff --git a/UPP/AllLibs/MyLibs b/UPP/AllLibs/MyLibs index 99652a9..9bff9ad 160000 --- a/UPP/AllLibs/MyLibs +++ b/UPP/AllLibs/MyLibs @@ -1 +1 @@ -Subproject commit 99652a9ad5ea0686ad9242b165508a9d92ac80a1 +Subproject commit 9bff9ad44dd625819ef654e98ca351d5bc5568a9 diff --git a/UPP/Core/Configs/modbus_data.c b/UPP/Core/Configs/modbus_data.c index b1cb836..ce6572e 100644 --- a/UPP/Core/Configs/modbus_data.c +++ b/UPP/Core/Configs/modbus_data.c @@ -23,7 +23,7 @@ #include "modbus_devid.h" /* DEFINE DATA FOR MODBUS */ -MB_DataStructureTypeDef MB_DATA = {0};; ///< Coils & Registers +MB_DataStructureTypeDef MB_DATA = {0}; ///< Coils & Registers MB_DataInternalTypeDef MB_INTERNAL; /** diff --git a/UPP/Core/Configs/mylibs_config.h b/UPP/Core/Configs/mylibs_config.h index a9dbd71..4838d99 100644 --- a/UPP/Core/Configs/mylibs_config.h +++ b/UPP/Core/Configs/mylibs_config.h @@ -65,7 +65,7 @@ //#define FILTER_MEDIAN_MAX_SIZE ///< Максимальный размер окна медианного фильтра (по умолчанию 5) //#define FILTER_AVERAGE_MAX_SIZE ///< Максимальный размер окна усредняющего фильтра (по умолчанию 8) //#define FILTER_POLY_MAX_ORDER ///< Максимальный порядок полинома (по умолчанию 4) - +#define FILTERS_DISABLE_MOVING_AVERAGE /** GEN_CONFIG * @} */ @@ -96,9 +96,12 @@ */ -//#define BENCH_TIME_ENABLE ///< Включить бенч времени -#define BENCH_TIME_MAX_CHANNELS 16 ///< Максимальное количество каналов измерения +#define BENCH_TIME_ENABLE ///< Включить бенч времени +#define BENCH_TIME_MAX_CHANNELS 5 ///< Максимальное количество каналов измерения +#define BT_ADC 0 +#define BT_PWM 1 +#define BT_SYSTICK 2 /** GEN_CONFIG * @} */ @@ -133,7 +136,7 @@ extern float dbg[16]; #define INCLUDE_TRACKERS_LIB ///< Подключить библиотеку с трекерами //#define INCLUDE_TRACE_LIB ///< Подключить библиотеку с трейсами #define INCLUDE_GENERAL_PERIPH_LIBS ///< Подключить библиотеку с периферией -//#define INCLUDE_BENCH_TIME ///< Подключить библиотеку с бенчмарком времени +#define INCLUDE_BENCH_TIME ///< Подключить библиотеку с бенчмарком времени #define INCLUDE_FILTERS ///< Подключить библиотеку с фильтрами #endif //MATLAB diff --git a/UPP/Core/Configs/upp_config.h b/UPP/Core/Configs/upp_config.h index 706225f..8e26bda 100644 --- a/UPP/Core/Configs/upp_config.h +++ b/UPP/Core/Configs/upp_config.h @@ -18,12 +18,12 @@ #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 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 @@ -34,6 +34,19 @@ * @brief Дефолтные параметры для внешней памяти. Они применятся по команде или по ошибке * @{ */ +/* Параметри мониторинга сети */ +#define PM_EXP_ALPHA_COEF_DEFAULT 0.01 + +/* Номинальные параметры */ +#define NOM_PHASE_NUMB 3 +#define NOM_U_V_DEFAULT 690 +#define NOM_U_DEVIATION_PLUS_PERCENT_DEFAULT 6 +#define NOM_U_DEVIATION_MINUS_PERCENT_DEFAULT 10 +#define NOM_F_HZ_DEFAULT 50 +#define NOM_F_DEVIATION_PLUS_PERCENT_DEFAULT 5 +#define NOM_F_DEVIATION_MINUS_PERCENT_DEFAULT 5 +#define NOM_I_A_DEFAULT 5 + /* Параметры ПУИ */ #define PUI_Iref_PERCENT_DEFAULT 150 #define PUI_Tnt_MS_DEFAULT 300 @@ -52,8 +65,8 @@ #define ADC_I_ZERO_DEFAULT 2048 /* Параметры определения перехода через ноль */ -#define ZERO_CROSS_HYSTERESIS_V_DEFAULT 10.0 -#define ZERO_CROSS_DEBOUNCE_10US_DEFAULT 2.5*100 // (2.5 * 100 = 2.5 мс) +#define ZERO_CROSS_HYSTERESIS_PERCENT_DEFAULT 2.0 +#define ZERO_CROSS_DEBOUNCE_10US_DEFAULT 2*100 // (2.5 * 100 = 2.5 мс) /* Параметры ШИМ для тиристоров */ #define PWM_THYR_FREQUENCY_HZ_DEFAULT 20000 @@ -70,11 +83,11 @@ * @brief Параметры устанавливаемые на этапе компиляции. Без перепрошивки их не поменять * @{ */ -#define PM_U_NOM_V 690 -#define PM_I_NOM_V 5 -#define PM_F_NOM_HZ 50 +/* Периоды вызова всякого */ +#define PM_ADC_PERIOD_US 10 ///< Период опроса АЦП в мкс +#define PM_SLOW_PERIOD_10US 50 ///< Период обновление медленных расчетов в 10мкс +#define PM_TEMP_PERIOD_10US 5000 ///< Период обновление датчиков температуры в 10мкс -#define PM_ADC_PERIOD_MKS 10 ///< Период опроса АЦП в мкс /* Частоты таймеров в МГц*/ #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 5d9ae19..b1ce9bd 100644 --- a/UPP/Core/Configs/upp_defs.h +++ b/UPP/Core/Configs/upp_defs.h @@ -29,7 +29,8 @@ typedef enum { WM_Not_Init = 0, ///< УПП не инициализирован WM_Ready = 1, ///< УПП в готовности WM_Running = 2, ///< УПП в работе, управляет тиристорами - WM_Error = 3, ///< УПП в аварии + WM_Done = 3, ///< УПП закончил свою работу + WM_Error = 4, ///< УПП в аварии } UPP_WorkModeType_t; /** @@ -147,7 +148,8 @@ typedef struct { * @brief Дефайны УПП которые используютяс исключительно внутри программы * @{ */ -#define ANGLE_PERIOD_MS (((float)1/(PM_F_NOM_HZ*2))*1000) +#define ANGLE_PERIOD_MS(_freq_) (((float)1/(_freq_*2))*1000) + /** * @brief Состояния полуволны */ diff --git a/UPP/Core/PowerMonitor/adc_tools.c b/UPP/Core/PowerMonitor/adc_tools.c index 2a8b7eb..3ac7560 100644 --- a/UPP/Core/PowerMonitor/adc_tools.c +++ b/UPP/Core/PowerMonitor/adc_tools.c @@ -156,7 +156,7 @@ HAL_StatusTypeDef ADC_Handle(ADC_Periodic_t *adc) { ADC_Coefs_t *coefs = &adc->Coefs[i]; data[i] = ((float)(raw[i])-coefs->lZero) * coefs->vMax / (coefs->lMax-coefs->lZero); - ADC_UpdateStatistics(adc, i, ADC_LEVEL_AC); +// ADC_UpdateStatistics(adc, i, ADC_LEVEL_AC); } // Фильтрация от шумов для всех каналов @@ -169,19 +169,15 @@ HAL_StatusTypeDef ADC_Handle(ADC_Periodic_t *adc) } } - // Преобразования температуры по таблице for (int i = ADC_TEMP_CHANNELS_START; i < ADC_NUMB_OF_CHANNELS; i++) { data[i] = Filter_Process(&adc->temp_map[i-ADC_TEMP_CHANNELS_START], raw[i]); - ADC_UpdateStatistics(adc, i, ADC_LEVEL_BASE); +// ADC_UpdateStatistics(adc, i, ADC_LEVEL_BASE); } - - - - - adc->f.DataReady = 1; + if(Filter_isDataReady(&adc->filter[0])) + adc->f.DataReady = 1; return HAL_OK; } @@ -221,7 +217,7 @@ void ADC_UpdateStatistics(ADC_Periodic_t *adc, uint8_t channel, ADC_StatLevel_t } // Накопление для Avg/RMS - stat->Sum += value; + stat->Sum += ABS(value); stat->SumSquares += value * value; stat->SampleCount++; diff --git a/UPP/Core/PowerMonitor/adc_tools.h b/UPP/Core/PowerMonitor/adc_tools.h index 7a47e57..9e7d307 100644 --- a/UPP/Core/PowerMonitor/adc_tools.h +++ b/UPP/Core/PowerMonitor/adc_tools.h @@ -67,7 +67,7 @@ typedef struct typedef enum { - ADC_LEVEL_DISABLE=0, ///< Базовая статистика - Max/Min + ADC_LEVEL_DISABLE=0, ///< Статистика отключена ADC_LEVEL_BASE, ///< Базовая статистика - Max/Min ADC_LEVEL_AC, ///< Статистика для переменных сигналов - AVG, RMS }ADC_StatLevel_t; diff --git a/UPP/Core/PowerMonitor/power_monitor.c b/UPP/Core/PowerMonitor/power_monitor.c index ff8c982..fa0e51e 100644 --- a/UPP/Core/PowerMonitor/power_monitor.c +++ b/UPP/Core/PowerMonitor/power_monitor.c @@ -12,9 +12,14 @@ HAL_StatusTypeDef PowerMonitor_Init(PowerMonitor_t *hpm) { + if(hpm == NULL) + return HAL_ERROR; + + /* Инициализация АЦП */ if(ADC_Init(&hpm->adc, &adc_tim, &hadc3) != HAL_OK) return HAL_ERROR; + /* Инициализация каналов АЦП */ 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], @@ -40,9 +45,11 @@ HAL_StatusTypeDef PowerMonitor_Init(PowerMonitor_t *hpm) return HAL_ERROR; + /* Инициализация алгоритма перехода через ноль */ if(ZC_Init(&hpm->zc, 3, (float)MB_INTERNAL.param.zc.Hysteresis/100, MB_INTERNAL.param.zc.DebouneCouner) != HAL_OK) return HAL_ERROR; + /* Инициализация каналов алгоритма перехода через ноль */ if(ZC_ConfigChannel(&hpm->zc, U_BA, ZC_BOTH_EDGES) != HAL_OK) return HAL_ERROR; if(ZC_ConfigChannel(&hpm->zc, U_AC, ZC_BOTH_EDGES) != HAL_OK) @@ -50,41 +57,136 @@ HAL_StatusTypeDef PowerMonitor_Init(PowerMonitor_t *hpm) if(ZC_ConfigChannel(&hpm->zc, U_BC, ZC_BOTH_EDGES) != HAL_OK) return HAL_ERROR; + + /* Инициализация экпоненциального фильтра медленного алга */ + for(int i = 0; i < 3; i++) + { + if(FilterExp_Init(&hpm->measured.exp[i], (float)MB_INTERNAL.param.pm.mean_alpha/65535)) + return HAL_ERROR; + Filter_Start(&hpm->measured.exp[i]); + } + + /* Инициализация среднего фильтра медленного алга */ + for(int i = 0; i < ADC_NUMB_OF_REGULAR_CHANNELS; i++) + { + if(FilterAverage_Init(&hpm->measured.avg[i], PM_SLOW_PERIOD_10US, FILTER_MODE_DEFAULT)) + return HAL_ERROR; + + Filter_Start(&hpm->measured.avg[i]); + } + for(int i = 0; i < ADC_NUMB_OF_T_CHANNELS; i++) + { + if(FilterAverage_Init(&hpm->measured.avg[ADC_TEMP_CHANNELS_START+i], PM_TEMP_PERIOD_10US, FILTER_MODE_DEFAULT)) + return HAL_ERROR; + + Filter_Start(&hpm->measured.avg[ADC_TEMP_CHANNELS_START+i]); + } + return HAL_OK; } HAL_StatusTypeDef PowerMonitor_Start(PowerMonitor_t *hpm) { - if(ADC_Start(&hpm->adc, PM_ADC_PERIOD_MKS) != HAL_OK) - return HAL_ERROR; + if(hpm == NULL) + return HAL_ERROR; + + if(ADC_Start(&hpm->adc, PM_ADC_PERIOD_US) != HAL_OK) + return HAL_ERROR; return HAL_OK; } +void PowerMonitor_SlowHandle(PowerMonitor_t *hpm) +{ + if(hpm == NULL) + return; + if(!hpm->f.runSlow) + return; + hpm->f.runSlow = 0; + PowerMonitor_Measured_t *meas = &hpm->measured; + + meas->Uslow[U_BC] = -meas->Uslow[U_BA] - meas->Uslow[U_AC]; + meas->Islow[I_B] = -meas->Islow[I_A] - meas->Islow[I_C]; + + float umean = 0; + float imean = 0; + float fmean = 0; + for(int i = 0; i < 3; i++) + { + umean += ABS(meas->Uslow[i]); + imean += ABS(meas->Islow[i]); + fmean += ABS(meas->F[i]); + } + umean /=3; + imean /=3; + fmean /=3; + + meas->U_mean = Filter_Process(&meas->exp[0], umean); + meas->I_mean = Filter_Process(&meas->exp[1], imean); + meas->F_mean = Filter_Process(&meas->exp[2], fmean); +} void PowerMonitor_Handle(PowerMonitor_t *hpm) { + if(hpm == NULL) + return; /* Считываем АЦП */ - static uint32_t last_zc_cnt[ADC_NUMB_OF_U_CHANNELS] = {0}; ADC_Handle(&hpm->adc); - hpm->U[U_BA] = hpm->adc.Data[ADC_CHANNEL_UBA]; - hpm->U[U_AC] = hpm->adc.Data[ADC_CHANNEL_UAC]; - hpm->U[U_BC] = -hpm->U[U_BA] - hpm->U[U_AC]; - hpm->I[I_C] = hpm->adc.Data[ADC_CHANNEL_IC]; - hpm->I[I_A] = hpm->adc.Data[ADC_CHANNEL_IA]; - hpm->I[I_B] = -hpm->I[I_A] - hpm->I[I_C]; + /* Заполняем величины */ + PowerMonitor_Measured_t *meas = &hpm->measured; + meas->Ureal[U_BA] = hpm->adc.Data[ADC_CHANNEL_UBA]; + meas->Ureal[U_AC] = hpm->adc.Data[ADC_CHANNEL_UAC]; + meas->Ureal[U_BC] = -meas->Ureal[U_BA] - meas->Ureal[U_AC]; + meas->Ireal[I_C] = hpm->adc.Data[ADC_CHANNEL_IC]; + meas->Ireal[I_A] = hpm->adc.Data[ADC_CHANNEL_IA]; + meas->Ireal[I_B] = -meas->Ireal[I_A] - meas->Ireal[I_C]; + meas->T[TEMP_1] = hpm->adc.Data[ADC_CHANNEL_TEMP1]; + meas->T[TEMP_2] = hpm->adc.Data[ADC_CHANNEL_TEMP2]; - hpm->T[TEMP_1] = hpm->adc.Data[ADC_CHANNEL_TEMP1]; - hpm->T[TEMP_2] = hpm->adc.Data[ADC_CHANNEL_TEMP2]; - - ZC_ProcessAllChannels(&hpm->zc, hpm->U, usTick); + /* Преобразуем в относительные единицы (о.е.) */ for(int i = 0; i < 3; i++) { - - hpm->F[i] = ZC_GetFrequency(&hpm->zc, i) / 2; + meas->U[i] = 10*meas->Ureal[i]/MB_INTERNAL.param.nominal.U; + meas->I[i] = 10*meas->Ireal[i]/MB_INTERNAL.param.nominal.I; + } + + /* Ищем переход через ноль */ + ZC_ProcessAllChannels(&hpm->zc, meas->U, usTick); + for(int i = 0; i < 3; i++) + { + meas->F[i] = ZC_GetFrequency(&hpm->zc, i) / 2; + } + + /* Накопление Average для медленной фильтрации */ + meas->Uslow[U_BA] = Filter_Process(&meas->avg[0], meas->U[U_BA]); + meas->Uslow[U_AC] = Filter_Process(&meas->avg[1], meas->U[U_AC]); + meas->Islow[I_C] = Filter_Process(&meas->avg[2], meas->I[I_C]); + meas->Islow[I_A] = Filter_Process(&meas->avg[3], meas->I[I_A]); + meas->T[TEMP_1] = Filter_Process(&meas->avg[4], meas->T[TEMP_1]); + meas->T[TEMP_2] = Filter_Process(&meas->avg[5], meas->T[TEMP_2]); + + /* Запускаем медленную обработку через slow_period прерываний */ +// if(hpm->isr_cnt == PM_SLOW_PERIOD_10US) + /* Запускаем медленную когда фильтры среднего зациклились */ + if(Filter_isDataReady(&meas->avg[0])) + { + hpm->isr_cnt = 0; + if(!hpm->f.runSlow) + { + hpm->f.runSlow = 1; + } + else // если уже запущена - ставим overrun slow calc + { + errors.prvt.f.err.slow_calc_overrun = 1; + errors.prvt.cnt.slow_calc_overrun++; + } + } + else + { + hpm->isr_cnt++; } } \ No newline at end of file diff --git a/UPP/Core/PowerMonitor/power_monitor.h b/UPP/Core/PowerMonitor/power_monitor.h index 56bf1cd..3a0d378 100644 --- a/UPP/Core/PowerMonitor/power_monitor.h +++ b/UPP/Core/PowerMonitor/power_monitor.h @@ -13,14 +13,55 @@ typedef struct { - ADC_Periodic_t adc; - ZeroCross_Handle_t zc; - UPP_HalfWave_t CurrentHalfWave[3]; + unsigned runSlow:1; ///< Запустить медленный алгоритм в while(1) - float U[3]; - float F[3]; - float I[3]; - float T[2]; + unsigned isU:1; ///< Есть ли напряжение + unsigned isI:1; ///< Есть ли ток + + unsigned protectUmax:1; ///< Отработка защиты по макс. напряжению + unsigned protectUmin:1; ///< Отработка защиты по мак с. напряжению + unsigned protectImax:1; ///< Отработка защиты по макс. току + unsigned protectImin:1; ///< Отработка защиты по мин. току +}PowerMonitor_Flags_t; + + +typedef struct +{ + float U_mean; ///< Среднее Напряжение по трем фазам + float I_mean; ///< Средний Ток по трем фазам + float F_mean; ///< Средняя Частота по трем фазам + float Uslow[3]; ///< Напряжение от АЦП (в о.е.) + float Islow[3]; ///< Ток от АЦП (в о.е.) + + + float U[3]; ///< Напряжение от АЦП (в о.е.) + float I[3]; ///< Ток от АЦП (в о.е.) + float F[3]; ///< Частота от Zero Cross + float T[2]; ///< Температура от АЦП + + + float Ureal[3]; ///< Напряжение от АЦП + float Ireal[3]; ///< Ток от АЦП + + FilterExp_t exp[3]; ///< Фильтры для mean + FilterAverage_t avg[6]; ///< Фильтры для avg +}PowerMonitor_Measured_t; + +typedef struct +{ +}PowerMonitor_Filters_t; + +typedef struct +{ + ADC_Periodic_t adc; ///< Хендл периодического АЦП + ZeroCross_Handle_t zc; ///< Хендл перехода через ноль + PowerMonitor_Filters_t fltr; + PowerMonitor_Measured_t measured; ///< Измеренные/рассчитанные величины + PowerMonitor_Flags_t f; ///< Флаги мониторинга + + + uint32_t slow_period; + uint32_t isr_cnt; }PowerMonitor_t; extern PowerMonitor_t pm; @@ -28,6 +69,7 @@ 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); #endif /* _POWER_MONITOR_H_ */ diff --git a/UPP/Core/UPP/pwm_thyristors.c b/UPP/Core/UPP/pwm_thyristors.c index 2d6daba..25a7abc 100644 --- a/UPP/Core/UPP/pwm_thyristors.c +++ b/UPP/Core/UPP/pwm_thyristors.c @@ -15,6 +15,9 @@ static HAL_StatusTypeDef __PWM_SetOutputState(PWM_Channel_t *hCh, uint32_t state * @brief Инициализация ШИМ тиристоров. * @param hpwm Указатель на хендл ШИМ тиристоров * @return HAL Status. + * @details Инициализируется 6 структур на каждый канал ШИМ для тиристора. + * И одна dummy структура для безопасной инициализации неизвестной фазы. + * В конце запускаются все каналы ШИМ (с запрещенным выходом). */ HAL_StatusTypeDef PWM_Init(PWM_Handle_t *hpwm) { @@ -75,6 +78,7 @@ HAL_StatusTypeDef PWM_Init(PWM_Handle_t *hpwm) * @param hpwm Указатель на хендл ШИМ тиристоров * @param Phase На какой фазе надо запустить ШИМ * @return HAL Status. + * @details Переводит автомат канала ШИМ в состояние запуска ШИМ. */ HAL_StatusTypeDef PWM_Start(PWM_Handle_t *hpwm, UPP_Phase_t Phase) { @@ -91,6 +95,7 @@ HAL_StatusTypeDef PWM_Start(PWM_Handle_t *hpwm, UPP_Phase_t Phase) switch(hpwm->Phase[Phase]->State) { + // Если мы НЕ в режиме ожидание - ошибка case PWM_THYR_DISABLED: case PWM_THYR_TIM_START: case PWM_THYR_TIM_ACTIVE: @@ -103,7 +108,7 @@ HAL_StatusTypeDef PWM_Start(PWM_Handle_t *hpwm, UPP_Phase_t Phase) return HAL_OK; default: - return HAL_ERROR;; + return HAL_ERROR; } return HAL_ERROR; @@ -113,7 +118,11 @@ HAL_StatusTypeDef PWM_Start(PWM_Handle_t *hpwm, UPP_Phase_t Phase) * @brief Остановить ШИМ. * @param hpwm Указатель на хендл ШИМ тиристоров * @param Phase На какой фазе надо остановить ШИМ + * @param force_stop_all Принудительно остановить ВЕСЬ ШИМ * @return HAL Status. + * @details Переводит автомат канала ШИМ в состояние отключенного ШИМ и + * включает канал в режим форсированного неактивного выхода. + * При передаче 1 в force_stop_all, отключаются все каналы ШИМ и выдается дискрет на запрет ШИМ */ HAL_StatusTypeDef PWM_Stop(PWM_Handle_t *hpwm, UPP_Phase_t Phase, uint8_t force_stop_all) { @@ -148,6 +157,7 @@ HAL_StatusTypeDef PWM_Stop(PWM_Handle_t *hpwm, UPP_Phase_t Phase, uint8_t force_ * @brief Хендл ШИМ тиристоров. * @param hpwm Указатель на хендл ШИМ тиристоров * @return HAL Status. + * @details Автомат состояний, который определяет поведение каналов ШИМ */ HAL_StatusTypeDef PWM_Handle(PWM_Handle_t *hpwm) { @@ -165,22 +175,22 @@ HAL_StatusTypeDef PWM_Handle(PWM_Handle_t *hpwm) switch (hPhase->State) { - case PWM_THYR_DISABLED: + case PWM_THYR_DISABLED: // канал отключен __PWM_SetOutputState(hPhase, PWM_DISABLE); break; - case PWM_THYR_TIM_WAIT: + case PWM_THYR_TIM_WAIT: // канал ожидает команды __PWM_SetOutputState(hPhase, PWM_DISABLE); break; - case PWM_THYR_TIM_START: + case PWM_THYR_TIM_START: // начать ШИМ (пачка импульсов) __PWM_SetOutputState(hPhase, PWM_ENABLE); hPhase->PulseCnt = hpwm->Config.PulseNumber; hPhase->State = PWM_THYR_TIM_ACTIVE; hpwm->f.Running++; break; - case PWM_THYR_TIM_ACTIVE: + case PWM_THYR_TIM_ACTIVE: // управление пачкой импульсов ШИМ hPhase->PulseCnt--; if (hPhase->PulseCnt <= 0) { @@ -189,13 +199,13 @@ HAL_StatusTypeDef PWM_Handle(PWM_Handle_t *hpwm) } break; - case PWM_THYR_TIM_DONE: + case PWM_THYR_TIM_DONE: // пачка импульсов отправлена - отключение hPhase->State = PWM_THYR_TIM_WAIT; if(hpwm->f.Running) hpwm->f.Running--; break; - default: + default: // чзх __PWM_SetOutputState(hPhase, PWM_DISABLE); break; } @@ -204,7 +214,7 @@ HAL_StatusTypeDef PWM_Handle(PWM_Handle_t *hpwm) } /** - * @brief Установка частоты ШИМ. + * @brief Установка параметров ШИМ. * @param hpwm Указатель на хендл ШИМ тиристоров * @param Frequency Частота в ГЦ * @return HAL Status. @@ -213,16 +223,19 @@ HAL_StatusTypeDef PWM_SetConfig(PWM_Handle_t *hpwm, uint8_t PhaseMask, uint16_t { if(assert_upp(hpwm)) return HAL_ERROR; - if(hpwm->f.Running) + if(hpwm->f.Running) // Если есть активные каналы - ниче не меняем return HAL_BUSY; - HAL_TIM_Base_Stop(&hpwm1); + // Остановка таймера + HAL_TIM_Base_Stop_IT(&hpwm1); hpwm->Config.PhaseMask.all = PhaseMask; hpwm->Config.PulseNumber = PulseNumber; hpwm->Config.Frequency = Frequency; + // Высставление периодов __HAL_TIM_SET_AUTORELOAD(&hpwm1, TIM_FreqToTick(Frequency, PWM_TIM1_FREQ_MHZ)); __HAL_TIM_SET_AUTORELOAD(&hpwm2, TIM_FreqToTick(Frequency, PWM_TIM3_FREQ_MHZ)); + // Скважности 50/50 __HAL_TIM_SET_COMPARE(&hpwm1, PWM_CHANNEL_1, __HAL_TIM_GET_AUTORELOAD(&hpwm1)/2); __HAL_TIM_SET_COMPARE(&hpwm1, PWM_CHANNEL_2, __HAL_TIM_GET_AUTORELOAD(&hpwm1)/2); __HAL_TIM_SET_COMPARE(&hpwm1, PWM_CHANNEL_3, __HAL_TIM_GET_AUTORELOAD(&hpwm1)/2); @@ -230,6 +243,10 @@ HAL_StatusTypeDef PWM_SetConfig(PWM_Handle_t *hpwm, uint8_t PhaseMask, uint16_t __HAL_TIM_SET_COMPARE(&hpwm2, PWM_CHANNEL_5, __HAL_TIM_GET_AUTORELOAD(&hpwm2)/2); __HAL_TIM_SET_COMPARE(&hpwm2, PWM_CHANNEL_6, __HAL_TIM_GET_AUTORELOAD(&hpwm2)/2); + + // Сброс счетчиков таймера и запуск заного + __HAL_TIM_SET_COUNTER(&hpwm1, 0); + __HAL_TIM_SET_COUNTER(&hpwm2, 0); return HAL_TIM_Base_Start_IT(&hpwm1); } @@ -240,13 +257,13 @@ HAL_StatusTypeDef PWM_SetConfig(PWM_Handle_t *hpwm, uint8_t PhaseMask, uint16_t * @param Phase Для какой фазы надо установить полуволну * @param halfwave Какую полуволну установить * @return HAL Status. + * @details Меняет указатель канала фазы на канал соответствующей полуволны */ HAL_StatusTypeDef PWM_SetHalfWave(PWM_Handle_t *hpwm, UPP_Phase_t Phase, UPP_HalfWave_t halfwave) { if(assert_upp(hpwm)) return HAL_ERROR; - // Сбрасываем текущий канал PWM_Stop(hpwm, Phase, 0); @@ -315,39 +332,3 @@ static HAL_StatusTypeDef __PWM_SetOutputState(PWM_Channel_t *hCh, uint32_t state } return HAL_OK; } - - -/** - * @brief Установка полуволны для слежения. - * @param hpwm Указатель на хендл ШИМ тиристоров - * @param Phase Для какой фазы надо установить полуволну - * @param halfwave Какую полуволну установить - * @return HAL Status. - */ -UPP_HalfWave_t PWM_GetHalfWave(PWM_Handle_t *hpwm, UPP_Phase_t Phase) -{ - if(assert_upp(hpwm)) - return UPP_WAVE_UNKNOWED; - // Если канал дурацкий - возвращаем UNKNOWED - if (Phase >= 3) - { - return UPP_WAVE_UNKNOWED; - } - if (hpwm->Phase[Phase] == NULL || hpwm->Phase[Phase] == &hpwm->AllPhases[PHASE_UNKNOWN]) - return UPP_WAVE_UNKNOWED; - - - // Выставляем канал - if(hpwm->Phase[Phase] == &hpwm->AllPhases[Phase]) - { - return UPP_WAVE_POSITIVE; - } - else if(hpwm->Phase[Phase] == &hpwm->AllPhases[Phase+3]) - { - return UPP_WAVE_NEGATIVE; - } - else - { - return UPP_WAVE_UNKNOWED; - } -} \ No newline at end of file diff --git a/UPP/Core/UPP/pwm_thyristors.h b/UPP/Core/UPP/pwm_thyristors.h index 5908225..8780a92 100644 --- a/UPP/Core/UPP/pwm_thyristors.h +++ b/UPP/Core/UPP/pwm_thyristors.h @@ -96,8 +96,6 @@ HAL_StatusTypeDef PWM_Stop(PWM_Handle_t *hpwm, UPP_Phase_t Phase, uint8_t force_ HAL_StatusTypeDef PWM_SetConfig(PWM_Handle_t *hpwm, uint8_t PhaseMask, uint16_t Frequency, uint8_t PulseNumber); /* Установка полуволны для слежения. */ HAL_StatusTypeDef PWM_SetHalfWave(PWM_Handle_t *hpwm, UPP_Phase_t Phase, UPP_HalfWave_t halfwave); -/* Установка полуволны для слежения. */ -UPP_HalfWave_t PWM_GetHalfWave(PWM_Handle_t *hpwm, UPP_Phase_t Phase); /* Хендл ШИМ тиристоров. */ HAL_StatusTypeDef PWM_Handle(PWM_Handle_t *hpwm); diff --git a/UPP/Core/UPP/upp_control.c b/UPP/Core/UPP/upp_control.c index dec4727..d0265bd 100644 --- a/UPP/Core/UPP/upp_control.c +++ b/UPP/Core/UPP/upp_control.c @@ -12,7 +12,7 @@ static int __CheckSimpleParamF(float *paramDist, uint16_t paramSrc, float Coef); static int __CheckSimpleParamU32(uint32_t *paramDist, uint16_t paramSrc, float Coef); static int __CheckSimpleParamU16(uint16_t *paramDist, uint16_t paramSrc); static int __CheckSimpleParamU8(uint8_t *paramDist, uint16_t paramSrc, float Coef); -static int __AngleSetLimit(void); +static void __AngleSetLimit(void); /** * @brief Контроль внутренних параметров УПП. @@ -38,6 +38,8 @@ void UPP_Control_InternalParams(void) uint8_t pwm_phase_mask = upp.hpwm.Config.PhaseMask.all; uint16_t pwm_freq = upp.hpwm.Config.Frequency; uint8_t pwm_pulse_num = upp.hpwm.Config.PulseNumber; + // временная переменная для параметров Мониторинга сети + float pm_alpha = upp.pm.measured.exp[0].alpha; for(int i = 0; i < ADC_NUMB_OF_REGULAR_CHANNELS; i++) @@ -58,11 +60,11 @@ void UPP_Control_InternalParams(void) } // Параметры алгоритма перехода через ноль - if(__CheckSimpleParamF(&zc_hysteresis, MB_INTERNAL.param.zc.Hysteresis, 100)) + if(__CheckSimpleParamF(&zc_hysteresis, MB_INTERNAL.param.zc.Hysteresis, 10000)) { zc_update = 1; } - if(__CheckSimpleParamU16(&zc_debounce, MB_INTERNAL.param.zc.Hysteresis)) + if(__CheckSimpleParamU16(&zc_debounce, MB_INTERNAL.param.zc.DebouneCouner)) { zc_update = 1; } @@ -79,7 +81,16 @@ void UPP_Control_InternalParams(void) if(__CheckSimpleParamU8(&pwm_pulse_num, MB_INTERNAL.param.pwm.PulseNumber, 1)) { pwm_update = 1; - } + } + // Параметры мониторинга + if(__CheckSimpleParamF(&pm_alpha, MB_INTERNAL.param.pm.mean_alpha, 65535)) + { + for(int i = 0; i < 3; i++) + { + Filter_ReInit(&upp.pm.measured.exp[i], pm_alpha); + } + } + // Обновление АЦП конфигов @@ -142,6 +153,17 @@ void UPP_SetDefault(int pui_default, int internal_default) if(internal_default) { + MB_INTERNAL.param.nominal.PhaseNumber = NOM_PHASE_NUMB; + MB_INTERNAL.param.nominal.U = NOM_U_V_DEFAULT*10; + MB_INTERNAL.param.nominal.U_deviation_plus = NOM_U_DEVIATION_PLUS_PERCENT_DEFAULT*100; + MB_INTERNAL.param.nominal.U_deviation_minus = NOM_U_DEVIATION_MINUS_PERCENT_DEFAULT*100; + MB_INTERNAL.param.nominal.F = NOM_F_HZ_DEFAULT*100; + MB_INTERNAL.param.nominal.F_deviation_plus = NOM_F_DEVIATION_PLUS_PERCENT_DEFAULT*100; + MB_INTERNAL.param.nominal.F_deviation_minus = NOM_F_DEVIATION_MINUS_PERCENT_DEFAULT*100; + MB_INTERNAL.param.nominal.I = NOM_I_A_DEFAULT*10; + + MB_INTERNAL.param.pm.mean_alpha = PM_EXP_ALPHA_COEF_DEFAULT*65535; + MB_INTERNAL.param.adc.ADC_Max[ADC_CHANNEL_UBA] = ADC_U_MAX_V_DEFAULT*10; MB_INTERNAL.param.adc.ADC_Max[ADC_CHANNEL_UAC] = ADC_U_MAX_V_DEFAULT*10; MB_INTERNAL.param.adc.ADC_Max[ADC_CHANNEL_IC] = ADC_I_MAX_A_DEFAULT*10; @@ -155,7 +177,7 @@ void UPP_SetDefault(int pui_default, int internal_default) MB_INTERNAL.param.pwm.Frequency = (float)PWM_THYR_FREQUENCY_HZ_DEFAULT; MB_INTERNAL.param.pwm.PulseNumber = PWM_THYR_PULSE_NUMBER_DEFAULT; - MB_INTERNAL.param.zc.Hysteresis = ZERO_CROSS_HYSTERESIS_V_DEFAULT*100; + MB_INTERNAL.param.zc.Hysteresis = ZERO_CROSS_HYSTERESIS_PERCENT_DEFAULT*100; MB_INTERNAL.param.zc.DebouneCouner = ZERO_CROSS_DEBOUNCE_10US_DEFAULT; //__AngleSetLimit(); } @@ -163,10 +185,10 @@ void UPP_SetDefault(int pui_default, int internal_default) -static int __AngleSetLimit(void) +static void __AngleSetLimit(void) { // Перерасчет максимально допустимого угла - float pulses_percent_of_period = ((MB_INTERNAL.param.pwm.PulseNumber / MB_INTERNAL.param.pwm.Frequency) * 1000) / ANGLE_PERIOD_MS; + float pulses_percent_of_period = ((MB_INTERNAL.param.pwm.PulseNumber / MB_INTERNAL.param.pwm.Frequency) * 1000) / ANGLE_PERIOD_MS(NOM_F_HZ_DEFAULT); float angle_limit = 1 - pulses_percent_of_period; Angle_SetLimit(&upp.hangle, angle_limit); } diff --git a/UPP/Core/UPP/upp_control.h b/UPP/Core/UPP/upp_control.h index 6404411..45f5b48 100644 --- a/UPP/Core/UPP/upp_control.h +++ b/UPP/Core/UPP/upp_control.h @@ -12,10 +12,10 @@ typedef struct { - unsigned set_default_pui:1; - unsigned set_default_internal:1; - unsigned go:1; - unsigned stop:1; + unsigned set_default_pui:1; ///< Выставить настройки ПУИ в дефолтные + unsigned set_default_internal:1;///< Выставить внутренние настройки в дефолтные + unsigned go:1; ///< Запустить УПП + unsigned stop:1; ///< Выставить внутренние настройки в дефолтные unsigned reserved:11; @@ -25,33 +25,51 @@ typedef struct typedef struct { + + struct + { + uint16_t mean_alpha; ///< Коэф альфа x10000 для эксп. фильтра Umean, Imean, Fmean + }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; + /* Параметры АЦП */ struct { - uint16_t ADC_Max[4]; - uint16_t ADC_Zero[4]; + uint16_t ADC_Max[4]; ///< В x 10 + uint16_t ADC_Zero[4]; ///< Кванты АЦП }adc; /* Параметры ШИМ */ struct { - uint16_t PhaseMask; - uint16_t Frequency; - uint16_t PulseNumber; + uint16_t PhaseMask; ///< Битовяя маска на какие фазы подавать ШИМ: 0 бит - a, 1 бит - b, 2 бит - c + uint16_t Frequency; ///< Частота ШИМ для пачки импульсов на тиристоры + uint16_t PulseNumber; ///< Количесво импульсов в пачке }pwm; /* Параметры Угла */ struct { - uint16_t Hysteresis; - uint16_t DebouneCouner; + uint16_t Hysteresis; ///< Гистерезис для определения перехода через ноль + uint16_t DebouneCouner; ///< Защита от дребезга: через сколько тактов снова начать фиксировать переход через ноль }zc; /* Параметры Угла */ struct { - uint16_t Angle_Max; - uint16_t Angle_Min; + uint16_t Angle_Max; ///< Максимальный угол открытия тиристора + uint16_t Angle_Min; ///< Минимальный угол открытия тиристора }angle; diff --git a/UPP/Core/UPP/upp_errors.h b/UPP/Core/UPP/upp_errors.h index 9bed663..ac04ca6 100644 --- a/UPP/Core/UPP/upp_errors.h +++ b/UPP/Core/UPP/upp_errors.h @@ -104,7 +104,7 @@ typedef struct uint64_t all; struct { - unsigned :1; + unsigned slow_calc_overrun:1; }err; }f; @@ -113,6 +113,7 @@ typedef struct uint16_t adc_reinit_err; uint16_t zc_reinit_err; uint16_t pwm_reinit_err; + uint16_t slow_calc_overrun; }cnt; }prvt; ///< Приватные ошибки, не идущие напрямую в ПУИ diff --git a/UPP/Core/UPP/upp_main.c b/UPP/Core/UPP/upp_main.c index 9356f6e..6ca39aa 100644 --- a/UPP/Core/UPP/upp_main.c +++ b/UPP/Core/UPP/upp_main.c @@ -6,6 +6,7 @@ * @details ******************************************************************************/ #include "upp_main.h" // всё остальное по работе с УПП +#include "tim.h" UPP_t upp; float alpha_dbg = 0.5; @@ -17,6 +18,7 @@ float alpha_dbg = 0.5; */ int UPP_Init(void) { + BenchTime_Init(); // Подключение указателей upp.errors = &errors; upp.PUI.params = &MB_DATA.HoldRegs.pui_params; @@ -60,8 +62,6 @@ int UPP_While(void) { upp.call->stop = 0; } - - // Сброс на дефолтные по запросу if(upp.call->set_default_pui) { @@ -73,7 +73,9 @@ int UPP_While(void) } - + + + PowerMonitor_SlowHandle(&upp.pm); // Если СТОП - переходим в ошибку if (upp.call->stop) upp.workmode = WM_Error; @@ -107,6 +109,13 @@ int UPP_While(void) PWM_Stop(&upp.hpwm, 0, 1); // Останавливаем ВЕСЬ ШИМ break; + + case WM_Done: + PWM_Stop(&upp.hpwm, 0, 1); // Останавливаем ВЕСЬ ШИМ + break; + + default: + break; } @@ -132,6 +141,8 @@ void UPP_Tick(void) void UPP_ADC_Handle(void) { + BenchTime_Start(BT_ADC, angletim.Instance->CNT, HAL_MAX_DELAY); + PowerMonitor_Handle(&upp.pm); for(int phase = 0; phase < 3; phase++) @@ -152,10 +163,14 @@ void UPP_ADC_Handle(void) } // Проверяем на ошибки + + upp.Timings.isr_adc = BenchTime_End(BT_ADC, angletim.Instance->CNT); } void UPP_PWM_Handle(void) { + BenchTime_Start(BT_PWM, angletim.Instance->CNT, HAL_MAX_DELAY); PWM_Handle(&upp.hpwm); + upp.Timings.isr_pwm = BenchTime_End(BT_PWM, angletim.Instance->CNT); } void UPP_Angle_Handle(void) @@ -184,8 +199,10 @@ void UPP_Angle_Handle(void) void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef* htim) { - if (htim == upp.hangle.htim) - { - UPP_Angle_Handle(); - } + if (htim == upp.hangle.htim) + { + BenchTime_Start(BT_SYSTICK, angletim.Instance->CNT, HAL_MAX_DELAY); + UPP_Angle_Handle(); + upp.Timings.isr_systick = BenchTime_End(BT_SYSTICK, angletim.Instance->CNT); + } } \ No newline at end of file diff --git a/UPP/Core/UPP/upp_main.h b/UPP/Core/UPP/upp_main.h index 62bc657..976e2f3 100644 --- a/UPP/Core/UPP/upp_main.h +++ b/UPP/Core/UPP/upp_main.h @@ -38,6 +38,13 @@ typedef struct UPP_Errors_t *errors; ///< Ошибки УПП uint32_t StartTick; + + struct + { + uint32_t isr_adc; + uint32_t isr_pwm; + uint32_t isr_systick; + }Timings; }UPP_t; extern UPP_t upp; diff --git a/UPP/MDK-ARM/UPP.uvprojx b/UPP/MDK-ARM/UPP.uvprojx index ff631f5..5045ead 100644 --- a/UPP/MDK-ARM/UPP.uvprojx +++ b/UPP/MDK-ARM/UPP.uvprojx @@ -564,57 +564,6 @@ dma.c 1 ../Core/Src/dma.c - - - 2 - 0 - 0 - 0 - 0 - 1 - 2 - 2 - 2 - 2 - 11 - - - 1 - - - - 2 - 0 - 2 - 2 - 2 - 2 - 2 - 2 - 2 - 2 - 0 - 2 - 2 - 2 - 2 - 2 - 0 - 0 - 2 - 2 - 2 - 2 - 2 - - - - - - - - - iwdg.c