реклама на сайте
подробности

 
 
> Простейший цифровой ФНЧ, для конечного массива точек
Ivan Kuznetzov
сообщение Jan 20 2011, 10:37
Сообщение #1


Местный
***

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



Есть массив, в котором записаны значения с АЦП. Напряжения формируют некую "огибающую"

Платформа: STM32, сигнал - массив значений с АЦП в вольтах.

1)Подскажите фильтр (алгоритм на Си) чтобы сгладить(усреднить) значения в массиве?
2) Как определить характерные места у огибающей (резкое увеличение значения, резкий спад)



Сообщение отредактировал Ivan Kuznetzov - Jan 20 2011, 11:26
Эскизы прикрепленных изображений
Прикрепленное изображение
 


--------------------
Разработчик
Go to the top of the page
 
+Quote Post
3 страниц V   1 2 3 >  
Start new topic
Ответов (1 - 14)
Demeny
сообщение Jan 20 2011, 11:21
Сообщение #2


Знающий
****

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



Цитата(Ivan Kuznetzov @ Jan 20 2011, 13:37) *
Есть массив, в котором записаны значения с АЦП. Напряжения формируют некую "огибающую"

1)Подскажите фильтр чтобы сгладить(усреднить) значения в массиве?

Для каждого элемента массива посчитайте среднее значение от окружающих его элементов.
Это и есть простейший цифровой ФНЧ. Чем шире окрестность, в которой считается среднее - тем сильнее "сглаживание", но и искажение формы исходного сигнала также сильнее.
Если не вдаваться в теорию - вот как-то так.


--------------------
Сделано в Китае. Упаковано в России.
Go to the top of the page
 
+Quote Post
Ivan Kuznetzov
сообщение Jan 20 2011, 12:02
Сообщение #3


Местный
***

Группа: Свой
Сообщений: 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
Эскизы прикрепленных изображений
Прикрепленное изображение
 


--------------------
Разработчик
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Jan 20 2011, 13:27
Сообщение #4


фанат дивана
******

Группа: Свой
Сообщений: 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;
sm.gif


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
Ivan Kuznetzov
сообщение Jan 20 2011, 13:55
Сообщение #5


Местный
***

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



AHTOXA, спасибо, действительно красивее! rolleyes.gif

Вот еще не пойму, как на синем графике найти указанные стрелками точки? дельту измерять какую-нибудь? wacko.gif


Эскизы прикрепленных изображений
Прикрепленное изображение
 


--------------------
Разработчик
Go to the top of the page
 
+Quote Post
firstvald
сообщение Jan 20 2011, 14:18
Сообщение #6


Знающий
****

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



Есть метод скользящего среднего, считается так:

(текущий обработанный результат)=( (предыдущий обработанный результат)*(N-1)/N )+(текущий код АЦП)/N

Под кодом АЦП может выступать текущий отсчет необработанной вашей реализации. Собственно точки тогда имеют железную привязку sm.gif

N=1....и до бесконечности

на практике достаточно N до 32, ну и естественно с ростом N теряются подробности сигнала.


Так характерные места - величины первой производной. Смотрите постоянно разницу предыдущего отсчета (возможно даже с некоторой глубиной, т е не последний, а предпоследний) и текущего. Ну стравнивайте полученную дельту с порогом или за знаком следите. Возможно понадобится и саму производную усреднять, если у вас по производной какие то критичные вычисления делаются.
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Jan 20 2011, 19:16
Сообщение #7


фанат дивана
******

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



Цитата(Ivan Kuznetzov @ Jan 20 2011, 18:55) *
AHTOXA, спасибо, действительно красивее! rolleyes.gif

Да, но так всё равно неправильно sm.gif Получается, что для первой точки мы взяли начальные данные, а для остальных - одна из точек (которая x-1) - уже отфильтрованная. Надо либо занычивать её в переменной, либо фильтровать в другой массив.
А лучше сделать скользящее среднее, как написал firstvald. Там можно регулировать степень сглаживания.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Jan 21 2011, 11:01
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 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);// Второе звено фильтра


Так например. ))
Go to the top of the page
 
+Quote Post
Ivan Kuznetzov
сообщение Jan 21 2011, 14:24
Сообщение #9


Местный
***

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



SasaVitebsk, поясните пожалуйста как пользоваться? Есть массив, 200 точек. Входные параметры фильтра - это data?


--------------------
Разработчик
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Jan 21 2011, 14:47
Сообщение #10


неотягощённый злом
******

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



Пробегало давненько:
Цитата
Код
u16_t Yavg;

for(;;)
{
   Yavg -= Yavg/256;
   Yavg += ADCH;
}


Запуск и готовность АЦП за Вами.
Утверждается, что в старшем байте Yavg получим фильтр НЧ с частотой среза = частоте запуска АЦП/256
с погрешностью обработки <0.5 LSB, по АФЧХ эквивалентный RC цепочке с такой же частотой среза.

Почему? Хемминг уже рассказал, у меня лучше не получится.


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
777777
сообщение Jan 23 2011, 10:58
Сообщение #11


Профессионал
*****

Группа: Участник
Сообщений: 1 091
Регистрация: 25-07-07
Из: Саратов
Пользователь №: 29 357



Цитата(Ivan Kuznetzov @ Jan 20 2011, 13:37) *
Платформа: STM32, сигнал - массив значений с АЦП в вольтах.

1)Подскажите фильтр (алгоритм на Си) чтобы сгладить(усреднить) значения в массиве?

Если вы работаете в серьезной фирме, а не в кружке "умелые руки" при районном доме пионеров, то разводить плату надо было так, чтобы программисту не пришлось фильтровать результаты АЦП. Как именно разводить - написано в любом учебнике схемотехники.
Go to the top of the page
 
+Quote Post
_pv
сообщение Jan 23 2011, 13:06
Сообщение #12


Гуру
******

Группа: Свой
Сообщений: 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)
разводить плату надо было так, чтобы программисту не пришлось фильтровать результаты АЦП

таким сигнал вполне может быть изначально, и совсем не обязательно вызван шумами на плате.
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Jan 24 2011, 10:20
Сообщение #13


неотягощённый злом
******

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



Цитата(777777 @ Jan 23 2011, 13:58) *
Если вы работаете в серьезной фирме, а не в кружке "умелые руки" при районном доме пионеров, то разводить плату надо было так, чтобы программисту не пришлось фильтровать результаты АЦП. Как именно разводить - написано в любом учебнике схемотехники.
Ага и всем-всем заказчикам отрубать руки если они датчик (TC или RTD например) подключат проводом без экрана и не дай Бог вблизи силовых кабелей или или или.......... :-)
В любом нормальном промышленном измерительном оборудовании имеется возможность регулировки степени фильтрации сигнала так-сказать по месту применения. Так-что схемотехника+трассировка - отдельно, грамотный софт - отдельно и перекладывать с больной головы на здоровую не стоит.


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Jan 24 2011, 11:15
Сообщение #14


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



В Саратове живут суровые профэссианалы biggrin.gif


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
777777
сообщение Jan 24 2011, 13:04
Сообщение #15


Профессионал
*****

Группа: Участник
Сообщений: 1 091
Регистрация: 25-07-07
Из: Саратов
Пользователь №: 29 357



Цитата(GetSmart @ Jan 24 2011, 14:15) *
В Саратове живут суровые профэссианалы biggrin.gif

Увы - не все. Почему-то считается немерянной крутизной развести плату минимального размера, сэкономив на конденсаторах по питанию, землях и размещении элементов - главное упихать их поплотнее, а то, что АЦП шумит на 4 разряда - это фигня, программисты отфильтруют.
Go to the top of the page
 
+Quote Post

3 страниц V   1 2 3 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 18th July 2025 - 06:15
Рейтинг@Mail.ru


Страница сгенерированна за 0.01522 секунд с 7
ELECTRONIX ©2004-2016