yakuzaa 0 20 января, 2011 Опубликовано 20 января, 2011 (изменено) · Жалоба Есть массив, в котором записаны значения с АЦП. Напряжения формируют некую "огибающую" Платформа: STM32, сигнал - массив значений с АЦП в вольтах. 1)Подскажите фильтр (алгоритм на Си) чтобы сгладить(усреднить) значения в массиве? 2) Как определить характерные места у огибающей (резкое увеличение значения, резкий спад) Изменено 20 января, 2011 пользователем Ivan Kuznetzov Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Demeny 0 20 января, 2011 Опубликовано 20 января, 2011 · Жалоба Есть массив, в котором записаны значения с АЦП. Напряжения формируют некую "огибающую" 1)Подскажите фильтр чтобы сгладить(усреднить) значения в массиве? Для каждого элемента массива посчитайте среднее значение от окружающих его элементов. Это и есть простейший цифровой ФНЧ. Чем шире окрестность, в которой считается среднее - тем сильнее "сглаживание", но и искажение формы исходного сигнала также сильнее. Если не вдаваться в теорию - вот как-то так. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
yakuzaa 0 20 января, 2011 Опубликовано 20 января, 2011 (изменено) · Жалоба Demeny, спасибо! функция уже заметно красивей стала!!! for (x=1;x<ARRAYSIZE;x++) Pulsearray[x] = (Pulsearray[x-1] + Pulsearray[x+1])/2; Изменено 20 января, 2011 пользователем Ivan Kuznetzov Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 15 20 января, 2011 Опубликовано 20 января, 2011 · Жалоба 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; :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
yakuzaa 0 20 января, 2011 Опубликовано 20 января, 2011 · Жалоба AHTOXA, спасибо, действительно красивее! :rolleyes: Вот еще не пойму, как на синем графике найти указанные стрелками точки? дельту измерять какую-нибудь? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
firstvald 22 20 января, 2011 Опубликовано 20 января, 2011 · Жалоба Есть метод скользящего среднего, считается так: (текущий обработанный результат)=( (предыдущий обработанный результат)*(N-1)/N )+(текущий код АЦП)/N Под кодом АЦП может выступать текущий отсчет необработанной вашей реализации. Собственно точки тогда имеют железную привязку :) N=1....и до бесконечности на практике достаточно N до 32, ну и естественно с ростом N теряются подробности сигнала. Так характерные места - величины первой производной. Смотрите постоянно разницу предыдущего отсчета (возможно даже с некоторой глубиной, т е не последний, а предпоследний) и текущего. Ну стравнивайте полученную дельту с порогом или за знаком следите. Возможно понадобится и саму производную усреднять, если у вас по производной какие то критичные вычисления делаются. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 15 20 января, 2011 Опубликовано 20 января, 2011 · Жалоба AHTOXA, спасибо, действительно красивее! :rolleyes: Да, но так всё равно неправильно :) Получается, что для первой точки мы взяли начальные данные, а для остальных - одна из точек (которая x-1) - уже отфильтрованная. Надо либо занычивать её в переменной, либо фильтровать в другой массив. А лучше сделать скользящее среднее, как написал firstvald. Там можно регулировать степень сглаживания. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SapegoAL 0 21 января, 2011 Опубликовано 21 января, 2011 · Жалоба /************************************************************************ * * * Библиотека для цифровой фильтрации. * * Версия: 1.01. * * * * Файл: fir.c Дата создания: 08.07.2010г. * * Последние изменения: 08.07.2010г. * * Сапего Александр Леонидович. ([email protected]) * * * ************************************************************************/ #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);// Второе звено фильтра Так например. )) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
yakuzaa 0 21 января, 2011 Опубликовано 21 января, 2011 · Жалоба SasaVitebsk, поясните пожалуйста как пользоваться? Есть массив, 200 точек. Входные параметры фильтра - это data? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
demiurg_spb 0 21 января, 2011 Опубликовано 21 января, 2011 · Жалоба Пробегало давненько: u16_t Yavg; for(;;) { Yavg -= Yavg/256; Yavg += ADCH; } Запуск и готовность АЦП за Вами. Утверждается, что в старшем байте Yavg получим фильтр НЧ с частотой среза = частоте запуска АЦП/256 с погрешностью обработки <0.5 LSB, по АФЧХ эквивалентный RC цепочке с такой же частотой среза. Почему? Хемминг уже рассказал, у меня лучше не получится. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
777777 0 23 января, 2011 Опубликовано 23 января, 2011 · Жалоба Платформа: STM32, сигнал - массив значений с АЦП в вольтах. 1)Подскажите фильтр (алгоритм на Си) чтобы сгладить(усреднить) значения в массиве? Если вы работаете в серьезной фирме, а не в кружке "умелые руки" при районном доме пионеров, то разводить плату надо было так, чтобы программисту не пришлось фильтровать результаты АЦП. Как именно разводить - написано в любом учебнике схемотехники. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_pv 61 23 января, 2011 Опубликовано 23 января, 2011 · Жалоба 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) искать локальные максимумы на производной, или, если заранее известно то как именно выглядит то что хочется найти, то максимумы корреляционной функции сигнала с тем, что ищем. разводить плату надо было так, чтобы программисту не пришлось фильтровать результаты АЦП таким сигнал вполне может быть изначально, и совсем не обязательно вызван шумами на плате. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
demiurg_spb 0 24 января, 2011 Опубликовано 24 января, 2011 · Жалоба Если вы работаете в серьезной фирме, а не в кружке "умелые руки" при районном доме пионеров, то разводить плату надо было так, чтобы программисту не пришлось фильтровать результаты АЦП. Как именно разводить - написано в любом учебнике схемотехники.Ага и всем-всем заказчикам отрубать руки если они датчик (TC или RTD например) подключат проводом без экрана и не дай Бог вблизи силовых кабелей или или или.......... :-) В любом нормальном промышленном измерительном оборудовании имеется возможность регулировки степени фильтрации сигнала так-сказать по месту применения. Так-что схемотехника+трассировка - отдельно, грамотный софт - отдельно и перекладывать с больной головы на здоровую не стоит. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GetSmart 0 24 января, 2011 Опубликовано 24 января, 2011 · Жалоба В Саратове живут суровые профэссианалы Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
777777 0 24 января, 2011 Опубликовано 24 января, 2011 · Жалоба В Саратове живут суровые профэссианалы Увы - не все. Почему-то считается немерянной крутизной развести плату минимального размера, сэкономив на конденсаторах по питанию, землях и размещении элементов - главное упихать их поплотнее, а то, что АЦП шумит на 4 разряда - это фигня, программисты отфильтруют. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться