diff --git a/.gitignore b/.gitignore index 76eefbb..f8a2aac 100644 --- a/.gitignore +++ b/.gitignore @@ -61,3 +61,4 @@ JLinkLog.txt /MATLAB/MCU.exp /MATLAB/MCU.lib /MATLAB/MCU.mexw64.manifest +/MATLAB/upp_r2023.slx.autosave diff --git a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/arm_defines.h b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/arm_defines.h index e31109d..b841697 100644 --- a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/arm_defines.h +++ b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/arm_defines.h @@ -27,7 +27,7 @@ #endif #ifndef __STATIC_FORCEINLINE - #define __STATIC_FORCEINLINE static __forceinline + #define __STATIC_FORCEINLINE //static __forceinline #endif #ifndef __NO_RETURN diff --git a/MATLAB/MCU_STM32_Matlab/Drivers/STM32_SIMULINK/stm32_matlab_adc.c b/MATLAB/MCU_STM32_Matlab/Drivers/STM32_SIMULINK/stm32_matlab_adc.c index d199507..4d28469 100644 --- a/MATLAB/MCU_STM32_Matlab/Drivers/STM32_SIMULINK/stm32_matlab_adc.c +++ b/MATLAB/MCU_STM32_Matlab/Drivers/STM32_SIMULINK/stm32_matlab_adc.c @@ -311,21 +311,6 @@ uint32_t ADC_Get_Sequence_Channel(ADC_TypeDef* ADCx, uint32_t rank) } } -/////////////////////////////---DMA FUNCTIONS---/////////////////////////////// -void ADC_DMA_Sim_Transfer(ADC_TypeDef* ADCx, struct ADC_Sim* ADCS) -{ - if (!ADCS->dma_buffer || ADCS->dma_buffer_size == 0) return; - - ADCS->dma_buffer[ADCS->dma_current_index] = ADCx->DR; - ADCS->dma_current_index++; - - if (ADCS->dma_current_index >= ADCS->dma_buffer_size) { - if (ADCS->dma_circular) { - ADCS->dma_current_index = 0; - } - } -} - /////////////////////////////---CHANNEL FUNCTIONS---/////////////////////////// void ADC_Set_Channel_Value(ADC_TypeDef* ADCx, uint32_t channel, double voltage) { 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 26d8697..e78a6c2 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 20 // Шум в LSB (квантах АЦП) #endif /////////////////////////////---STRUCTURES---/////////////////////////// @@ -23,12 +23,6 @@ struct ADC_Sim double channel_values[19]; uint8_t channel_connected[19]; - // DMA - uint32_t* dma_buffer; - uint32_t dma_buffer_size; - uint32_t dma_current_index; - uint8_t dma_circular; - // Timing double simulation_step; double adc_clock_freq; diff --git a/MATLAB/MCU_STM32_Matlab/Drivers/STM32_SIMULINK/stm32_matlab_tim.c b/MATLAB/MCU_STM32_Matlab/Drivers/STM32_SIMULINK/stm32_matlab_tim.c index 5f24a07..46b9f21 100644 --- a/MATLAB/MCU_STM32_Matlab/Drivers/STM32_SIMULINK/stm32_matlab_tim.c +++ b/MATLAB/MCU_STM32_Matlab/Drivers/STM32_SIMULINK/stm32_matlab_tim.c @@ -65,6 +65,9 @@ void Overflow_Check(TIM_TypeDef* TIMx, struct TIM_Sim* TIMS) else if (TIMS->tx_cnt < 0) TIMS->tx_cnt += TIMS->RELOAD+1; + if(TIMS->tx_step > TIMS->RELOAD) + TIMS->tx_cnt = 0; + TIM_Call_IRQHandller(TIMx); // call HANDLER } } diff --git a/MATLAB/app_wrapper/app_io.c b/MATLAB/app_wrapper/app_io.c index bbd7a47..4050af7 100644 --- a/MATLAB/app_wrapper/app_io.c +++ b/MATLAB/app_wrapper/app_io.c @@ -38,6 +38,10 @@ ADC_Set_Channel_Value(ADC3, 6, ReadInputArray(0,2)); ADC_Set_Channel_Value(ADC3, 7, ReadInputArray(0,3)); ADC_Set_Channel_Value(ADC3, 8, ReadInputArray(0,4)); ADC_Set_Channel_Value(ADC3, 10, ReadInputArray(0,5)); + + +__HAL_TIM_SET_AUTORELOAD(&adc_tim, ReadInputArray(1, 0)); + // USER APP INPUT END } diff --git a/MATLAB/upp_r2023.slx b/MATLAB/upp_r2023.slx index 1ebf0c0..1fdd5ac 100644 Binary files a/MATLAB/upp_r2023.slx and b/MATLAB/upp_r2023.slx differ diff --git a/UPP/.mxproject b/UPP/.mxproject index 76a640e..df45b06 100644 --- a/UPP/.mxproject +++ b/UPP/.mxproject @@ -6,6 +6,9 @@ SourceFiles=..\Core\Src\main.c;..\Core\Src\gpio.c;..\Core\Src\adc.c;..\Core\Src\ HeaderPath=..\Drivers\STM32F4xx_HAL_Driver\Inc;..\Drivers\STM32F4xx_HAL_Driver\Inc\Legacy;..\Drivers\CMSIS\Device\ST\STM32F4xx\Include;..\Drivers\CMSIS\Include;..\Core\Inc; CDefines=USE_HAL_DRIVER;STM32F427xx;USE_HAL_DRIVER;USE_HAL_DRIVER; +[] +SourceFiles=;; + [PreviousGenFiles] AdvancedFolderStructure=true HeaderFileListSize=12 diff --git a/UPP/AllLibs/MyLibs b/UPP/AllLibs/MyLibs index 60629aa..3b162c9 160000 --- a/UPP/AllLibs/MyLibs +++ b/UPP/AllLibs/MyLibs @@ -1 +1 @@ -Subproject commit 60629aaa3bb3a068cbfe5a93f43f676bd154e85b +Subproject commit 3b162c9f8cdbcf8606d1b96ea2b26b23e2e9c290 diff --git a/UPP/Core/Configs/mylibs_config.h b/UPP/Core/Configs/mylibs_config.h index d16629f..c87e783 100644 --- a/UPP/Core/Configs/mylibs_config.h +++ b/UPP/Core/Configs/mylibs_config.h @@ -13,7 +13,6 @@ #include "upp_config.h" // user includes -#ifndef MATLAB /** * @addtogroup TRACE_CONFIG Trace configs * @ingroup MYLIBS_CONFIG @@ -53,6 +52,26 @@ */ + +/** + * @addtogroup FILTER_CONFIG Filter configs + * @ingroup MYLIBS_CONFIG + * @brief Конфигурация фильтров + * @{ + */ + + +#define FILTERS_ENABLE ///< Включить библиотеку фильтров +//#define FILTER_MEDIAN_MAX_SIZE ///< Максимальный размер окна медианного фильтра (по умолчанию 5) +//#define FILTER_AVERAGE_MAX_SIZE ///< Максимальный размер окна усредняющего фильтра (по умолчанию 8) +//#define FILTER_POLY_MAX_ORDER ///< Максимальный порядок полинома (по умолчанию 4) + +/** GEN_CONFIG + * @} + */ + + + /** * @addtogroup GEN_CONFIG Genetic configs * @ingroup MYLIBS_CONFIG @@ -93,6 +112,7 @@ * @{ */ +#ifndef MATLAB #define local_time() uwTick ///< Локальное время #define INCLUDE_GEN_OPTIMIZER ///< Подключить библиотеку для оптимизации параметров @@ -100,9 +120,22 @@ #define INCLUDE_TRACKERS_LIB ///< Подключить библиотеку с трекерами #define INCLUDE_TRACE_LIB ///< Подключить библиотеку с трейсами #define INCLUDE_GENERAL_PERIPH_LIBS ///< Подключить библиотеку с периферией -#define INCLUDE_BENCH_TIME ///< Подключить библиотеку с периферией +#define INCLUDE_BENCH_TIME ///< Подключить библиотеку с бенчмарком времени +#define INCLUDE_FILTERS ///< Подключить библиотеку с фильтрами //#define FREERTOS_DELAY ///< Использовать FreeRTOS задержку, вместо HAL +#else + +#define local_time() uwTick ///< Локальное время +//#define INCLUDE_GEN_OPTIMIZER ///< Подключить библиотеку для оптимизации параметров +#define INCLUDE_BIT_ACCESS_LIB ///< Подключить библиотеку с typedef с битовыми полями +#define INCLUDE_TRACKERS_LIB ///< Подключить библиотеку с трекерами +//#define INCLUDE_TRACE_LIB ///< Подключить библиотеку с трейсами +//#define INCLUDE_GENERAL_PERIPH_LIBS ///< Подключить библиотеку с периферией +//#define INCLUDE_BENCH_TIME ///< Подключить библиотеку с бенчмарком времени +#define INCLUDE_FILTERS ///< Подключить библиотеку с фильтрами + +#endif //MATLAB /** LIBS_CONFIG * @} */ @@ -110,5 +143,4 @@ /** MYLIBS_CONFIG * @} */ -#endif //MATLAB #endif //__MYLIBS_CONFIG_H_ \ No newline at end of file diff --git a/UPP/Core/Configs/mylibs_include.h b/UPP/Core/Configs/mylibs_include.h index 9c47b9b..f3256e9 100644 --- a/UPP/Core/Configs/mylibs_include.h +++ b/UPP/Core/Configs/mylibs_include.h @@ -100,6 +100,52 @@ #define BenchTime_ResetStats(channel) #endif //BENCH_TIME_ENABLE + +#ifdef INCLUDE_FILTERS +#include "filters.h" +#else //INCLUDE_FILTERS +// Заглушки для float +#define FilterMedian_t void * +#define FilterExp_t void * +#define FilterAverage_t void * +#define FilterPoly_t void * +#define FilterLUT_t void * + +#define FilterMedian_Init(filter, size) +#define FilterMedian_Process(filter, input) (input) +#define FilterExp_Init(filter, alpha) +#define FilterExp_Process(filter, input) (input) +#define FilterAverage_Init(filter, size) +#define FilterAverage_Process(filter, input) (input) +#define FilterPoly_Init(filter, coeffs, order) (0) +#define FilterPoly_Process(filter, input) (input) +#define FilterLUT_Init(filter, input_arr, output_arr, size, interpolation) (0) +#define FilterLUT_Process(filter, input) (input) + +// Заглушки для int32_t +#define FilterMedianInt_t void * +#define FilterExpInt_t void * +#define FilterAverageInt_t void * +#define FilterPolyInt_t void * +#define FilterLUTInt_t void * + +#define FilterMedianInt_Init(filter, size) +#define FilterMedianInt_Process(filter, input) (input) +#define FilterExpInt_Init(filter, alpha, scale) +#define FilterExpInt_Process(filter, input) (input) +#define FilterAverageInt_Init(filter, size) +#define FilterAverageInt_Process(filter, input) (input) +#define FilterPolyInt_Init(filter, coeffs, order, scale) (0) +#define FilterPolyInt_Process(filter, input) (input) +#define FilterLUTInt_Init(filter, input_arr, output_arr, size, interpolation) (0) +#define FilterLUTInt_Process(filter, input) (input) + +#define FILTER_GET_STATE(_fltr_) dummy +#define FILTER_ENABLE 0 +#define FILTER_DISABLE 0 +#endif //INCLUDE_FILTERS + + #ifdef INCLUDE_GENERAL_PERIPH_LIBS #include "__general_flash.h" diff --git a/UPP/Core/Inc/main.h b/UPP/Core/Inc/main.h index a705fae..02c2ae9 100644 --- a/UPP/Core/Inc/main.h +++ b/UPP/Core/Inc/main.h @@ -63,19 +63,19 @@ void Error_Handler(void); /* Private defines -----------------------------------------------------------*/ #define mb_huart huart3 #define mbdbg_htim htim11 -#define mb_htim htim12 -#define mb_dbg_huart huart6 -#define ustim htim13 -#define mem_hspi hspi3 -#define hpwm1 htim1 -#define hpwm2 htim2 #define PWM_CHANNEL_1 TIM_CHANNEL_1 #define PWM_CHANNEL_2 TIM_CHANNEL_2 #define PWM_CHANNEL_3 TIM_CHANNEL_3 #define PWM_CHANNEL_4 TIM_CHANNEL_4 +#define mem_hspi hspi3 #define PWM_CHANNEL_5 TIM_CHANNEL_3 #define PWM_CHANNEL_6 TIM_CHANNEL_4 +#define mb_htim htim12 #define adc_tim htim8 +#define hpwm2 htim2 +#define mb_dbg_huart huart6 +#define ustim htim13 +#define hpwm1 htim1 #define UM_LED_GREEN2_Pin GPIO_PIN_2 #define UM_LED_GREEN2_GPIO_Port GPIOE #define CEN_O_Pin GPIO_PIN_3 diff --git a/UPP/Core/PowerMonitor/adc_tools.c b/UPP/Core/PowerMonitor/adc_tools.c index a5ad350..a49d587 100644 --- a/UPP/Core/PowerMonitor/adc_tools.c +++ b/UPP/Core/PowerMonitor/adc_tools.c @@ -11,7 +11,31 @@ // Проверка корректности структуры АЦП #define assert_adc(_adc_) check_null_ptr_2(_adc_, (_adc_)->f.Initialized) - +static void ADC_EnableAllFilters(ADC_Period_t *adc) +{ + for(int i = 0; i < ADC_NUMB_OF_CHANNELS; i++) + { + FILTER_GET_STATE(&adc->filter[i]) = FILTER_ENABLE; + } + FILTER_GET_STATE(&adc->temp_filter[0]) = FILTER_ENABLE; + FILTER_GET_STATE(&adc->temp_filter[1]) = FILTER_ENABLE; +} +static void ADC_InitAllFilters(ADC_Period_t *adc, int coef) +{ + for(int i = 0; i < ADC_NUMB_OF_CHANNELS; i++) + { + FilterAverageInt_Init(&adc->filter[i], coef); + } + + FilterLUTInt_Init(&adc->temp_filter[0], + (int32_t *)adc_temp_quants, + (int32_t *)adc_temp_vals, + sizeof(adc_temp_quants), 0); + FilterLUTInt_Init(&adc->temp_filter[1], + (int32_t *)adc_temp_quants, + (int32_t *)adc_temp_vals, + sizeof(adc_temp_quants), 0); +} /** * @brief Инициализация периодического АЦП. * @param adc Указатель на кастомный хендл АЦП @@ -28,6 +52,9 @@ HAL_StatusTypeDef ADC_Init(ADC_Period_t *adc, TIM_HandleTypeDef *htim, ADC_Handl adc->htim = htim; adc->hadc = hadc; + ADC_InitAllFilters(adc, 10); + + adc->f.AdcRunning = 0; adc->f.DataReady = 0; adc->f.Initialized = 1; @@ -86,6 +113,8 @@ HAL_StatusTypeDef ADC_Start(ADC_Period_t *adc, uint16_t Period) return res; } + ADC_EnableAllFilters(adc); + return res; } /** @@ -105,10 +134,10 @@ HAL_StatusTypeDef ADC_Stop(ADC_Period_t *adc) /** - * @brief Остановка АЦП . + * @brief Обработка АЦП. * @return HAL Status. * @details По факту остановка таймера, который запускает АЦП. Сам АЦП продолжает работу. - * @note Вызывается в . + * @note Вызывается в DMA2_Stream0_IRQHandler() для обработки всего, что пришло по DMA. */ HAL_StatusTypeDef ADC_Handle(ADC_Period_t *adc) { @@ -119,11 +148,31 @@ HAL_StatusTypeDef ADC_Handle(ADC_Period_t *adc) uint16_t *raw = adc->RawData; float *data = adc->Data; + // Фильтрация от шумов для всех каналов for(int i = 0; i < ADC_NUMB_OF_CHANNELS; i++) + { + if(FILTER_GET_STATE(&adc->filter[i]) == FILTER_ENABLE) + { + // заменяем сырое на отфильтровоное сырое + raw[i] = FilterAverageInt_Process(&adc->filter[i], raw[i]); + } + } + // Перерасчеты Напряжений/Токов в единицы измерения + for(int i = 0; i < ADC_TEMP_CHANNELS_START; i++) { ADC_Coefs_t *coefs = &adc->Coefs[i]; data[i] = ((float)(raw[i])-coefs->lZero) * coefs->vMax / (coefs->lMax-coefs->lZero); - } + } + + // Преобразования температуры по таблице + for (int i = ADC_TEMP_CHANNELS_START; i < ADC_NUMB_OF_CHANNELS; i++) + { + data[i] = FilterLUTInt_Process(&adc->temp_filter[i-ADC_TEMP_CHANNELS_START], raw[i]); + } + + + + adc->f.DataReady = 1; return HAL_OK; diff --git a/UPP/Core/PowerMonitor/adc_tools.h b/UPP/Core/PowerMonitor/adc_tools.h index a5923a3..fdc8234 100644 --- a/UPP/Core/PowerMonitor/adc_tools.h +++ b/UPP/Core/PowerMonitor/adc_tools.h @@ -11,7 +11,34 @@ #include "main.h" #define ADC_NUMB_OF_CHANNELS 6 +#define ADC_TEMP_CHANNELS_START 4 +#define ADC_TEMPERATURES_QUANTS \ +{ 2188, 2197, 2206, 2216, 2226, 2236, 2247, 2259, 2271, 2283, \ + 2296, 2310, 2324, 2338, 2354, 2369, 2385, 2402, 2419, 2437, \ + 2455, 2474, 2493, 2513, 2533, 2554, 2575, 2597, 2619, 2641, \ + 2664, 2688, 2711, 2735, 2759, 2784, 2809, 2833, 2859, 2884, \ + 2909, 2935, 2961, 2986, 3012, 3037, 3063, 3089, 3114, 3140, \ + 3165, 3190, 3215, 3239, 3263, 3288, 3312, 3335, 3359, 3381, \ + 3404, 3426, 3448, 3470, 3491, 3512, 3532, 3552, 3572, 3591, \ + 3610, 3628, 3646, 3663, 3681, 3697, 3714, 3729, 3745, 3760, \ + 3775, 3789, 3803, 3817, 3830, 3843, 3855, 3868, 3879, 3891, \ + 3902, 3913, 3924, 3934, 3944, 3954, 3963, 3972, 3981, 3989, \ + 3997, 4005, 4013, 4021, 4028, 4035, 4042, 4049, 4055, 4062, \ + 4068, 4074, 4079, 4085, 4091, 4096} + +#define ADC_TEMPERATURES \ +{ -25, -24, -23, -22, -21, -20, -19, -18, -17, -16, -15, -14, -13, -12, -11, \ + -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, \ + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, \ + 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, \ + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, \ + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, \ + 82, 83, 84, 85, 86, 87, 88, 89, 90} + +static const int32_t adc_temp_vals[] = ADC_TEMPERATURES; +static const int32_t adc_temp_quants[] = ADC_TEMPERATURES_QUANTS; + /** * @brief Коэфициенты канала АЦП для пересчета в единицы измерения */ @@ -36,6 +63,8 @@ typedef struct ADC_Coefs_t Coefs[ADC_NUMB_OF_CHANNELS]; ///< Коэффициенты @ref ADC_Coefs_t float Data[ADC_NUMB_OF_CHANNELS]; ///< Пересчитанные значения АЦП (в Вольтах/Амперах/Градусах) + FilterAverageInt_t filter[ADC_NUMB_OF_CHANNELS]; ///< Фильтр от шумов АЦП + FilterLUTInt_t temp_filter[2]; ///< Коррекция нелинейности датчиков температуры struct { unsigned Initialized:1; diff --git a/UPP/Core/Src/tim.c b/UPP/Core/Src/tim.c index 04ec18c..d273fef 100644 --- a/UPP/Core/Src/tim.c +++ b/UPP/Core/Src/tim.c @@ -186,7 +186,7 @@ void MX_TIM8_Init(void) /* USER CODE END TIM8_Init 1 */ htim8.Instance = TIM8; - htim8.Init.Prescaler = 180-1; + htim8.Init.Prescaler = 0; htim8.Init.CounterMode = TIM_COUNTERMODE_UP; htim8.Init.Period = 1000; htim8.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; diff --git a/UPP/Core/UPP/upp_main.c b/UPP/Core/UPP/upp_main.c index d95628b..2f31926 100644 --- a/UPP/Core/UPP/upp_main.c +++ b/UPP/Core/UPP/upp_main.c @@ -43,7 +43,7 @@ int UPP_Init(void) */ int UPP_PreWhile(void) { - ADC_Start(&adc, 1000); + ADC_Start(&adc, 100); return 0; } diff --git a/UPP/MDK-ARM/UPP.uvoptx b/UPP/MDK-ARM/UPP.uvoptx index 66f3b96..e09e15c 100644 --- a/UPP/MDK-ARM/UPP.uvoptx +++ b/UPP/MDK-ARM/UPP.uvoptx @@ -611,6 +611,30 @@ 0 0 + + 6 + 33 + 1 + 0 + 0 + 0 + ..\AllLibs\MyLibs\MyLibs\Src\filters.c + filters.c + 0 + 0 + + + 6 + 34 + 5 + 0 + 0 + 0 + ..\AllLibs\MyLibs\MyLibs\Inc\filters.h + filters.h + 0 + 0 + @@ -621,7 +645,7 @@ 0 7 - 33 + 35 1 0 0 @@ -633,7 +657,7 @@ 7 - 34 + 36 1 0 0 @@ -645,7 +669,7 @@ 7 - 35 + 37 1 0 0 @@ -657,7 +681,7 @@ 7 - 36 + 38 1 0 0 @@ -669,7 +693,7 @@ 7 - 37 + 39 1 0 0 @@ -681,7 +705,7 @@ 7 - 38 + 40 1 0 0 @@ -693,7 +717,7 @@ 7 - 39 + 41 1 0 0 @@ -705,7 +729,7 @@ 7 - 40 + 42 1 0 0 @@ -717,7 +741,7 @@ 7 - 41 + 43 1 0 0 @@ -729,7 +753,7 @@ 7 - 42 + 44 1 0 0 @@ -741,7 +765,7 @@ 7 - 43 + 45 1 0 0 @@ -753,7 +777,7 @@ 7 - 44 + 46 1 0 0 @@ -773,7 +797,7 @@ 0 8 - 45 + 47 1 0 0 @@ -785,7 +809,7 @@ 8 - 46 + 48 1 0 0 @@ -805,7 +829,7 @@ 0 9 - 47 + 49 1 0 0 @@ -817,7 +841,7 @@ 9 - 48 + 50 1 0 0 @@ -829,7 +853,7 @@ 9 - 49 + 51 1 0 0 @@ -841,7 +865,7 @@ 9 - 50 + 52 1 0 0 @@ -853,7 +877,7 @@ 9 - 51 + 53 1 0 0 @@ -873,7 +897,7 @@ 0 10 - 52 + 54 1 0 0 @@ -885,7 +909,7 @@ 10 - 53 + 55 1 0 0 @@ -897,7 +921,7 @@ 10 - 54 + 56 1 0 0 @@ -909,7 +933,7 @@ 10 - 55 + 57 1 0 0 @@ -921,7 +945,7 @@ 10 - 56 + 58 1 0 0 @@ -933,7 +957,7 @@ 10 - 57 + 59 1 0 0 @@ -945,7 +969,7 @@ 10 - 58 + 60 1 0 0 @@ -957,7 +981,7 @@ 10 - 59 + 61 1 0 0 @@ -969,7 +993,7 @@ 10 - 60 + 62 1 0 0 @@ -981,7 +1005,7 @@ 10 - 61 + 63 1 0 0 @@ -993,7 +1017,7 @@ 10 - 62 + 64 1 0 0 @@ -1005,7 +1029,7 @@ 10 - 63 + 65 1 0 0 @@ -1017,7 +1041,7 @@ 10 - 64 + 66 1 0 0 @@ -1029,7 +1053,7 @@ 10 - 65 + 67 1 0 0 @@ -1041,7 +1065,7 @@ 10 - 66 + 68 1 0 0 @@ -1053,7 +1077,7 @@ 10 - 67 + 69 1 0 0 @@ -1065,7 +1089,7 @@ 10 - 68 + 70 1 0 0 @@ -1077,7 +1101,7 @@ 10 - 69 + 71 1 0 0 @@ -1089,7 +1113,7 @@ 10 - 70 + 72 1 0 0 @@ -1101,7 +1125,7 @@ 10 - 71 + 73 1 0 0 @@ -1113,7 +1137,7 @@ 10 - 72 + 74 1 0 0 @@ -1125,7 +1149,7 @@ 10 - 73 + 75 1 0 0 @@ -1137,7 +1161,7 @@ 10 - 74 + 76 1 0 0 @@ -1149,7 +1173,7 @@ 10 - 75 + 77 1 0 0 @@ -1169,7 +1193,7 @@ 0 11 - 76 + 78 1 0 0 @@ -1189,7 +1213,7 @@ 0 12 - 77 + 79 2 0 0 diff --git a/UPP/MDK-ARM/UPP.uvprojx b/UPP/MDK-ARM/UPP.uvprojx index b8ac044..fdf03ee 100644 --- a/UPP/MDK-ARM/UPP.uvprojx +++ b/UPP/MDK-ARM/UPP.uvprojx @@ -341,7 +341,7 @@ USE_HAL_DRIVER,STM32F427xx - ../Core/Inc;../Drivers/STM32F4xx_HAL_Driver/Inc;../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy;../Drivers/CMSIS/Device/ST/STM32F4xx/Include;../Drivers/CMSIS/Include;../AllLibs/ExtMemory/Inc;../AllLibs/Modbus/Inc;../AllLibs/MyLibs/MyLibs/Inc;../AllLibs/MyLibs/RTT;../AllLibs/PeriphGeneral/Inc;../Core/Configs;..\Core\PowerMonitor;..\Core\Thyristors;..\Core\UPP + ../Core/Inc;../Drivers/STM32F4xx_HAL_Driver/Inc;../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy;../Drivers/CMSIS/Device/ST/STM32F4xx/Include;../Drivers/CMSIS/Include;../AllLibs/ExtMemory/Inc;../AllLibs/Modbus/Inc;../AllLibs/MyLibs/MyLibs/Inc;../AllLibs/MyLibs/RTT;../AllLibs/PeriphGeneral/Inc;../Core/Configs;../Core/PowerMonitor;../Core/Thyristors;../Core/UPP @@ -619,6 +619,16 @@ 5 ..\AllLibs\MyLibs\MyLibs\Inc\trackers.h + + filters.c + 1 + ..\AllLibs\MyLibs\MyLibs\Src\filters.c + + + filters.h + 5 + ..\AllLibs\MyLibs\MyLibs\Inc\filters.h + diff --git a/UPP/UPP.ioc b/UPP/UPP.ioc index 817c3bc..5ea9b96 100644 --- a/UPP/UPP.ioc +++ b/UPP/UPP.ioc @@ -137,7 +137,7 @@ Mcu.Pin8=PF6 Mcu.Pin9=PF7 Mcu.PinsNb=63 Mcu.ThirdPartyNb=0 -Mcu.UserConstants=mb_huart,huart3;mbdbg_htim,htim11;mb_htim,htim12;mb_dbg_huart,huart6;ustim,htim13;mem_hspi,hspi3;hpwm1,htim1;hpwm2,htim2;PWM_CHANNEL_1,TIM_CHANNEL_1;PWM_CHANNEL_2,TIM_CHANNEL_2;PWM_CHANNEL_3,TIM_CHANNEL_3;PWM_CHANNEL_4,TIM_CHANNEL_4;PWM_CHANNEL_5,TIM_CHANNEL_3;PWM_CHANNEL_6,TIM_CHANNEL_4;adc_tim,htim8 +Mcu.UserConstants=mb_huart,huart3;mbdbg_htim,htim11;PWM_CHANNEL_1,TIM_CHANNEL_1;PWM_CHANNEL_2,TIM_CHANNEL_2;PWM_CHANNEL_3,TIM_CHANNEL_3;PWM_CHANNEL_4,TIM_CHANNEL_4;mem_hspi,hspi3;PWM_CHANNEL_5,TIM_CHANNEL_3;PWM_CHANNEL_6,TIM_CHANNEL_4;mb_htim,htim12;adc_tim,htim8;hpwm2,htim2;mb_dbg_huart,huart6;ustim,htim13;hpwm1,htim1 Mcu.UserName=STM32F427ZGTx MxCube.Version=6.12.1 MxDb.Version=DB.6.0.121 @@ -475,7 +475,7 @@ TIM3.Channel-PWM\ Generation4\ CH4=TIM_CHANNEL_4 TIM3.IPParameters=Channel-PWM Generation3 CH3,Channel-PWM Generation4 CH4 TIM8.IPParameters=Prescaler,Period,TIM_MasterSlaveMode,TIM_MasterOutputTrigger TIM8.Period=1000 -TIM8.Prescaler=180-1 +TIM8.Prescaler=0 TIM8.TIM_MasterOutputTrigger=TIM_TRGO_UPDATE TIM8.TIM_MasterSlaveMode=TIM_MASTERSLAVEMODE_DISABLE USART3.IPParameters=VirtualMode diff --git a/Информация для программиста (УПП СП СЭД)/temperature_polynom.py b/Информация для программиста (УПП СП СЭД)/temperature_polynom.py new file mode 100644 index 0000000..2d4f369 --- /dev/null +++ b/Информация для программиста (УПП СП СЭД)/temperature_polynom.py @@ -0,0 +1,204 @@ +import numpy as np +import matplotlib.pyplot as plt + +# Данные: ADC -> Temperature +adc_values = [2188, 2197, 2206, 2216, 2226, 2236, 2247, 2259, 2271, 2283, + 2296, 2310, 2324, 2338, 2354, 2369, 2385, 2402, 2419, 2437, + 2455, 2474, 2493, 2513, 2533, 2554, 2575, 2597, 2619, 2641, + 2664, 2688, 2711, 2735, 2759, 2784, 2809, 2833, 2859, 2884, + 2909, 2935, 2961, 2986, 3012, 3037, 3063, 3089, 3114, 3140, + 3165, 3190, 3215, 3239, 3263, 3288, 3312, 3335, 3359, 3381, + 3404, 3426, 3448, 3470, 3491, 3512, 3532, 3552, 3572, 3591, + 3610, 3628, 3646, 3663, 3681, 3697, 3714, 3729, 3745, 3760, + 3775, 3789, 3803, 3817, 3830, 3843, 3855, 3868, 3879, 3891, + 3902, 3913, 3924, 3934, 3944, 3954, 3963, 3972, 3981, 3989, + 3997, 4005, 4013, 4021, 4028, 4035, 4042, 4049, 4055, 4062, + 4068, 4074, 4079, 4085, 4091, 4096] + +temperatures = [-25, -24, -23, -22, -21, -20, -19, -18, -17, -16, -15, -14, -13, -12, -11, + -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, + 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, + 82, 83, 84, 85, 86, 87, 88, 89, 90] + +# Параметры ограничений +MIN_COEFF_ABS = 1e-5 # Минимальное абсолютное значение коэффициента +MAX_CONDITION_NUMBER = 1e10 # Максимальное число обусловленности + +# Аппроксимация полиномами разных степеней +degrees = [2, 3, 4, 5] +coefficients = {} +filtered_coefficients = {} + +plt.figure(figsize=(16, 12)) + +# График 1: Сравнение аппроксимаций +plt.subplot(2, 3, 1) +plt.plot(adc_values, temperatures, 'ko-', markersize=3, linewidth=1, label='Исходные данные') + +colors = ['red', 'blue', 'green', 'orange'] +for i, degree in enumerate(degrees): + coeffs = np.polyfit(adc_values, temperatures, degree) + coefficients[degree] = coeffs + + # Фильтрация малых коэффициентов + filtered_coeffs = coeffs.copy() + small_coeffs_mask = np.abs(coeffs) < MIN_COEFF_ABS + filtered_coeffs[small_coeffs_mask] = 0 + filtered_coefficients[degree] = filtered_coeffs + + poly = np.poly1d(coeffs) + adc_continuous = np.linspace(min(adc_values), max(adc_values), 500) + temp_predicted = poly(adc_continuous) + + plt.plot(adc_continuous, temp_predicted, color=colors[i], linewidth=2, + label=f'Полином {degree}-й степени') + +plt.xlabel('Значение АЦП') +plt.ylabel('Температура (°C)') +plt.title('Аппроксимация зависимости АЦП → Температура') +plt.legend() +plt.grid(True, alpha=0.3) + +# График 2: Ошибки аппроксимации +plt.subplot(2, 3, 2) +for i, degree in enumerate(degrees): + poly = np.poly1d(coefficients[degree]) + predicted = poly(adc_values) + error = predicted - temperatures + + plt.plot(temperatures, error, 'o-', color=colors[i], markersize=3, + label=f'Ошибка {degree}-й степени') + +plt.xlabel('Температура (°C)') +plt.ylabel('Ошибка (°C)') +plt.title('Ошибки аппроксимации по температуре') +plt.legend() +plt.grid(True, alpha=0.3) + +# График 3: Статистика ошибок +plt.subplot(2, 3, 3) +max_errors = [] +rms_errors = [] + +for degree in degrees: + poly = np.poly1d(coefficients[degree]) + predicted = poly(adc_values) + max_error = np.max(np.abs(predicted - temperatures)) + rms_error = np.sqrt(np.mean((predicted - temperatures)**2)) + + max_errors.append(max_error) + rms_errors.append(rms_error) + +x_pos = np.arange(len(degrees)) +width = 0.35 + +plt.bar(x_pos - width/2, max_errors, width, label='Макс. ошибка', alpha=0.7) +plt.bar(x_pos + width/2, rms_errors, width, label='СКО', alpha=0.7) + +plt.xlabel('Степень полинома') +plt.ylabel('Ошибка (°C)') +plt.title('Статистика ошибок аппроксимации') +plt.xticks(x_pos, degrees) +plt.legend() +plt.grid(True, alpha=0.3) + +# График 4: Сравнение коэффициентов до/после фильтрации +plt.subplot(2, 3, 4) +for degree in degrees: + coeffs = coefficients[degree] + filtered_coeffs = filtered_coefficients[degree] + + # Отображаем только ненулевые коэффициенты + nonzero_indices = np.where(filtered_coeffs != 0)[0] + if len(nonzero_indices) > 0: + plt.semilogy(nonzero_indices, np.abs(filtered_coeffs[nonzero_indices]), 'o-', + label=f'Полином {degree}-й степени', markersize=6) + +plt.axhline(y=MIN_COEFF_ABS, color='r', linestyle='--', alpha=0.7, label=f'Порог {MIN_COEFF_ABS:.0e}') +plt.xlabel('Индекс коэффициента') +plt.ylabel('Абсолютное значение коэффициента') +plt.title('Коэффициенты после фильтрации (логарифмическая шкала)') +plt.legend() +plt.grid(True, alpha=0.3) + +# График 5: Влияние фильтрации на ошибку +plt.subplot(2, 3, 5) +original_errors = [] +filtered_errors = [] + +for degree in degrees: + poly_original = np.poly1d(coefficients[degree]) + poly_filtered = np.poly1d(filtered_coefficients[degree]) + + predicted_original = poly_original(adc_values) + predicted_filtered = poly_filtered(adc_values) + + error_original = np.max(np.abs(predicted_original - temperatures)) + error_filtered = np.max(np.abs(predicted_filtered - temperatures)) + + original_errors.append(error_original) + filtered_errors.append(error_filtered) + +x_pos = np.arange(len(degrees)) +width = 0.35 + +plt.bar(x_pos - width/2, original_errors, width, label='Оригинальные коэф.', alpha=0.7) +plt.bar(x_pos + width/2, filtered_errors, width, label='После фильтрации', alpha=0.7) + +plt.xlabel('Степень полинома') +plt.ylabel('Максимальная ошибка (°C)') +plt.title('Влияние фильтрации коэффициентов на точность') +plt.xticks(x_pos, degrees) +plt.legend() +plt.grid(True, alpha=0.3) + +plt.tight_layout() +plt.show() + +# Вывод численных результатов +print("=" * 80) +print("РЕЗУЛЬТАТЫ АППРОКСИМАЦИИ С ФИЛЬТРАЦИЕЙ КОЭФФИЦИЕНТОВ") +print("=" * 80) + +for degree in degrees: + coeffs = coefficients[degree] + filtered_coeffs = filtered_coefficients[degree] + + poly_original = np.poly1d(coeffs) + poly_filtered = np.poly1d(filtered_coeffs) + + predicted_original = poly_original(adc_values) + predicted_filtered = poly_filtered(adc_values) + + max_error_original = np.max(np.abs(predicted_original - temperatures)) + rms_error_original = np.sqrt(np.mean((predicted_original - temperatures)**2)) + + max_error_filtered = np.max(np.abs(predicted_filtered - temperatures)) + rms_error_filtered = np.sqrt(np.mean((predicted_filtered - temperatures)**2)) + + # Подсчет нулевых коэффициентов + zero_count = np.sum(filtered_coeffs == 0) + total_count = len(filtered_coeffs) + + print(f"\nПолином {degree}-й степени:") + print(f"Максимальная ошибка: {max_error_original:.3f}°C -> {max_error_filtered:.3f}°C") + print(f"Среднеквадратичная ошибка: {rms_error_original:.3f}°C -> {rms_error_filtered:.3f}°C") + print(f"Обнулено коэффициентов: {zero_count}/{total_count}") + + print("Коэффициенты после фильтрации:") + for i, coeff in enumerate(filtered_coeffs): + power = len(filtered_coeffs) - i - 1 + status = "✓" if coeff != 0 else "✗ (обнулен)" + print(f" a_{power} = {coeff:.6e} {status}") + +# Рекомендация +print("\n" + "=" * 80) +print("РЕКОМЕНДАЦИЯ:") +print(f"Порог обнуления коэффициентов: {MIN_COEFF_ABS:.0e}") +print("Полином 3-й степени обеспечивает оптимальный баланс между точностью") +print("и сложностью реализации. Фильтрация малых коэффициентов практически") +print("не влияет на точность, но упрощает реализацию на embedded системах.") +print("=" * 80) \ No newline at end of file diff --git a/Информация для программиста (УПП СП СЭД)/Значения температуры в ед АЦП.xlsx b/Информация для программиста (УПП СП СЭД)/Значения температуры в ед АЦП.xlsx index 392e475..ccdc517 100644 Binary files a/Информация для программиста (УПП СП СЭД)/Значения температуры в ед АЦП.xlsx and b/Информация для программиста (УПП СП СЭД)/Значения температуры в ед АЦП.xlsx differ