diff --git a/MATLAB/MCU_Wrapper/run_mex.bat b/MATLAB/MCU_Wrapper/run_mex.bat index c30c29f..add764a 100644 --- a/MATLAB/MCU_Wrapper/run_mex.bat +++ b/MATLAB/MCU_Wrapper/run_mex.bat @@ -54,6 +54,33 @@ set code_PERIPH=.\MCU_STM32_Matlab\stm32_matlab_conf.c^ .\MCU_STM32_Matlab\Drivers\STM32_SIMULINK\stm32_matlab_gpio.c^ .\MCU_STM32_Matlab\Drivers\STM32_SIMULINK\stm32_matlab_dma.c^ .\MCU_STM32_Matlab\Drivers\STM32_SIMULINK\stm32_periph_registers.c^ + .\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\BasicMathFunctions\BasicMathFunctions.c^ + .\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\BasicMathFunctions\BasicMathFunctionsF16.c^ + .\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\BayesFunctions\BayesFunctions.c^ + .\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\BayesFunctions\BayesFunctionsF16.c^ + .\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\CommonTables\CommonTables.c^ + .\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\CommonTables\CommonTablesF16.c^ + .\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\ComplexMathFunctions\ComplexMathFunctions.c^ + .\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\ComplexMathFunctions\ComplexMathFunctionsF16.c^ + .\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\ControllerFunctions\ControllerFunctions.c^ + .\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\DistanceFunctions\DistanceFunctionsF16.c^ + .\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\FastMathFunctions\FastMathFunctions.c^ + .\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\FastMathFunctions\FastMathFunctionsF16.c^ + .\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\FilteringFunctions\FilteringFunctions.c^ + .\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\FilteringFunctions\FilteringFunctionsF16.c^ + .\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\InterpolationFunctions\InterpolationFunctions.c^ + .\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\InterpolationFunctions\InterpolationFunctionsF16.c^ + .\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\MatrixFunctions\MatrixFunctions.c^ + .\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\MatrixFunctions\MatrixFunctionsF16.c^ + .\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\QuaternionMathFunctions\QuaternionMathFunctions.c^ + .\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\StatisticsFunctions\StatisticsFunctions.c^ + .\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\StatisticsFunctions\StatisticsFunctionsF16.c^ + .\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\SupportFunctions\SupportFunctions.c^ + .\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\SupportFunctions\SupportFunctionsF16.c^ + .\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\SVMFunctions\SVMFunctions.c^ + .\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\SVMFunctions\SVMFunctionsF16.c^ + .\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\TransformFunctions\TransformFunctions.c^ + .\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\TransformFunctions\TransformFunctionsF16.c^ .\MCU_STM32_Matlab\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal.c^ .\MCU_STM32_Matlab\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_adc.c^ .\MCU_STM32_Matlab\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_adc_ex.c^ @@ -75,7 +102,24 @@ set includes_PERIPH=-I".\MCU_STM32_Matlab\."^ -I".\MCU_STM32_Matlab\Drivers\CMSIS"^ -I".\MCU_STM32_Matlab\Drivers\CMSIS\Device\STM32F4xx"^ -I".\MCU_STM32_Matlab\Drivers\STM32F4xx_HAL_Driver\Inc"^ - -I".\MCU_STM32_Matlab\Drivers\STM32F4xx_HAL_Driver\Inc\Legacy" + -I".\MCU_STM32_Matlab\Drivers\STM32F4xx_HAL_Driver\Inc\Legacy"^ + -I".\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Include"^ + -I".\MCU_STM32_Matlab\Drivers\CMSIS\DSP\PrivateInclude"^ + -I".\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\BasicMathFunctions"^ + -I".\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\BayesFunctions"^ + -I".\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\CommonTables"^ + -I".\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\ComplexMathFunctions"^ + -I".\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\ControllerFunctions"^ + -I".\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\DistanceFunctions"^ + -I".\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\FastMathFunctions"^ + -I".\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\FilteringFunctions"^ + -I".\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\InterpolationFunctions"^ + -I".\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\MatrixFunctions"^ + -I".\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\QuaternionMathFunctions"^ + -I".\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\StatisticsFunctions"^ + -I".\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\SupportFunctions"^ + -I".\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\SVMFunctions"^ + -I".\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\TransformFunctions" :: PERIPH BAT END ::------------------------------------------------------------------------- diff --git a/MATLAB/app_wrapper/app_io.c b/MATLAB/app_wrapper/app_io.c index cd56554..780a0bf 100644 --- a/MATLAB/app_wrapper/app_io.c +++ b/MATLAB/app_wrapper/app_io.c @@ -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.Ureal[i], ind_port, nn++); + WriteOutputArray(upp.pm.measured.U[i], ind_port, nn++); } for (int i = 0; i < 3; i++) { //3-5 @@ -45,16 +45,19 @@ void Write_PowerMonitor(real_T* Buffer, int ind_port) } for (int i = 0; i < 3; i++) { //9-11 - WriteOutputArray(upp.pm.measured.Ireal[i], ind_port, nn++); + WriteOutputArray(upp.pm.measured.I[i], ind_port, nn++); } for (int i = 0; i < 2; i++) { //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++); + { //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++); } } diff --git a/MATLAB/upp_r2023.slx b/MATLAB/upp_r2023.slx index d0868f1..87e6520 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 9bff9ad..513f56f 160000 --- a/UPP/AllLibs/MyLibs +++ b/UPP/AllLibs/MyLibs @@ -1 +1 @@ -Subproject commit 9bff9ad44dd625819ef654e98ca351d5bc5568a9 +Subproject commit 513f56fe7dbf0fa8e6a075c22e138c908a01d33f diff --git a/UPP/Core/Configs/upp_config.h b/UPP/Core/Configs/upp_config.h index 8e26bda..709f35b 100644 --- a/UPP/Core/Configs/upp_config.h +++ b/UPP/Core/Configs/upp_config.h @@ -66,7 +66,7 @@ /* Параметры определения перехода через ноль */ #define ZERO_CROSS_HYSTERESIS_PERCENT_DEFAULT 2.0 -#define ZERO_CROSS_DEBOUNCE_10US_DEFAULT 2*100 // (2.5 * 100 = 2.5 мс) +#define ZERO_CROSS_DEBOUNCE_CNT_DEFAULT 2*100 // (2.5 * 100 = 2.5 мс) /* Параметры ШИМ для тиристоров */ #define PWM_THYR_FREQUENCY_HZ_DEFAULT 20000 @@ -84,9 +84,9 @@ * @{ */ /* Периоды вызова всякого */ -#define PM_ADC_PERIOD_US 10 ///< Период опроса АЦП в мкс -#define PM_SLOW_PERIOD_10US 50 ///< Период обновление медленных расчетов в 10мкс -#define PM_TEMP_PERIOD_10US 5000 ///< Период обновление датчиков температуры в 10мкс +#define PM_ADC_PERIOD_US 10 ///< Период опроса АЦП в мкс +#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 ///< Частота тиков таймера АЦП diff --git a/UPP/Core/PowerMonitor/adc_tools.c b/UPP/Core/PowerMonitor/adc_tools.c index 3ac7560..3e38f48 100644 --- a/UPP/Core/PowerMonitor/adc_tools.c +++ b/UPP/Core/PowerMonitor/adc_tools.c @@ -178,6 +178,7 @@ HAL_StatusTypeDef ADC_Handle(ADC_Periodic_t *adc) if(Filter_isDataReady(&adc->filter[0])) adc->f.DataReady = 1; + return HAL_OK; } @@ -217,7 +218,7 @@ void ADC_UpdateStatistics(ADC_Periodic_t *adc, uint8_t channel, ADC_StatLevel_t } // Накопление для Avg/RMS - stat->Sum += ABS(value); + stat->Sum += fabsf(value); stat->SumSquares += value * value; stat->SampleCount++; diff --git a/UPP/Core/PowerMonitor/phases_transform.c b/UPP/Core/PowerMonitor/phases_transform.c new file mode 100644 index 0000000..cf6ab63 --- /dev/null +++ b/UPP/Core/PowerMonitor/phases_transform.c @@ -0,0 +1,49 @@ +/** +****************************************************************************** +* @file phases_transform.c +* @brief Функции для преобразования напряжений/токов в многофазных системах +****************************************************************************** +* @details +******************************************************************************/ +#include "phases_transform.h" +#define SQRT3 1.7320508 + +/** + * @brief Рассчитать результирующий вектор трехфазной системы по фазным величинам. + * @return Длина вектора (модуль). + * @note Вызывается в DMA2_Stream0_IRQHandler() для обработки всего, что пришло по DMA. + */ +float vector_abs_phase_calc(float phase1, float phase2) +{ + /* Двухвазная система координат x-y */ + float x = phase1; + float y = (-phase1 - 2*phase2)/SQRT3; + float V = 0; + arm_status res = arm_sqrt_f32(x*x + y*y, &V); + + if(res == ARM_MATH_SUCCESS) + return V; + else + return 0; +} + +/** + * @brief Рассчитать результирующий вектор трехфазной системы по линейным величинам. + * @return Длина вектора (модуль). + * @note Вызывается в DMA2_Stream0_IRQHandler() для обработки всего, что пришло по DMA. + */ +float vector_abs_linear_calc(float phase1, float phase2) +{ + /* Двухвазная система координат x-y */ + float x = (phase1 - phase2)/SQRT3; + float y = -phase1 - phase2; + float V = 0; + arm_status res = arm_sqrt_f32(x*x + y*y, &V); + + if(res == ARM_MATH_SUCCESS) + return V; + else + return 0; +} + + diff --git a/UPP/Core/PowerMonitor/phases_transform.h b/UPP/Core/PowerMonitor/phases_transform.h new file mode 100644 index 0000000..5d78003 --- /dev/null +++ b/UPP/Core/PowerMonitor/phases_transform.h @@ -0,0 +1,16 @@ +/** +****************************************************************************** +* @file phases_transform.h +* @brief Функции для преобразования напряжений/токов в многофазных системах +****************************************************************************** +*****************************************************************************/ +#ifndef _PHASES_TRANSFORM_H_ +#define _PHASES_TRANSFORM_H_ +#include "main.h" + +/* Рассчитать результирующий вектор трехфазной системы по фазным величинам. */ +float vector_abs_phase_calc(float phase1, float phase2); +/* Рассчитать результирующий вектор трехфазной системы по линейным величинам. */ +float vector_abs_linear_calc(float phase1, float phase2); + +#endif /* _PHASES_TRANSFORM_H_ */ diff --git a/UPP/Core/PowerMonitor/power_monitor.c b/UPP/Core/PowerMonitor/power_monitor.c index fa0e51e..aeb06ec 100644 --- a/UPP/Core/PowerMonitor/power_monitor.c +++ b/UPP/Core/PowerMonitor/power_monitor.c @@ -6,9 +6,11 @@ * @details ******************************************************************************/ #include "power_monitor.h" +#include "phases_transform.h" #include "adc.h" #include "tim.h" +static void __SynchAvgFilters(PowerMonitor_t *hpm); HAL_StatusTypeDef PowerMonitor_Init(PowerMonitor_t *hpm) { @@ -59,27 +61,27 @@ HAL_StatusTypeDef PowerMonitor_Init(PowerMonitor_t *hpm) /* Инициализация экпоненциального фильтра медленного алга */ - for(int i = 0; i < 3; i++) + for(int i = 0; i < EXP_ALL; i++) { - if(FilterExp_Init(&hpm->measured.exp[i], (float)MB_INTERNAL.param.pm.mean_alpha/65535)) + if(FilterExp_Init(&hpm->exp[i], (float)MB_INTERNAL.param.pm.mean_alpha/65535)) return HAL_ERROR; - Filter_Start(&hpm->measured.exp[i]); + Filter_Start(&hpm->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; + if(FilterAverage_Init(&hpm->avg[i], PM_SLOW_PERIOD_CNT, FILTER_MODE_DEFAULT)) + return HAL_ERROR; - Filter_Start(&hpm->measured.avg[i]); + Filter_Start(&hpm->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)) + if(FilterAverage_Init(&hpm->avg[ADC_TEMP_CHANNELS_START+i], PM_TEMP_SLOW_PERIOD_CNT, FILTER_MODE_DEFAULT)) return HAL_ERROR; - Filter_Start(&hpm->measured.avg[ADC_TEMP_CHANNELS_START+i]); + Filter_Start(&hpm->avg[ADC_TEMP_CHANNELS_START+i]); } return HAL_OK; @@ -104,76 +106,87 @@ void PowerMonitor_SlowHandle(PowerMonitor_t *hpm) return; if(!hpm->f.runSlow) return; - hpm->f.runSlow = 0; 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->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; + + /* Расчет всякого для трех фаз отдельно */ + float fmean = 0; // средняя частота по трем фазам + float iphase_mean = 0; // средний ток каждой фазы for(int i = 0; i < 3; i++) { - umean += ABS(meas->Uslow[i]); - imean += ABS(meas->Islow[i]); - fmean += ABS(meas->F[i]); + /* Получение частоты фазы */ + meas->F[i] = ZC_GetFrequency(&hpm->zc, i) / 2; + fmean += meas->F[i]; + + /* Средний ток фазы */ + iphase_mean = fabsf(meas->Islow[i]); + meas->Imean[i] = Filter_Process(&hpm->exp[EXP_IC+i], iphase_mean); } - umean /=3; - imean /=3; - fmean /=3; + /* Получение средней частоты по трем фазам */ + fmean /= 3; + meas->Fmean = Filter_Process(&hpm->exp[EXP_F], fmean); - 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); + + /* Расчет результирущих векторов трехфазной сети */ + 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; } void PowerMonitor_Handle(PowerMonitor_t *hpm) { if(hpm == NULL) return; - /* Считываем АЦП */ - ADC_Handle(&hpm->adc); + /* Считываем АЦП с пересчетами и медианой фильтрацией от выбросов */ + ADC_Handle(&hpm->adc); - - /* Заполняем величины */ + /* Заполняем величины Напряжений/Токов */ 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]; + 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]; /* Преобразуем в относительные единицы (о.е.) */ for(int i = 0; i < 3; i++) { - meas->U[i] = 10*meas->Ureal[i]/MB_INTERNAL.param.nominal.U; - meas->I[i] = 10*meas->Ireal[i]/MB_INTERNAL.param.nominal.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; } /* Ищем переход через ноль */ - ZC_ProcessAllChannels(&hpm->zc, meas->U, usTick); - for(int i = 0; i < 3; i++) - { - meas->F[i] = ZC_GetFrequency(&hpm->zc, i) / 2; - } + ZC_ProcessAllChannels(&hpm->zc, meas->Ufast, usTick); + /* Вообще фильтры должны рабтоать синхронно, но на всякий синхронизация */ + __SynchAvgFilters(hpm); + /* Накопление 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]); + 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]); + /* Запускаем медленную обработку через slow_period прерываний */ -// if(hpm->isr_cnt == PM_SLOW_PERIOD_10US) +// if(hpm->isr_cnt == PM_SLOW_PERIOD_CNT) /* Запускаем медленную когда фильтры среднего зациклились */ - if(Filter_isDataReady(&meas->avg[0])) + /* Берем 0 фильтр, просто так, потому что они все должны работать синхронно */ + if(Filter_isDataReady(&hpm->avg[0])) { + hpm->isr_cnt = 0; if(!hpm->f.runSlow) { @@ -189,4 +202,27 @@ void PowerMonitor_Handle(PowerMonitor_t *hpm) { hpm->isr_cnt++; } +} + +/* Синхронизация фильтров. Но вообще не должна никогда отрабатывать */ +static void __SynchAvgFilters(PowerMonitor_t *hpm) +{ + uint8_t counts_equal = 1; + uint32_t first_count = hpm->avg[0].count; + for (int i = 1; i < ADC_NUMB_OF_REGULAR_CHANNELS; i++) + { + if (hpm->avg[i].count != first_count) + { + counts_equal = 0; + break; + } + } + if(!counts_equal) + { + for(int i = 0; i < ADC_NUMB_OF_REGULAR_CHANNELS; i++) + { + Filter_ReInit(&hpm->avg[i], hpm->avg[i].size, FILTER_MODE_DEFAULT); + Filter_Start(&hpm->avg[i]); + } + } } \ No newline at end of file diff --git a/UPP/Core/PowerMonitor/power_monitor.h b/UPP/Core/PowerMonitor/power_monitor.h index 3a0d378..6d0d54a 100644 --- a/UPP/Core/PowerMonitor/power_monitor.h +++ b/UPP/Core/PowerMonitor/power_monitor.h @@ -10,6 +10,15 @@ #include "adc_tools.h" #include "zero_cross.h" +/* Индексы экспоненциальных фильтров */ +#define EXP_ALL 6 +#define EXP_U 0 +#define EXP_I 1 +#define EXP_IC 2 +#define EXP_IA 3 +#define EXP_IB 4 +#define EXP_F 5 + typedef struct { @@ -27,24 +36,27 @@ typedef struct typedef struct { - float U_mean; ///< Среднее Напряжение по трем фазам - float I_mean; ///< Средний Ток по трем фазам - float F_mean; ///< Средняя Частота по трем фазам - float Uslow[3]; ///< Напряжение от АЦП (в о.е.) - float Islow[3]; ///< Ток от АЦП (в о.е.) + /* Усредненные величины (о.е.) */ + float Uvec; ///< Результирующий вектор Напряжения по трем фазам + float Ivec; ///< Результирующий вектор Тока по трем фазам + float Imean[3]; ///< Средний Ток по трем фазам + float Fmean; ///< Средняя Частота по трем фазам + + /* Быстрые величины (в о.е.) - обновляются в каждом прерывании АЦП */ + 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) - 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 @@ -55,8 +67,12 @@ typedef struct { ADC_Periodic_t adc; ///< Хендл периодического АЦП ZeroCross_Handle_t zc; ///< Хендл перехода через ноль - PowerMonitor_Filters_t fltr; + PowerMonitor_Measured_t measured; ///< Измеренные/рассчитанные величины + + FilterExp_t exp[EXP_ALL]; ///< Фильтры для mean + FilterAverage_t avg[ADC_NUMB_OF_CHANNELS]; ///< Фильтры для avg + PowerMonitor_Flags_t f; ///< Флаги мониторинга diff --git a/UPP/Core/PowerMonitor/power_protect.c b/UPP/Core/PowerMonitor/power_protect.c new file mode 100644 index 0000000..99d8aeb --- /dev/null +++ b/UPP/Core/PowerMonitor/power_protect.c @@ -0,0 +1,8 @@ +/** +****************************************************************************** +* @file power_protect.c +* @brief Модуль реализующий защиты по Напряжению/Токам/Температуре +****************************************************************************** +* @details +******************************************************************************/ +#include "power_protect.h" \ No newline at end of file diff --git a/UPP/Core/PowerMonitor/power_protect.h b/UPP/Core/PowerMonitor/power_protect.h new file mode 100644 index 0000000..a378e78 --- /dev/null +++ b/UPP/Core/PowerMonitor/power_protect.h @@ -0,0 +1,11 @@ +/** +****************************************************************************** +* @file power_monitor.h +* @brief Модуль реализующий защиты по Напряжению/Токам/Температуре +****************************************************************************** +*****************************************************************************/ +#ifndef _POWER_PROTECT_H_ +#define _POWER_PROTECT_H_ +#include "main.h" + +#endif /* _POWER_PROTECT_H_ */ diff --git a/UPP/Core/UPP/upp_control.c b/UPP/Core/UPP/upp_control.c index d0265bd..e949a30 100644 --- a/UPP/Core/UPP/upp_control.c +++ b/UPP/Core/UPP/upp_control.c @@ -39,7 +39,7 @@ void UPP_Control_InternalParams(void) 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; + float pm_alpha = upp.pm.exp[0].alpha; for(int i = 0; i < ADC_NUMB_OF_REGULAR_CHANNELS; i++) @@ -87,7 +87,7 @@ void UPP_Control_InternalParams(void) { for(int i = 0; i < 3; i++) { - Filter_ReInit(&upp.pm.measured.exp[i], pm_alpha); + Filter_ReInit(&upp.pm.exp[i], pm_alpha); } } @@ -178,7 +178,7 @@ void UPP_SetDefault(int pui_default, int internal_default) MB_INTERNAL.param.pwm.PulseNumber = PWM_THYR_PULSE_NUMBER_DEFAULT; MB_INTERNAL.param.zc.Hysteresis = ZERO_CROSS_HYSTERESIS_PERCENT_DEFAULT*100; - MB_INTERNAL.param.zc.DebouneCouner = ZERO_CROSS_DEBOUNCE_10US_DEFAULT; + MB_INTERNAL.param.zc.DebouneCouner = ZERO_CROSS_DEBOUNCE_CNT_DEFAULT; //__AngleSetLimit(); } } diff --git a/UPP/Core/UPP/upp_control.h b/UPP/Core/UPP/upp_control.h index 45f5b48..1cbcc53 100644 --- a/UPP/Core/UPP/upp_control.h +++ b/UPP/Core/UPP/upp_control.h @@ -15,7 +15,7 @@ typedef struct unsigned set_default_pui:1; ///< Выставить настройки ПУИ в дефолтные unsigned set_default_internal:1;///< Выставить внутренние настройки в дефолтные unsigned go:1; ///< Запустить УПП - unsigned stop:1; ///< Выставить внутренние настройки в дефолтные + unsigned stop:1; ///< Остановка УПП (авария) unsigned reserved:11; diff --git a/UPP/MDK-ARM/UPP.uvoptx b/UPP/MDK-ARM/UPP.uvoptx index a8f9a56..fd4f4c5 100644 --- a/UPP/MDK-ARM/UPP.uvoptx +++ b/UPP/MDK-ARM/UPP.uvoptx @@ -128,7 +128,24 @@ -U-O142 -O2190 -S0 -C0 -N00("ARM CoreSight SW-DP") -D00(2BA01477) -L00(0) -TO18 -TC10000000 -TP21 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO7 -FD20000000 -FC800 -FN1 -FF0STM32F4xx_1024.FLM -FS08000000 -FL0100000 -FP0($$Device:STM32F427ZGTx$CMSIS\Flash\STM32F4xx_1024.FLM) - + + + 0 + 0 + 156 + 1 +
0
+ 0 + 0 + 0 + 0 + 0 + 0 + ..\Core\PowerMonitor\power_monitor.c + + +
+
0 @@ -498,6 +515,30 @@ 0 0 0 + ..\Core\PowerMonitor\zero_cross.c + zero_cross.c + 0 + 0 + + + 3 + 26 + 5 + 0 + 0 + 0 + ..\Core\PowerMonitor\zero_cross.h + zero_cross.h + 0 + 0 + + + 3 + 27 + 1 + 0 + 0 + 0 ..\Core\PowerMonitor\adc_tools.c adc_tools.c 0 @@ -505,7 +546,7 @@ 3 - 26 + 28 5 0 0 @@ -517,25 +558,49 @@ 3 - 27 + 29 1 0 0 0 - ..\Core\PowerMonitor\zero_cross.c - zero_cross.c + ..\Core\PowerMonitor\phases_transform.c + phases_transform.c 0 0 3 - 28 + 30 5 0 0 0 - ..\Core\PowerMonitor\zero_cross.h - zero_cross.h + ..\Core\PowerMonitor\phases_transform.h + phases_transform.h + 0 + 0 + + + 3 + 31 + 1 + 0 + 0 + 0 + ..\Core\PowerMonitor\power_protect.c + power_protect.c + 0 + 0 + + + 3 + 32 + 5 + 0 + 0 + 0 + ..\Core\PowerMonitor\power_protect.h + power_protect.h 0 0 @@ -549,7 +614,7 @@ 0 4 - 29 + 33 1 0 0 @@ -561,7 +626,7 @@ 4 - 30 + 34 1 0 0 @@ -573,7 +638,7 @@ 4 - 31 + 35 1 0 0 @@ -585,7 +650,7 @@ 4 - 32 + 36 1 0 0 @@ -597,7 +662,7 @@ 4 - 33 + 37 1 0 0 @@ -609,7 +674,7 @@ 4 - 34 + 38 1 0 0 @@ -621,7 +686,7 @@ 4 - 35 + 39 1 0 0 @@ -633,7 +698,7 @@ 4 - 36 + 40 1 0 0 @@ -645,7 +710,7 @@ 4 - 37 + 41 1 0 0 @@ -657,7 +722,7 @@ 4 - 38 + 42 1 0 0 @@ -669,7 +734,7 @@ 4 - 39 + 43 1 0 0 @@ -681,7 +746,7 @@ 4 - 40 + 44 1 0 0 @@ -693,7 +758,7 @@ 4 - 41 + 45 1 0 0 @@ -713,7 +778,7 @@ 0 5 - 42 + 46 5 0 0 @@ -725,7 +790,7 @@ 5 - 43 + 47 5 0 0 @@ -737,7 +802,7 @@ 5 - 44 + 48 5 0 0 @@ -749,7 +814,7 @@ 5 - 45 + 49 5 0 0 @@ -761,7 +826,7 @@ 5 - 46 + 50 5 0 0 @@ -773,7 +838,7 @@ 5 - 47 + 51 5 0 0 @@ -785,7 +850,7 @@ 5 - 48 + 52 1 0 0 @@ -797,7 +862,7 @@ 5 - 49 + 53 5 0 0 @@ -817,7 +882,7 @@ 0 6 - 50 + 54 1 0 0 @@ -829,7 +894,7 @@ 6 - 51 + 55 1 0 0 @@ -841,7 +906,7 @@ 6 - 52 + 56 1 0 0 @@ -853,7 +918,7 @@ 6 - 53 + 57 1 0 0 @@ -865,7 +930,7 @@ 6 - 54 + 58 1 0 0 @@ -877,7 +942,7 @@ 6 - 55 + 59 1 0 0 @@ -889,7 +954,7 @@ 6 - 56 + 60 1 0 0 @@ -901,7 +966,7 @@ 6 - 57 + 61 1 0 0 @@ -913,7 +978,7 @@ 6 - 58 + 62 1 0 0 @@ -925,7 +990,7 @@ 6 - 59 + 63 1 0 0 @@ -937,7 +1002,7 @@ 6 - 60 + 64 1 0 0 @@ -949,7 +1014,7 @@ 6 - 61 + 65 1 0 0 @@ -969,7 +1034,7 @@ 0 7 - 62 + 66 1 0 0 @@ -981,7 +1046,7 @@ 7 - 63 + 67 1 0 0 @@ -995,13 +1060,13 @@ PeriphGeneral - 1 + 0 0 0 0 8 - 64 + 68 1 0 0 @@ -1013,7 +1078,7 @@ 8 - 65 + 69 1 0 0 @@ -1025,7 +1090,7 @@ 8 - 66 + 70 1 0 0 @@ -1037,7 +1102,7 @@ 8 - 67 + 71 1 0 0 @@ -1049,7 +1114,7 @@ 8 - 68 + 72 1 0 0 @@ -1069,7 +1134,7 @@ 0 9 - 69 + 73 1 0 0 @@ -1081,7 +1146,7 @@ 9 - 70 + 74 1 0 0 @@ -1093,7 +1158,7 @@ 9 - 71 + 75 1 0 0 @@ -1105,7 +1170,7 @@ 9 - 72 + 76 1 0 0 @@ -1117,7 +1182,7 @@ 9 - 73 + 77 1 0 0 @@ -1129,7 +1194,7 @@ 9 - 74 + 78 1 0 0 @@ -1141,7 +1206,7 @@ 9 - 75 + 79 1 0 0 @@ -1153,7 +1218,7 @@ 9 - 76 + 80 1 0 0 @@ -1165,7 +1230,7 @@ 9 - 77 + 81 1 0 0 @@ -1177,7 +1242,7 @@ 9 - 78 + 82 1 0 0 @@ -1189,7 +1254,7 @@ 9 - 79 + 83 1 0 0 @@ -1201,7 +1266,7 @@ 9 - 80 + 84 1 0 0 @@ -1213,7 +1278,7 @@ 9 - 81 + 85 1 0 0 @@ -1225,7 +1290,7 @@ 9 - 82 + 86 1 0 0 @@ -1237,7 +1302,7 @@ 9 - 83 + 87 1 0 0 @@ -1249,7 +1314,7 @@ 9 - 84 + 88 1 0 0 @@ -1261,7 +1326,7 @@ 9 - 85 + 89 1 0 0 @@ -1273,7 +1338,7 @@ 9 - 86 + 90 1 0 0 @@ -1285,7 +1350,7 @@ 9 - 87 + 91 1 0 0 @@ -1297,7 +1362,7 @@ 9 - 88 + 92 1 0 0 @@ -1309,7 +1374,7 @@ 9 - 89 + 93 1 0 0 @@ -1321,7 +1386,7 @@ 9 - 90 + 94 1 0 0 @@ -1333,7 +1398,7 @@ 9 - 91 + 95 1 0 0 @@ -1345,7 +1410,7 @@ 9 - 92 + 96 1 0 0 @@ -1365,7 +1430,7 @@ 0 10 - 93 + 97 1 0 0 @@ -1385,7 +1450,7 @@ 0 11 - 94 + 98 2 0 0 @@ -1399,7 +1464,7 @@ ::CMSIS - 1 + 0 0 0 1 diff --git a/UPP/MDK-ARM/UPP.uvprojx b/UPP/MDK-ARM/UPP.uvprojx index 5045ead..24baab7 100644 --- a/UPP/MDK-ARM/UPP.uvprojx +++ b/UPP/MDK-ARM/UPP.uvprojx @@ -17,8 +17,8 @@ STM32F427ZGTx STMicroelectronics - Keil.STM32F4xx_DFP.2.16.0 - http://www.keil.com/pack/ + Keil.STM32F4xx_DFP.2.17.1 + https://www.keil.com/pack/ IRAM(0x20000000-0x2002FFFF) IRAM2(0x10000000-0x1000FFFF) IROM(0x8000000-0x80FFFFF) CLOCK(25000000) FPU2 CPUTYPE("Cortex-M4") TZ @@ -515,6 +515,16 @@ 5 ..\Core\PowerMonitor\power_monitor.h + + zero_cross.c + 1 + ..\Core\PowerMonitor\zero_cross.c + + + zero_cross.h + 5 + ..\Core\PowerMonitor\zero_cross.h + adc_tools.c 1 @@ -526,14 +536,24 @@ ..\Core\PowerMonitor\adc_tools.h - zero_cross.c + phases_transform.c 1 - ..\Core\PowerMonitor\zero_cross.c + ..\Core\PowerMonitor\phases_transform.c - zero_cross.h + phases_transform.h 5 - ..\Core\PowerMonitor\zero_cross.h + ..\Core\PowerMonitor\phases_transform.h + + + power_protect.c + 1 + ..\Core\PowerMonitor\power_protect.c + + + power_protect.h + 5 + ..\Core\PowerMonitor\power_protect.h