|
Простейший цифровой ФНЧ, для конечного массива точек |
|
|
|
Jan 20 2011, 10:37
|

Местный
  
Группа: Свой
Сообщений: 307
Регистрация: 6-02-08
Из: Россия, Екатеринбург
Пользователь №: 34 798

|
Есть массив, в котором записаны значения с АЦП. Напряжения формируют некую "огибающую" Платформа: STM32, сигнал - массив значений с АЦП в вольтах. 1)Подскажите фильтр (алгоритм на Си) чтобы сгладить(усреднить) значения в массиве? 2) Как определить характерные места у огибающей (резкое увеличение значения, резкий спад)
Сообщение отредактировал Ivan Kuznetzov - Jan 20 2011, 11:26
Эскизы прикрепленных изображений
--------------------
Разработчик
|
|
|
|
|
Jan 20 2011, 11:21
|

Знающий
   
Группа: Свой
Сообщений: 648
Регистрация: 11-02-06
Из: Санкт-Петербург
Пользователь №: 14 237

|
Цитата(Ivan Kuznetzov @ Jan 20 2011, 13:37)  Есть массив, в котором записаны значения с АЦП. Напряжения формируют некую "огибающую"
1)Подскажите фильтр чтобы сгладить(усреднить) значения в массиве? Для каждого элемента массива посчитайте среднее значение от окружающих его элементов. Это и есть простейший цифровой ФНЧ. Чем шире окрестность, в которой считается среднее - тем сильнее "сглаживание", но и искажение формы исходного сигнала также сильнее. Если не вдаваться в теорию - вот как-то так.
--------------------
Сделано в Китае. Упаковано в России.
|
|
|
|
|
Jan 20 2011, 12:02
|

Местный
  
Группа: Свой
Сообщений: 307
Регистрация: 6-02-08
Из: Россия, Екатеринбург
Пользователь №: 34 798

|
Demeny, спасибо! функция уже заметно красивей стала!!! Код for (x=1;x<ARRAYSIZE;x++) Pulsearray[x] = (Pulsearray[x-1] + Pulsearray[x+1])/2;
Сообщение отредактировал Ivan Kuznetzov - Jan 20 2011, 12:02
Эскизы прикрепленных изображений
--------------------
Разработчик
|
|
|
|
|
Jan 20 2011, 13:27
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(Ivan Kuznetzov @ Jan 20 2011, 17:02)  Код for (x=1;x<ARRAYSIZE;x++) Pulsearray[x] = (Pulsearray[x-1] + Pulsearray[x+1])/2; Наверное лучше Код Pulsearray[x] = (Pulsearray[x-1] + Pulsearray[x] + Pulsearray[x+1])/3;
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Jan 20 2011, 14:18
|

Знающий
   
Группа: Свой
Сообщений: 580
Регистрация: 3-06-08
Пользователь №: 38 041

|
Есть метод скользящего среднего, считается так: (текущий обработанный результат)=( (предыдущий обработанный результат)*(N-1)/N )+(текущий код АЦП)/N Под кодом АЦП может выступать текущий отсчет необработанной вашей реализации. Собственно точки тогда имеют железную привязку  N=1....и до бесконечности на практике достаточно N до 32, ну и естественно с ростом N теряются подробности сигнала. Так характерные места - величины первой производной. Смотрите постоянно разницу предыдущего отсчета (возможно даже с некоторой глубиной, т е не последний, а предпоследний) и текущего. Ну стравнивайте полученную дельту с порогом или за знаком следите. Возможно понадобится и саму производную усреднять, если у вас по производной какие то критичные вычисления делаются.
|
|
|
|
|
Jan 20 2011, 19:16
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(Ivan Kuznetzov @ Jan 20 2011, 18:55)  AHTOXA, спасибо, действительно красивее!  Да, но так всё равно неправильно  Получается, что для первой точки мы взяли начальные данные, а для остальных - одна из точек (которая x-1) - уже отфильтрованная. Надо либо занычивать её в переменной, либо фильтровать в другой массив. А лучше сделать скользящее среднее, как написал firstvald. Там можно регулировать степень сглаживания.
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Jan 21 2011, 11:01
|
Гуру
     
Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521

|
Код /************************************************************************ * * * Библиотека для цифровой фильтрации. * * Версия: 1.01. * * * * Файл: fir.c Дата создания: 08.07.2010г. * * Последние изменения: 08.07.2010г. * * Сапего Александр Леонидович. (sapegoal@mail.ru) * * * ************************************************************************/
#include "stdint.h"
// Фильтр 2-го порядка исходя из формулы y0^ = a0*(x0+x2)+a1*x1 + b1*y0 + b2*y1 + c1*y0 // где a и b - коэффициенты, c - целая часть y0 // После выполнения производится сдвиг y. // y1 -> y2, y0 -> y1, y0^ -> y0; // // В процедуру передаётся 2 параметра // 1 - указатель на значения, в последовательности: x0,x1,x2,y0,y1,y2 // 2 - указатель на значения коэффициентов в последовательности: a0,a1,b1,b2,c1 // По финишу результат делится на 32768
struct data_s { int16_t x[3],y[3]; // Данные фильтра };
struct coef_s { int16_t a0, a1, b1, b2, c1; // Коэффициенты фильтра };
void fir2_16(uint8_t * data, uint8_t * coef) { struct data_s *d_s; struct coef_s *c_s; int32_t acc; d_s = (struct data_s *) data; c_s = (struct coef_s *) coef; acc = (int32_t)(d_s->x[0] + d_s->x[2]) * (int32_t)c_s->a0; acc += (int32_t)d_s->x[1] * (int32_t)c_s->a1; acc += (int32_t)d_s->y[0] * (int32_t)c_s->b1; acc += (int32_t)d_s->y[1] * (int32_t)c_s->b2; acc >>= 15; acc += d_s->y[0] * c_s->c1; d_s->y[2] = d_s->y[1]; d_s->y[1] = d_s->y[0]; d_s->y[0] = acc; } Код // Фильтр Баттерворта 4 порядка 1000 -> 100; 200 = -30 дб // // 1 звено y0 = 0,061885*(x0+x2) + 0,123770*x1 + 1,048600*y1 - 0,296140*y2 // Коэффициенты a0,a1,b1,b2,c1 = 2028, 4056, 1593, -9704, 1 // 2 звено y0 = 0,077956*(x0+x2) + 0,155913*x1 + 1,320910*y1 - 0,632739*y2 // Коэффициенты a0,a1,b1,b2,c1 = 2554, 5109, 10516, -20734, 1 // int16_t fltr_c1[5] = {2028, 4056, 1593, -9704, 1}, fltr_c2[5] = {2554, 5109, 10516, -20734, 1}; Код fir2_16((uint8_t *)&lin[cnt_line].x[0],(uint8_t *)fltr_c1);// Первое звено фильтра fir2_16((uint8_t *)&lin[cnt_line].y[0],(uint8_t *)fltr_c2);// Второе звено фильтра Так например. ))
|
|
|
|
|
Jan 21 2011, 14:47
|

неотягощённый злом
     
Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643

|
Пробегало давненько: Цитата Код u16_t Yavg;
for(;;) { Yavg -= Yavg/256; Yavg += ADCH; } Запуск и готовность АЦП за Вами. Утверждается, что в старшем байте Yavg получим фильтр НЧ с частотой среза = частоте запуска АЦП/256 с погрешностью обработки <0.5 LSB, по АФЧХ эквивалентный RC цепочке с такой же частотой среза. Почему? Хемминг уже рассказал, у меня лучше не получится.
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
Jan 23 2011, 13:06
|
Гуру
     
Группа: Свой
Сообщений: 2 563
Регистрация: 8-04-05
Из: Nsk
Пользователь №: 3 954

|
Цитата(Ivan Kuznetzov @ Jan 20 2011, 16:37)  1)Подскажите фильтр (алгоритм на Си) чтобы сгладить(усреднить) значения в массиве? 2) Как определить характерные места у огибающей (резкое увеличение значения, резкий спад) 1) demiurg_spb и firstvald уже подсказали простейший IIR фильтр: Код y[0] = x[0]; for (int i = 1; i < len; i++) y[i] = y[i-1] + (x[i] - y[i-1]) * K K = 0.0 .. 1.0, временная постоянная фильтра. Ну и конечно можно (и нужно) заменить на целочисленное умножение и битовый сдвиг вправо. Хотя если надо потом точно определять положение "характерных мест", то fir фильтр (скользящее среднее - частный случай) лучше из-за линейной фазовой характеристики. Кстати, то что предложил SasaVitebsk - fir фильтром не является. 2) искать локальные максимумы на производной, или, если заранее известно то как именно выглядит то что хочется найти, то максимумы корреляционной функции сигнала с тем, что ищем. Цитата(777777) разводить плату надо было так, чтобы программисту не пришлось фильтровать результаты АЦП таким сигнал вполне может быть изначально, и совсем не обязательно вызван шумами на плате.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|