Цитата(ZVE @ Sep 17 2009, 14:18)

Да покажите пример пожалуйста....
Я очень сильно упрощу. Те кто владеют теорией - пусть лучше не читают.

Основная цель будет - показать, что всё не так уж страшно.

Кто хочет глубже - без учебников не обойтись. Я не буду касаться таких свойств фильтров как фазовые искажения, импульсная х-ка и т.п. Только частотная и амплитудная.
Представим себе, что у нас входной сигнал 1200 Гц. Мы его принимаем на АЦП AVR. В связи с тем, что АЦП AVR работает лишь с положительным сигналом, нам пришлось его пропустить ч/з разделительный конденсатор и выставить резисторами 0.5 от опорного напряжения (типичный случай). В результате мы получаем синус от 0 до 1.1V(опора) max, что составит 0-1023 в единицах АЦП. Но для дальнейших расчтётов нам лучше работать с сигналом имеющим знак. Можно, не мудрствуя лукаво вычесть 512 и получить сигнал +/- 512. Но, резистивный делитель может быть сыставлен не совсем точно (например 0.6V) и в результате мы получим сдвинутый сигнал и соответственно постоянную составляющую в нём. Плюс, допустим мы хотим зарезать сетевые помехи (50 и 100 Гц) и какие-то высокочастотные помехи (например 5кГц). Короче мы решили слегка фильтрануть сигнал для уменьшения воздействия внешних помех. Допустим амплитудная характеристика нам важна только относительная. Ну к примеру идёт манипуляция по принципу есть сигнал/нет сигнала.

Таким образом надо его выделить и обработать пиковым детектором.

Скажем частота может плавать незначительно.
Берём прогу, что я приложил в прошлом посте (спасибо автору) и строим полосовой фильтр. (clip1)
Теперь немного о дробной арифметике.
Все знают что если 1 поделить на 2 то получим 0.5. Если ещё раз разделить = 0.25. Что такое деление на 2 - сдвиг вправо на 1 разряд. Таким образом если себе представить дробную часть, то двочное число 1000000B = 0.5, 01000000B = 0.25, 01100000B = 0.25+0125 = 0.375. Из этого понятно, что умножение на дробные коэффициенты можно представить как сдвиги и сложения. Желательно подобрать такие коэффициенты, чтобы число этих операций было минимальным при допустимой погрешности вычислений. Понятно также, что если у нас сигнал 10 бит, то сдвиги на 8-9 разрядов практически не внесут значимых результатов. Надо также учитывать, что фильтр может искажать сигнал по амплитуде. Для этого желательно следить за амплитудным значением на графике АЧХ. Для простоты картины можно отталкиваться от того, что сумма коэффициентов должна быть равна 1. Если это не так, то результирующий сигнал увеличится либо уменьшится. Часто это бывает непринципиально или даже желательно.
Исходя из этого "подкорректируем" коэффициенты X фильтра и перерисуем график воспользовавшись программой. (clip2)
Поступим аналогично с Y. (clip3)
После построения графика - видим что размах полезного сигнала изменился в 1.3 раза. Можно, естественно, подобрать коэффициенты более точно, но для поставленной задачи нам это ни к чему.
Теперь перенесём это на бумагу.
Теперь поясню, для тех кто непонимает, что это за X, Y, i.

Надо понимать, что фильтр состоит из звеньев (в данном фильтре 1 звено). Звенья независимы. Выходные данные первого звена - входные второго. И так далее.
В данном контексте будем считать так:
X входные данные первого звена (сигнал с АЦП)
Y выходные данные первого звена (выход фильтра). Если у нас более одного звена, то Y это входные данные второго звена.
(i) текущее значение
(i-1) предыдущее значение (значение полученное в предыдущей выборке)
(i-2) значение полученное 2 выборки назад и т.д.
Я упрощу выражение и вместо X(i-1) буду писать X1 и так далее.
Итак X коэфф. фильтра будут выглядеть так:
0.0625*(X0+X4)-0.125*X2 = ((X0+X4)>>4)-(X2>>3)
Y коэф. будут выглядеть так
-(-1.875*Y1+2*Y2-1.0625*Y3+0.3125*Y4) = 1.875*Y1-2*Y2+1.0625*Y3-0.3125Y4 = 2*Y1-0.125*Y1-2*Y2+Y3+0.0625*Y3-0.3125*Y4
= (Y1<<1)-(Y1>>3)-(Y2<<1)+Y3+(Y3>>4)-(Y4>>2)-(Y4>>4)
Итого общая формула (1):
Y0 = ((X0+X4)>>4)-(X2>>3)+(Y1<<1)-(Y1>>3)-(Y2<<1)+Y3+(Y3>>4)-(Y4>>2)-(Y4>>4)
Для понимания дальнейшего я перепишу по другому первых 2 члена
((X0+X4)>>4)-(X2>>3) = ((X0+X4)>>1)-X2)>>3
По сути это вынос множителя за скобки и математически ничего не даёт. На самом деле это уменьшает объём вычислений и повышает их точность.
Давайте перепишем полученную формулу фильтра (1) с учётом последнего замечания, но не ввиде формулы, а в виде последовательности вычислений.
Для этого введём временную переменную Temp и будем выбирать равные коэф. сдвигов. Я в коментах буду указывать номер члена формулы (1) которые я взял.
В результате получим:
Temp = (X0+X4+Y3-Y4)>>1; // все члены со сдвигом 4 = 1,7,9
Temp += (-X2-Y1); // ... 3 = 2,4 Естественно лучше записать Temp -= X2+Y1;
Temp >>= 1;
Temp += (-Y4); // .... 2 = 8 Опять таки Temp -= Y4;
Temp >>= 2; // Поскольку у нас нет членов со сдвигом >>1
Temp += (Y1<<1)-(Y2<<1)+Y3;
Из получившейся проги видно что результирующий коэфф. действительно будет более 1 так как в последней строчки получим 1 а в предпоследней ещё 1/4, но это просто так, для проверки себя.
Я не буду сейчас писать кольцевой буфер для входных значений фильтра. Чтобы было понятней что я делаю. Кстати если используем ФНЧ или ФВЧ, то там вообще это без надобности. Тем не менее, я часто пишу кольцевой буфер с отладочными целями, чтобы в процессе отладки увидеть как работает фильтр и некоторые его звенья. После завершения отладки - могу выкинуть, либо сохранить.
Итак, будет выглядеть так:
X4=X3; // Новый сэмпл сдвигает значения
X3=X2;
X2=X1;
X1=X0;
X0=ADCH;
Temp = (X0+X4+Y3-Y4)>>1; // все члены со сдвигом 4 = 1,7,9
Temp += (-X2-Y1); // ... 3 = 2,4 Естественно лучше записать Temp -= X2+Y1;
Temp >>= 1;
Temp += (-Y4); // .... 2 = 8 Опять таки Temp -= Y4;
Temp >>= 2; // Поскольку у нас нет членов со сдвигом >>1
Temp += (Y1<<1)-(Y2<<1)+Y3;
Y4=Y3; // Новый сэмпл сдвигает значения
Y3=Y2;
Y2=Y1;
Y1=Y0;
Y0=Temp;
Ну вот и всё.
На последок хотелось бы отметить что имеет значение разрядность чисел. Бывает, при сложных фильтрах, где малые коэффициенты происходит потеря точности, которая сводит на нет весь результат. Особенно если пользовать 8 бит данные. Часто бывает, при пограничных значениях (близких к максимому или минимому) что происходит потеря точности из-за переполнений и в этом случае достаточно использовать повышенную разрядность только переменной Temp.
Но в этом смысле преимущество Си просто фантастическое.
Представим что я написал этот фильтр для разрядности АЦП 8 бит. Тогда объявление переменных следующее:
int8_t X0,X1,X2,X3,X4,Y1,Y2,Y3,Y4,Temp;
Представим, что в процессе работы/наладки, я пришёл к выводу, что мне надо повысить разрядность до 10 бит.
Исправления будут следующие:
1) В строке объявления переменных надо исправить uint8_t на uint16_t (2 символа)
2) в строке программы изменить ADCH на ADC (1 символ)
3) В строке инициализации АЦП убрать (1<<ADLAR) (ещё 10 символов)
Итого исправления 13 символов. Тот кто пишет на ассемблере может оценить объём работы необходимый для перевода такого фильтра с 8 на 16 бит.
Цитата(Serhiy_UA @ Sep 17 2009, 16:19)

Много лет назад экспериментировал на ATmega16 со звуковыми частотами. То же АЦП-цифровой фильтр-ШИМ-RC. Строил НЧ и ВЧ фильтры с БИХ, с аккумулятором сумм до 32-бит, а также коэффициентами до 16-бит. Фильтры в итоге всегда самовозбуждались. Тема по прежнему актуальна.
Кто либо построил и реально использовал такие фильтры, есть ли положительные результаты, чем рассчитывали коэффициенты?
Собственно цифровые фильтры хороши именно тем, что без разницы на чем они считаются. Mega16/ARM/PIC - при тех же коэффициентах и разрядностях работать будут одинаково. По моему очевидно, что ATMega не разрабатывалась для обработки звука. Для этого есть более удобные процы. Я работал со звуком только в рамках телефонной линии. При выборке 8кГц и верхней частоте 3.4кГц требуется, для удовлетворительного качества, АЦП разрядностью 14 бит. При этом для обработки двух потоков приходится греметь всеми костями ATMega на частоте 16МГц. Пробовал обеспечить вывод разными способами, в том числе и ШИМом. Понятно что 14 бит ШИМ на 8кГц даёт сотни МГц поэтому упрощали до 8 бит. Даже при 8 бит для получения приемлемого сигнала, требовалась выходная обвеска сопоставимая с размерами изделия. Причём настройка-регулировка была бы непростая.
Короче из всех вариантов этот был самым отвратительным. Существуют внешние цапы, в том числе звуковые, в том числе с нелинейной характеристикой и встроенными цифровыми фильтрами. Стоят - копейки. С фильтрами проблем не было. Правда, как я говорил обработка была весьма топорная.