Тестирование фильтров с шумным сигналом на АЦП

И на рабочем компе mexw64 не блокируется...
This commit is contained in:
Razvalyaev 2025-11-11 13:05:05 +03:00
parent 5b3eff4041
commit 3614e8f8c3
10 changed files with 44 additions and 117 deletions

View File

@ -148,7 +148,7 @@ echo ===========================
:: 1. ПРЕЖДЕ ЧЕМ КОМПИЛИРОВАТЬ - ВЫГРУЗИТЬ СТАРЫЙ ФАЙЛ :: 1. ПРЕЖДЕ ЧЕМ КОМПИЛИРОВАТЬ - ВЫГРУЗИТЬ СТАРЫЙ ФАЙЛ
:: 2. Компиляция с флагами для MSVC :: 2. Компиляция с флагами для MSVC
:: set LINK_EMBEDDED=/BASE:0x10000000 /FIXED:NO /FILEALIGN:0x1000 /FORCE:MULTIPLE /DYNAMICBASE:NO :: set LINK_EMBEDDED=/BASE:0x00000000 /FIXED:NO /FILEALIGN:0x1000 /FORCE:MULTIPLE /DYNAMICBASE:NO
set C_EMBEDDED="-w" set C_EMBEDDED="-w"
mex %output% %defines% %includes% %codes% %debug% CFLAGS="$CFLAGS %C_EMBEDDED%" LINKFLAGS="$LINKFLAGS %LINK_EMBEDDED%" mex %output% %defines% %includes% %codes% %debug% CFLAGS="$CFLAGS %C_EMBEDDED%" LINKFLAGS="$LINKFLAGS %LINK_EMBEDDED%"
echo %DATE% %TIME% echo %DATE% %TIME%

View File

@ -59,7 +59,7 @@ void app_writeOutputBuffer(real_T* Buffer) {
} }
extern ADC_Period_t adc; extern ADC_Periodic_t adc;
for(int i = 0; i < 6; i++) for(int i = 0; i < 6; i++)
{ {
WriteOutputArray(adc.Data[i], 1, i); WriteOutputArray(adc.Data[i], 1, i);

Binary file not shown.

@ -1 +1 @@
Subproject commit 3b162c9f8cdbcf8606d1b96ea2b26b23e2e9c290 Subproject commit 9b9969dd7ce85e3e317e6fef71c9e1e591d52e46

View File

@ -36,52 +36,17 @@
#ifdef INCLUDE_TRACKERS_LIB #ifdef INCLUDE_TRACKERS_LIB
#include "trackers.h" #include "trackers.h"
#else #else
#define TrackerTypeDef(num_user_vars) void *
#define num_of_usercnts(_user_) 0
#define assert_tracecnt(_cntstruct_, _uservarnumb_) 0
#define if_assert_usertracker(_cntstruct_, _uservarnumb_) if(0)
#define tern_assert_usertracker(_cntstruct_, _uservarnumb_) 0
#define TrackerGet_Ok(_cntstruct_) dummy
#define TrackerGet_Err(_cntstruct_) dummy
#define TrackerGet_Warn(_cntstruct_) dummy
#define TrackerGet_User(_cntstruct_, _uservarnumb_) dummy
#define TrackerCnt_Ok(_cntstruct_)
#define TrackerCnt_Err(_cntstruct_)
#define TrackerCnt_Warn(_cntstruct_)
#define TrackerCnt_User(_cntstruct_, _uservarnumb_)
#define TrackerWrite_User(_cntstruct_, _uservarnumb_, _val_)
#define TrackerClear_All(_cntstruct_)
#define TrackerClear_Ok(_cntstruct_)
#define TrackerClear_Err(_cntstruct_)
#define TrackerClear_Warn(_cntstruct_)
#define TrackerClear_User(_cntstruct_)
#define TrackerClear_UserAll(_cntstruct_)
#endif #endif
#ifdef INCLUDE_TRACE_LIB #ifdef INCLUDE_TRACE_LIB
#include "trace.h" #include "trace.h"
#else #else
#define my_printf(...)
#define log_printf(TAG, fmt, ...)
#define TRACE_GPIO_SET(_gpio_,_pin_)
#define TRACE_GPIO_RESET(_gpio_,_pin_)
#define RTT_FlashPrepare(...)
#define RTT_EraseFlash(...) 0
#define RTT_SaveToFlash(...) 0
#define RTT_ReadFromFlash(...) 0
#define HF_CheckRecovered(...) 0
#define HF_HandleFault(...)
#endif #endif
#ifdef INCLUDE_GEN_OPTIMIZER #ifdef INCLUDE_GEN_OPTIMIZER
#include "gen_optimizer.h" #include "gen_optimizer.h"
#else #else
#define GenOptimizer_t void*
#define GenOptimizer_Init(opt, n_params, n_cand, n_best, iq_mutation, start_params)
#define GenOptimizer_Step(opt, params, LossFunc)
#define PARAM_SCALE_Q16(x, min_val, max_val) (x)
#define PARAM_UNSCALE_Q16(q16_val, min_val, max_val) (q16_val)
#endif #endif
@ -89,60 +54,12 @@
#ifdef INCLUDE_BENCH_TIME #ifdef INCLUDE_BENCH_TIME
#include "bench_time.h" #include "bench_time.h"
#else //BENCH_TIME_ENABLE #else //BENCH_TIME_ENABLE
#define BenchTime_Init()
#define BenchTime_Start(channel, ticks, tick_period) 0
#define BenchTime_End(channel, ticks) 0
#define BenchTime_GetMin(channel) 0
#define BenchTime_GetMax(channel) 0
#define BenchTime_GetAverage(channel) 0
#define BenchTime_GetCount(channel) 0
#define BenchTime_GetLast(channel) 0
#define BenchTime_ResetStats(channel)
#endif //BENCH_TIME_ENABLE #endif //BENCH_TIME_ENABLE
#ifdef INCLUDE_FILTERS #ifdef INCLUDE_FILTERS
#include "filters.h" #include "filters.h"
#else //INCLUDE_FILTERS #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 #endif //INCLUDE_FILTERS

View File

@ -11,18 +11,18 @@
// Проверка корректности структуры АЦП // Проверка корректности структуры АЦП
#define assert_adc(_adc_) check_null_ptr_2(_adc_, (_adc_)->f.Initialized) #define assert_adc(_adc_) check_null_ptr_2(_adc_, (_adc_)->f.Initialized)
static void ADC_EnableAllFilters(ADC_Period_t *adc) static void ADC_EnableAllFilters(ADC_Periodic_t *adc)
{ {
for(int i = 0; i < ADC_NUMB_OF_CHANNELS; i++) for(int i = 0; i < ADC_NUMB_OF_CHANNELS; i++)
{ {
FILTER_GET_STATE(&adc->filter[i]) = FILTER_ENABLE; Filter_Start(&adc->filter[i]);
} }
} }
static void ADC_InitAllFilters(ADC_Period_t *adc, int coef) static void ADC_InitAllFilters(ADC_Periodic_t *adc)
{ {
for(int i = 0; i < ADC_NUMB_OF_CHANNELS; i++) for(int i = 0; i < ADC_NUMB_OF_CHANNELS; i++)
{ {
FilterAverageInt_Init(&adc->filter[i], coef); Filter_Init(&adc->filter[i], Filter_Coef);
} }
FilterLUTInt_Init(&adc->temp_filter[0], FilterLUTInt_Init(&adc->temp_filter[0],
@ -41,7 +41,7 @@ static void ADC_InitAllFilters(ADC_Period_t *adc, int coef)
* @param hadc Указатель на HAL хендл АЦП * @param hadc Указатель на HAL хендл АЦП
* @return HAL Status. * @return HAL Status.
*/ */
HAL_StatusTypeDef ADC_Init(ADC_Period_t *adc, TIM_HandleTypeDef *htim, ADC_HandleTypeDef *hadc) HAL_StatusTypeDef ADC_Init(ADC_Periodic_t *adc, TIM_HandleTypeDef *htim, ADC_HandleTypeDef *hadc)
{ {
HAL_StatusTypeDef res; HAL_StatusTypeDef res;
if(check_null_ptr_2(htim, hadc)) if(check_null_ptr_2(htim, hadc))
@ -50,8 +50,7 @@ HAL_StatusTypeDef ADC_Init(ADC_Period_t *adc, TIM_HandleTypeDef *htim, ADC_Handl
adc->htim = htim; adc->htim = htim;
adc->hadc = hadc; adc->hadc = hadc;
ADC_InitAllFilters(adc, 10); ADC_InitAllFilters(adc);
adc->f.AdcRunning = 0; adc->f.AdcRunning = 0;
adc->f.DataReady = 0; adc->f.DataReady = 0;
@ -68,7 +67,7 @@ HAL_StatusTypeDef ADC_Init(ADC_Period_t *adc, TIM_HandleTypeDef *htim, ADC_Handl
* @param levelMax Максимальный уровень АЦП (в квантах АЦП) * @param levelMax Максимальный уровень АЦП (в квантах АЦП)
* @return HAL Status. * @return HAL Status.
*/ */
HAL_StatusTypeDef ADC_ConfigChannel(ADC_Period_t *adc, int ChNumb, uint16_t levelZero, float valueMax, uint16_t levelMax) HAL_StatusTypeDef ADC_ConfigChannel(ADC_Periodic_t *adc, int ChNumb, uint16_t levelZero, float valueMax, uint16_t levelMax)
{ {
HAL_StatusTypeDef res; HAL_StatusTypeDef res;
if(assert_adc(adc)) if(assert_adc(adc))
@ -89,7 +88,7 @@ HAL_StatusTypeDef ADC_ConfigChannel(ADC_Period_t *adc, int ChNumb, uint16_t leve
* @return HAL Status. * @return HAL Status.
* @details Запускает АЦП с частотой дискретизации на которую настроен таймер adc_tim. * @details Запускает АЦП с частотой дискретизации на которую настроен таймер adc_tim.
*/ */
HAL_StatusTypeDef ADC_Start(ADC_Period_t *adc, uint16_t Period) HAL_StatusTypeDef ADC_Start(ADC_Periodic_t *adc, uint16_t Period)
{ {
HAL_StatusTypeDef res; HAL_StatusTypeDef res;
if(assert_adc(adc)) if(assert_adc(adc))
@ -111,9 +110,9 @@ HAL_StatusTypeDef ADC_Start(ADC_Period_t *adc, uint16_t Period)
return res; return res;
} }
//ADC_EnableAllFilters(adc); ADC_EnableAllFilters(adc);
FILTER_GET_STATE(&adc->temp_filter[0]) = FILTER_ENABLE; Filter_Start(&adc->temp_filter[0]);
FILTER_GET_STATE(&adc->temp_filter[1]) = FILTER_ENABLE; Filter_Start(&adc->temp_filter[1]);
return res; return res;
} }
@ -123,7 +122,7 @@ HAL_StatusTypeDef ADC_Start(ADC_Period_t *adc, uint16_t Period)
* @return HAL Status. * @return HAL Status.
* @details По факту остановка таймера, который запускает АЦП. Сам АЦП продолжает работу. * @details По факту остановка таймера, который запускает АЦП. Сам АЦП продолжает работу.
*/ */
HAL_StatusTypeDef ADC_Stop(ADC_Period_t *adc) HAL_StatusTypeDef ADC_Stop(ADC_Periodic_t *adc)
{ {
if(assert_adc(adc)) if(assert_adc(adc))
return HAL_ERROR; return HAL_ERROR;
@ -139,7 +138,7 @@ HAL_StatusTypeDef ADC_Stop(ADC_Period_t *adc)
* @details По факту остановка таймера, который запускает АЦП. Сам АЦП продолжает работу. * @details По факту остановка таймера, который запускает АЦП. Сам АЦП продолжает работу.
* @note Вызывается в DMA2_Stream0_IRQHandler() для обработки всего, что пришло по DMA. * @note Вызывается в DMA2_Stream0_IRQHandler() для обработки всего, что пришло по DMA.
*/ */
HAL_StatusTypeDef ADC_Handle(ADC_Period_t *adc) HAL_StatusTypeDef ADC_Handle(ADC_Periodic_t *adc)
{ {
if(assert_adc(adc)) if(assert_adc(adc))
return HAL_ERROR; return HAL_ERROR;
@ -151,10 +150,10 @@ HAL_StatusTypeDef ADC_Handle(ADC_Period_t *adc)
// Фильтрация от шумов для всех каналов // Фильтрация от шумов для всех каналов
for(int i = 0; i < ADC_NUMB_OF_CHANNELS; i++) for(int i = 0; i < ADC_NUMB_OF_CHANNELS; i++)
{ {
if(FILTER_GET_STATE(&adc->filter[i]) == FILTER_ENABLE) if(Filter_GetState(&adc->filter[i]) == FILTER_ENABLE)
{ {
// заменяем сырое на отфильтровоное сырое // заменяем сырое на отфильтровоное сырое
raw[i] = FilterAverageInt_Process(&adc->filter[i], raw[i]); raw[i] = Filter_Process(&adc->filter[i], raw[i]);
} }
} }
// Перерасчеты Напряжений/Токов в единицы измерения // Перерасчеты Напряжений/Токов в единицы измерения
@ -182,7 +181,7 @@ HAL_StatusTypeDef ADC_Handle(ADC_Period_t *adc)
/** /**
* @brief Сбор статистики. * @brief Сбор статистики.
*/ */
void ADC_UpdateStatistics(ADC_Period_t *adc, uint8_t channel, float value) void ADC_UpdateStatistics(ADC_Periodic_t *adc, uint8_t channel, float value)
{ {
if(assert_adc(adc)) if(assert_adc(adc))
return; return;
@ -221,7 +220,7 @@ void ADC_UpdateStatistics(ADC_Period_t *adc, uint8_t channel, float value)
/** /**
* @brief Сброс статистики. * @brief Сброс статистики.
*/ */
void ADC_ResetStatistics(ADC_Period_t *adc, uint8_t channel) void ADC_ResetStatistics(ADC_Periodic_t *adc, uint8_t channel)
{ {
if (channel < ADC_NUMB_OF_REGULAR_CHANNELS) { if (channel < ADC_NUMB_OF_REGULAR_CHANNELS) {
memset(&adc->Stat[channel], 0, sizeof(ADC_Statistics)); memset(&adc->Stat[channel], 0, sizeof(ADC_Statistics));

View File

@ -40,6 +40,11 @@
static const int32_t adc_temp_vals[] = ADC_TEMPERATURES; static const int32_t adc_temp_vals[] = ADC_TEMPERATURES;
static const int32_t adc_temp_quants[] = ADC_TEMPERATURES_QUANTS; static const int32_t adc_temp_quants[] = ADC_TEMPERATURES_QUANTS;
#define Filter_t FilterAverageInt_t
#define Filter_Init FilterAverageInt_Init
#define Filter_Process FilterAverageInt_Process
#define Filter_Coef 10, FILTER_MODE_DEFAULT
/** /**
* @brief Коэфициенты канала АЦП для пересчета в единицы измерения * @brief Коэфициенты канала АЦП для пересчета в единицы измерения
*/ */
@ -77,7 +82,7 @@ typedef struct
// Data and calculation // Data and calculation
uint16_t RawData[ADC_NUMB_OF_CHANNELS]; ///< Сырые значения АЦП uint16_t RawData[ADC_NUMB_OF_CHANNELS]; ///< Сырые значения АЦП
ADC_Coefs_t Coefs[ADC_NUMB_OF_REGULAR_CHANNELS]; ///< Коэффициенты @ref ADC_Coefs_t для регулярных каналов (не температуры) ADC_Coefs_t Coefs[ADC_NUMB_OF_REGULAR_CHANNELS]; ///< Коэффициенты @ref ADC_Coefs_t для регулярных каналов (не температуры)
FilterAverageInt_t filter[ADC_NUMB_OF_CHANNELS]; ///< Фильтр от шумов АЦП Filter_t filter[ADC_NUMB_OF_CHANNELS]; ///< Фильтр от шумов АЦП
FilterLUTInt_t temp_filter[2]; ///< Коррекция нелинейности датчиков температуры FilterLUTInt_t temp_filter[2]; ///< Коррекция нелинейности датчиков температуры
float Data[ADC_NUMB_OF_CHANNELS]; ///< Пересчитанные значения АЦП (в Вольтах/Амперах) float Data[ADC_NUMB_OF_CHANNELS]; ///< Пересчитанные значения АЦП (в Вольтах/Амперах)
@ -90,21 +95,21 @@ typedef struct
unsigned DataReady:1; unsigned DataReady:1;
}f; ///< Флаги }f; ///< Флаги
uint32_t LastTick; // Время последнего преобразования uint32_t LastTick; // Время последнего преобразования
}ADC_Period_t; }ADC_Periodic_t;
/* Инициализация периодического АЦП */ /* Инициализация периодического АЦП */
HAL_StatusTypeDef ADC_Init(ADC_Period_t *adc, TIM_HandleTypeDef *htim, ADC_HandleTypeDef *hadc); HAL_StatusTypeDef ADC_Init(ADC_Periodic_t *adc, TIM_HandleTypeDef *htim, ADC_HandleTypeDef *hadc);
/* Конфигуарция канала АЦП. */ /* Конфигуарция канала АЦП. */
HAL_StatusTypeDef ADC_ConfigChannel(ADC_Period_t *adc, int ChNumb, uint16_t levelZero, float valueMax, uint16_t levelMax); HAL_StatusTypeDef ADC_ConfigChannel(ADC_Periodic_t *adc, int ChNumb, uint16_t levelZero, float valueMax, uint16_t levelMax);
/* Запуск АЦП. */ /* Запуск АЦП. */
HAL_StatusTypeDef ADC_Start(ADC_Period_t *adc, uint16_t Period); HAL_StatusTypeDef ADC_Start(ADC_Periodic_t *adc, uint16_t Period);
/* Остановка АЦП. */ /* Остановка АЦП. */
HAL_StatusTypeDef ADC_Stop(ADC_Period_t *adc); HAL_StatusTypeDef ADC_Stop(ADC_Periodic_t *adc);
/* Остановка АЦП . */ /* Остановка АЦП . */
HAL_StatusTypeDef ADC_Handle(ADC_Period_t *adc); HAL_StatusTypeDef ADC_Handle(ADC_Periodic_t *adc);
#endif //_ADC_TOOLS_H_ #endif //_ADC_TOOLS_H_

View File

@ -102,6 +102,14 @@ void ZC_ProcessChannel(ZeroCross_Handle_t *zc, uint8_t channel, float value, uin
ZC_Channel_t *zc_ch = &zc->Channel[channel]; ZC_Channel_t *zc_ch = &zc->Channel[channel];
zc_ch->CurrentValue = value; zc_ch->CurrentValue = value;
// Фильтрация дребезга
if(zc_ch->DebounceCounter)
{
zc_ch->DebounceCounter--;
return;
}
// Детектирование rising edge (отрицательное -> положительное) // Детектирование rising edge (отрицательное -> положительное)
if ((zc_ch->LastValue <= -zc->Hysteresis) && if ((zc_ch->LastValue <= -zc->Hysteresis) &&
(value >= zc->Hysteresis)) { (value >= zc->Hysteresis)) {

View File

@ -12,7 +12,7 @@
#include "adc_tools.h" #include "adc_tools.h"
#include "zero_cross.h" #include "zero_cross.h"
ADC_Period_t adc; ADC_Periodic_t adc;
ZeroCross_Handle_t hzc; ZeroCross_Handle_t hzc;
uint32_t ZC_Detected[ZC_MAX_CHANNELS] = {0}; uint32_t ZC_Detected[ZC_MAX_CHANNELS] = {0};
#define ADC_CHANNEL_UBA 0 #define ADC_CHANNEL_UBA 0
@ -34,8 +34,6 @@ int UPP_Init(void)
ADC_ConfigChannel(&adc, ADC_CHANNEL_UAC, 2048, 1216, 4095); ADC_ConfigChannel(&adc, ADC_CHANNEL_UAC, 2048, 1216, 4095);
ADC_ConfigChannel(&adc, ADC_CHANNEL_IC, 2048, 53, 4095); ADC_ConfigChannel(&adc, ADC_CHANNEL_IC, 2048, 53, 4095);
ADC_ConfigChannel(&adc, ADC_CHANNEL_IA, 2048, 53, 4095); ADC_ConfigChannel(&adc, ADC_CHANNEL_IA, 2048, 53, 4095);
ADC_ConfigChannel(&adc, ADC_CHANNEL_TEMP1, 2554, 90, 4095);
ADC_ConfigChannel(&adc, ADC_CHANNEL_TEMP2, 2554, 90, 4095);
ZC_Init(&hzc, ZC_MAX_CHANNELS, 10, 3); ZC_Init(&hzc, ZC_MAX_CHANNELS, 10, 3);
ZC_ConfigChannel(&hzc, 0, ZC_BOTH_EDGES); ZC_ConfigChannel(&hzc, 0, ZC_BOTH_EDGES);

View File

@ -17,8 +17,8 @@
<TargetCommonOption> <TargetCommonOption>
<Device>STM32F427ZGTx</Device> <Device>STM32F427ZGTx</Device>
<Vendor>STMicroelectronics</Vendor> <Vendor>STMicroelectronics</Vendor>
<PackID>Keil.STM32F4xx_DFP.2.16.0</PackID> <PackID>Keil.STM32F4xx_DFP.2.17.1</PackID>
<PackURL>http://www.keil.com/pack/</PackURL> <PackURL>https://www.keil.com/pack/</PackURL>
<Cpu>IRAM(0x20000000-0x2002FFFF) IRAM2(0x10000000-0x1000FFFF) IROM(0x8000000-0x80FFFFF) CLOCK(25000000) FPU2 CPUTYPE("Cortex-M4") TZ</Cpu> <Cpu>IRAM(0x20000000-0x2002FFFF) IRAM2(0x10000000-0x1000FFFF) IROM(0x8000000-0x80FFFFF) CLOCK(25000000) FPU2 CPUTYPE("Cortex-M4") TZ</Cpu>
<FlashUtilSpec></FlashUtilSpec> <FlashUtilSpec></FlashUtilSpec>
<StartupFile></StartupFile> <StartupFile></StartupFile>