Программирование AVR AVR223: Digital Filters with AVR (цифровые фильтры на AVR) Tue, March 19 2024  

Поделиться

Нашли опечатку?

Пожалуйста, сообщите об этом - просто выделите ошибочное слово или фразу и нажмите Shift Enter.

AVR223: Digital Filters with AVR (цифровые фильтры на AVR) Печать
Добавил(а) microsin   

В статье приведен почти дословный перевод на русский язык апноута Atmel AVR223. Рассказывается, как на практике рассчитать и сделать цифровой фильтр на AVR. Исходники примеров фильтров можно скачать по ссылке [11].

[Содержание]

• реализация цифровых фильтров
• коэффициенты и масштабирование данных
• быстрая реализация FIR-фильтра 4-го порядка
• быстрая реализация IIR-фильтра 2-го порядка
• методы оптимизации

[1. Введение]

Приложения, обрабатывающие сигналы от внешних аналоговых источников/сенсоров обычно нуждаются в некоторой цифровой фильтрации. Для максимально высокого быстродействия фильтра обычно выбирают специализированные Цифровые Сигнальные Процессоры (Digital Signal Processors, DSP), но во многих случаях они оказываются слишком дорогими для использования. В этом случае на сцену выходят 8- и 16-битные микроконтроллеры (MCU). Они недороги, эффективны, и имеют все возможности по вводу и выводу I/O, и модули коммуникаций, которые DSP имеют очень редко.

Микроконтроллеры Atmel AVR хорошо подходят для обработки сигнала, так как имеют мощную архитектуру, набор инструкций и встроенный многоканальный 10-битный АЦП (Analog to Digital Converter, ADC). Серия megaAVR® также имеет аппаратный умножитель, который важен в сигнальной обработке.

В этом документе фокусируется рассмотрение аппаратного умножителя AVR, использование регистров общего назначения для функциональности аккумулятора, рассматривается, как масштабировать коэффициенты при реализации алгоритмов с архитектурой фиксированной дробной точки, и возможные пути оптимизирования реализации фильтра. Приложено два примера реализации.

Поскольку теория цифровых фильтров не является целью этого апноута, раскрыт только некоторый базис. Список советуемой литературы, более глубоко раскрывающей теорию цифровых фильтров, указан в конце этого документа.

[2. Основы цифровых фильтров]

Все линейные цифровые, инвариантные по времени (linear, time-invariant, LTI) фильтры могут быть описаны дифференциальным уравнением, как показано в Уравнении 1 (x - входной сигнал, y - выходной сигнал, n - номер выборки сигнала, характеризует прошедшее время).

Уравнение 1: основное дифференциальное уравнение для цифровых фильтров
AVR223-equ01.PNG

Фильтр уникально определяется по его порядку (наибольшее из M и N) и коэффициентам ai и bj. Порядок фильтра (наибольшее из M и N) определяет максимальную задержку по времени между входом и выходом фильтра. Обычно коэффициенты (ai, bj) масштабируются таким образом, что коэффициент a0 равен 1. Выходное значение сигнала фильтра может быть вычислено, как показано в Уравнении 2:

Уравнение 2: дифференциальное уравнение для выхода фильтра
AVR223-equ02.PNG

Если x[n] является импульсом (x==1 при n==0 и x==0 при n!=0), то выход называют импульсным откликом фильтра h[n].

Фильтры классифицируются по двум типам, в зависимости от значения M:
- тип фильтра с конечным импульсным откликом, КИХ-фильтр (Finite Impulse Response, FIR), для него M==0
- тип фильтра с бесконечным импульсным откликом, БИХ-фильтр (Infinite Impulse Response, IIR), для него M!=0

Реальное отличие этих двух типов фильтров - отсутствие (FIR фильтр) или наличие (IIR фильтр) обратной связи с выхода на вход. Фильтры IIR вычисляются с рекурсией, т. е. предыдущие значения (y[n-1]) участвуют в вычислении текущего (y[n]) выходного значения. Термин конечный/бесконечный описывает длину ответа фильтра на входной импульс (при игнорировании эффектов квантования в реальной реализации фильтра). Фильтр IIR, у которого N==0, образует специальный класс фильтра, называемый "all-pole" фильтр, или фильтр, имеющий только полюсы. Для более детального рассмотрения этих двух классов фильтров (FIR и IIR), обращайтесь к рекомендуемой литературе из списка в конце статьи.

Часто цифровые фильтры описываются в Z-домене, домене комплексной частоты (не спрашивайте меня, что это такое). Z-преобразование Уравнения 1 показано в Уравнении 3:

Уравнение 3: Z-преобразование основного цифрового фильтра
AVR223-equ03.PNG

Функция преобразования H(z) обычно предоставляется для фильтра, поскольку это дает компактное представление, и позволяет легко выполнить частотный анализ. Функция преобразования задается как зависимость между выходом и входом фильтра в Z-домене, как показано в Уравнении 4. Обратите внимание, что функция преобразования является Z-преобразованием импульсного ответа фильтра h[n].

Уравнение 4: функция преобразования для основного цифрового фильтра
AVR223-equ04.PNG

Как можно увидеть, числитель описывает часть feed-forward (без обратной связи), а знаменатель - часть feedback (с обратной связью). Для более детального рассмотрения Z-домена, обращайтесь к рекомендуемой литературе из списка в конце статьи.

Для реализации фильтра по заданной функции преобразования важно знать, что z в Z-домене представляет элемент задержки, и экспонента задает длину задержки в единицах выборок (в промежутках времени между выборками). Рисунок 2-1 показывает схему цифрового фильтра в Прямой Форме 1.

Рисунок 2-1: Прямая Форма 1 представления основного цифрового фильтра.
AVR223-fig2-1.PNG

[3. Соображения, принимаемые во внимание при реализации фильтра]

Когда проектируют фильтр на выбранной архитектуре микроконтроллера (MCU), необходимо принять во внимание несколько моментов. Например:

- точность (количество бит) представления сигнала на входе и выходе будет влиять на максимально допустимое усиление фильтра и его пропускную способность (throughput).
- точность коэффициентов фильтра влияет на ответ по частоте, АЧХ (frequency response) и пропускную способность фильтра.
- порядок фильтра влияет на пропускную способность фильтра.
- дробные коэффициенты фильтра требуют некоторых ухищрений при использовании целочисленного перемножителя (в микроконтроллерах AVR он именно такой).

Эти и другие вопросы реализации обсуждаются в этой секции статьи. В дополнение приведено быстрое описание аппаратного перемножителя AVR и виртуального аккумулятора, потому что знания о них важны для понимания работы кода фильтра.

3.1 Аппаратный перемножитель, встроенный в AVR

Поскольку AVR имеет 8-битную архитектуру, аппаратный перемножитель 8-битный, а при перемножении двух чисел 8 бит на 8 бит получается результат 16 бит. Перемножитель в этой статье (апноут AVR223) работает при использовании трех различных инструкций ассемблера: MUL (беззнаковая инструкция умножения), MULS (умножение со знаком) и MULSU (перемножение числа со знаком на беззнаковое).

Алгоритм фильтра состоит из суммы результатов нескольких шагов вычислений. Первый результат вычисляется "простым" (MUL) перемножением между двумя N-битными числами, в результате чего получается 2N-битный результат. Перемножение выполняется с одним байтом, который умножается на каждый из множителей, и результат сохраняется 2N-битном "аккумуляторе". Следующий результат вычисляется и добавляется в аккумулятор, чем производится так называемая операция multiply-and-accumulate (MAC).

Примеры фильтров в этой статье используют две различные операции умножения:

muls16x16_24
mac16x16_24

Здесь используется умножение со знаком двух 16-битных операндов с 24-битным результатом. Результат не 32-битный, поскольку входные выборки и коэффициенты подобраны так, что не используют весь диапазон 16 бит.

Имейте в виду, что AVR также имеет инструкции для дробных перемножений, но они не используются в этой статье. За подробностями обращайтесь к апноуту “AVR201: Using the AVR Hardware Multiplier” (AVR201: использование аппаратного перемножителя AVR).

3.2 Виртуальный аккумулятор AVR

У AVR нет выделенного специального аккумулятора, вместо него AVR позволяет любым из 32-х восьмибитных регистров общего назначения (GPIO registers) работать в форме "виртуального аккумулятора". В этой статье виртуальный аккумулятор будет просто называется "аккумулятором". Такой аккумулятор более гибкий, чем обычные аккумуляторы, используемые в других архитектурах (хотя, возможно иногда работает медленнее).

Например, если для AVR необходим 24-битный аккумулятор, чтобы перемножить (MUL) две 12-битные величины, комбинируются три 8-битных GP-регистра в один 24-битный аккумулятор. Если MAC требует 40-битного аккумулятора, комбинируются пять 8-битных регистров. Такая гибкость аккумулятора не требует разделения операций на результаты и подрезультаты, переносимых туда и обратно во время операций MAC (которые требуются, если аккумулятор имеет фиксированную разрядность 32 или менее бит).

Гибкость аккумулятора AVR - важный инструмент для обхода проблем переполнения в алгоритмах с фиксированной точкой (Fixed Point, FP), которые будут обсуждены далее в этой статье.

3.3 Переполнение значений в операциях с фиксированной точкой.

Переполнение может произойти в двух местах алгоритма фильтра - в промежуточных результатах вычислений и на выходе фильтра. Переполнение в промежуточных результатах может произойти:

- при перемножении величин с разрядностью N1 и N2, в результате получится результат из N1+N2 бит.
- сложение двух величин может выдать сумму, которая имеет на 1 бит больше размер, чем самый большой по разрядности операнд сложения. Например, рассмотрим Уравнение 5 для FIR фильтра 4-го порядка:

Уравнение 5: дифференциальное уравнение для фильтра FIR 4-го порядка
AVR223-equ05.PNG

Выходное значение фильтра y[n] равно сумме пяти промежуточных составляющих. Если предположить, что входные выборки x[n] и коэффициенты bj имеют величины 16 бит со знаком, алгоритм потребует 34-битного аккумулятора - см. расчет в Уравнении 6. В этом уравнении N - требуемая разрядность аккумулятора, K - разрядность операндов (x[n] и bj) не считая бита знака, M - количество слагаемых (порядок фильтра +1). Один добавляемый бит - это бит знака.

Уравнение 6: требуемая разрядность аккумулятора для фильтра FIR 4-го порядка
AVR223-equ06.PNG

Аккумулятор для данного случая должен состоять из 5 байт регистров GPIO (40 бит), чтобы сохранить максимальную величину, которая может встретиться в вычислениях.

Имейте в виду, что для фильтра IIR выходные значения фильтра участвуют в вычислениях алгоритма фильтра. Если выходные значения фильтра имеют бОльшую разрядность, чем входные, размер аккумулятора должен быть подобран с учетом разрядности выхода фильтра.

Чтобы избежать переполнения на стадии выхода фильтра, усиление фильтра должно быть ограничено, чтобы стало возможным представить результат с заданной точностью (разрядностью) для выхода. Ограничение усиления будет, конечно, зависеть от спектра и разрядности (по отношению к выходу) входного сигнала.

Самый консервативный критерий для того, чтобы избежать переполнения в состояниях выхода, состоит в том, чтобы абсолютная сумма импульсных ответов фильтра, помноженная на максимальное абсолютное значение на входе не превышала максимальное абсолютное значение выхода, см. Уравнение 7.

Уравнение 7: консервативный критерий отсутствия переполнения на выходе фильтра.
AVR223-equ07.PNG

Если импульсный ответ не удовлетворяет этому критерию, он должен быть просто умножен на фактор, который уменьшит абсолютное значение суммы.

Имейте в виду, что для целых чисел со знаком максимальное значение положительной величины на 1 меньше, чем абсолютный минимум отрицательной величины. Предположим, что вход имеет разрядность M бит и выход имеет разрядность N бит, в этом случае Уравнение 8 покажет критерий для наихудшего сценария.

Уравнение 8: "наихудший случай" консервативного критерия для целых со знаком.
AVR223-equ08.PNG

Хотя выполнение этого критерия гарантирует отсутствие переполнения, его недостаток - существенное снижение усиления фильтра. Характеристики входного сигнала могут быть такими, что этот критерий будет слишком пессимистичен.

Другой общий критерий, который лучше подходит для узкополосных сигналов (таких, как синусоидальный сигнал), состоит в том, что абсолютное максимальное усиление фильтра, умноженное на абсолютное максимальное значение входного сигнала, не может превысить максимальное значение выхода. Уравнение 9 показывает этот критерий.

Уравнение 9: критерий для устранения переполнения при узкополосных сигналах.
AVR223-equ09.PNG

Именно этот критерий используется для реализации фильтра в этой статье: с одинаковой разрядностью для входа и выхода усиление у фильтра не должно превышать 0 dB (коэффициент передачи не должен быть больше 1).

Имейте в виду, что ограничение усиления зависит от характеристик входного сигнала, поэтому с помощью некоторого экспериментирования можно найти оптимальный лимит.

3.4 Масштабирование коэффициентов.

Другой важный вопрос - представление коэффициентов фильтра на архитектуре, использующей числа с фиксированной точкой (Fixed Point, FP). FP вовсе не означает тот факт, что все числа обязательно должны быть целыми - как уже было указано, доступно также дробное FP умножение. Однако в этой статье используются только целочисленные умножения, таким образом сделан фокус на реализации с помощью представления целых чисел.

Обычно для более точного представления числа оно должно иметь максимально возможное число бит. Для применения дробных коэффициентов фильтра в целочисленных умножениях проблема сводится к масштабированию всех коэффициентов самым большим общим множителем, который не вызывает переполнений в их представлении. Это масштабирование также применяется и к коэффициенту a0, с применением масштабирования вниз выхода (по необходимости) для получения корректного значения (особенно касается фильтров IIR). Поскольку аппаратное деление недоступно, фактор масштабирования должен быть в форме 2k, так как деление и умножение с основанием 2 легко реализуется сдвигами. Принцип масштабирования коэффициентов и последующего масштабирования вниз показан в Уравнении 10.

Уравнение 10: масштабирование коэффициентов фильтра с последующим масштабированием вниз результата.
AVR223-equ10.PNG

Имейте в виду, что бит знака (самый старший бит) должен быть сохранен при масштабировании вниз (сдвиге на K раз вправо). Проще всего для этой цели применить инструкцию ассемблера ASR (арифметический сдвиг вправо).

Например, коэффициенты фильтра bj = {0.9001,-0.6500,0.3000}. Если используется 16-битное представление чисел, то масштабированные коэффициенты должны быть в диапазоне [-215..(215-1)] = [-32768..32767]. Обычно коэффициент с самым большим абсолютным значением определяет ограничение максимального множителя масштабирования. в нашем случае максимальный множитель масштабирования без любого переполнения равен 215. Округлив масштабированные коэффициенты, получим в результате значения {29494,-21299,9830} и приблизительную ошибку округления при масштабировании вниз {1.5*10-5, 6.1*10-6, 1.2*10-5}.

Оптимизация масштабирования вниз возможна, если фактор K превышает число 8, умноженное на целое число (1, 2, 3, ..). В этом случае программа при масштабировании вниз может просто отбрасывать младшие байты результата (1, 2, 3, .. байта). Пример показан на Рисунке 3-1, где 32-битный результат должен быть смасштабирован вниз в 2^18 раз (т. е. сдвинут вправо 18 раз). Это выполняется путем сдвига старших 16-ти бит только два раза вправо (при этом младшие 16 бит просто не принимаются во внимание).

Рисунок 3-1: оптимизация масштабирования вниз (серым помечены неиспользуемые биты)
AVR223-fig3-1.PNG

Эффект масштабирования вниз

Можно задаться вопросом, почему каждый раз мы добавляем биты, чтобы избежать переполнения в подрезультатах, а затем “выбрасываем их”, чтобы вместить результат в указанное разрешение. Объяснение этого "парадокса" следующее - дополнительные биты нам нужны, чтобы поддержать точность при вычислениях, а фильтр имеет единичное усиление, при этом его выходные значения сигнала должны интерпретироваться как целые числа.

Для фильтров с единичным коэффициентом передачи коэффициенты фильтра (ai, bj) будут дробными числами, меньшими, чем единица. Таким образом, домножение при масштабировании просто добавляет биты, которые будут представлять дробные значения. Суммирование, однако, добавит биты, которые представляют более высокое значение. Но из-за единичного усиления фильтра, эти биты никогда не будут использоваться в результате: выход фильтра не получит абсолютную величину сигнала больше, чем величина сигнала на входе, что позволяет выходу быть представленным с тем же самым целочисленным диапазоном, как и вход.

Масштабирование вниз просто удаляет дробную часть результата, оставляя только целую часть с требуемой точностью (количеством бит). Ясно, что это также означает - точность уменьшается. Это важно для IIR-фильтров, так как у них есть обратная связь. Если эффект от потери точности здесь создает проблему, то потеря точности может быть уменьшена двумя способами:

- сделать усиление фильтра максимальным, при этом выход будет использовать весь доступный диапазон значений.
- увеличить одновременно и точность выхода и усиление фильтра.

Если применяется второй метод, то последний фактор может влиять на размер кода и пропускную способность, так как  может потребоваться аккумулятор увеличенного размера.

Уменьшенная точность с целью повышения пропускной способности

Чтобы ускорить работу алгоритма фильтрации,  может потребоваться уменьшить точность коэффициентов и/или входных выборок сигнала, что позволит уменьшить размер аккумулятора. Уменьшенный аккумулятор означает, что алгоритм потребует меньше операций на умножение коэффициента фильтра и выборки. Однако, прежде чем уменьшать точность, нужно принять во внимание два момента:

- уменьшение точности входных выборок означает добавление шума в систему, что обычно нежелательно.
- уменьшение точности коэффициентов фильтра означает, что нужную характеристику фильтра получить будет сложнее.

Другие методы повышения пропускной способности см. в разделе "Оптимизация реализации фильтра".

[4. Реализация фильтра]

Примеры фильтров в этой статье разработаны и скомпилированы в среде компилятора IAR EWAVR версии 5.03A.

Коэффициенты фильтра вычислены с помощью специального программного обеспечения. Для этого имеется множество программ, начиная от дорогих типа Matlab, кончая бесплатными апплетами Java, доступными через web. Список web-сайтов, которые имеют дело с темой вычислениями коэффициентов фильтра, предоставлен в литературном списке в конце статьи. Альтернативой может быть вычисление коэффициентов "трудным" путем - вручную. Методы для расчета коэффициентов фильтра (и достижения стабильности этих фильтров) описаны в [1] и [2].

В примерах реализованы два фильтра - фильтр верхних частот (High Pass, HP) FIR-фильтр 4-го порядка, и полосовой фильтр (Band Pass, BP) IIR-фильтр 2-го порядка. В обеих реализациях используются 10-битные со знаком отсчеты сигнала на входе (разрядность АЦП AVR 10 бит). FIR-фильтр использует 13-битные коэффициенты со знаком, IIR-фильтр использует 12-битные коэффициенты со знаком. Это требует максимального размера аккумулятора 24 бита.

Фильтры реализованы на ассемблере по соображениям эффективности. Реализация выполнена так, что функции фильтра можно вызывать из кода на C. Перед вызовом функций фильтра требуется инициализировать узлы фильтра (память и элементы задержки) - иначе начальные условия для работы фильтра будут неизвестны. Для обоих фильтров приведен пример кода на C, инициализирующего и вызывающего предоставленные функции фильтра.

Все параметры, требуемые для фильтрации, передаются во время выполнения, поэтому функции могут быть повторно использованы для реализации более чем одного фильтра без дополнительных затрат места под код. Это может использоваться для каскадного соединения фильтров - часто несколько фильтров второго порядка включаются друг за другом (выход одного фильтра со входом другого) для получения фильтра более высокого порядка. Однако, так как выход каждого из фильтров в каскаде масштабируется вниз перед попаданием на вход другого фильтра, то на выходе результирующего фильтра может оказаться совсем не то, что ожидалось. Это происходит потому, что теряется точность между каскадами фильтров. Естественно, эффект этого становится более явным с увеличением количества звеньев в каскадном фильтре.

Реализация фильтров сделана с фокусом на быстродействие, поскольку очень важна высокая пропускная способность фильтра. См. раздел "Оптимизация реализации фильтра", где размещены советы по уменьшению размера кода, увеличению пропускной способности, экономии использования памяти.

4.1 FIR-фильтр 4-го порядка

Чтобы продемонстрировать технику каскадирования, этот фильтр реализован путем соединения двух HP фильтров второго порядка. Оба фильтра сделаны по технике окна, описанной в [1], применено окно Хемминга (Hamming window). Параметры фильтра показаны в Таблице 4-1. Рисунок 4-1 показывает амплитудную характеристику обоих фильтров по отдельности, и характеристику их каскадирования.

Таблица 4-1: параметры HP FIR-фильтра 2-го порядка

Фильтр
Порядок
Срез
Коэффициенты (b0,b1,b2)
Масштабирование
Смасштабированные коэффициенты (b0,b1,b2)
 1  2  0.4 -0.0373, 0.9253, -0.0373  212 -153, 3790, -153
 2  2  0.6 -0.0540, 0.8920, -0.0540  212 -222, 3653, -222

Рисунок 4-1: АЧХ FIR-фильтров
AVR223-fig4-1.PNG

Подпрограммы фильтров реализованы на ассемблере для получения эффективного кода. Однако параметры фильтра и узлы фильтра предварительно (до вызова функции фильтрации) должны быть проинициализированы программой на языке C.  Структура содержит коэффициенты фильтра и узлы фильтра, которые задаются для каждого фильтра отдельно. Структуры заданы следующим образом:

struct FIR_filter
{
  int filterNodes [FILTER_ORDER];          //память для узлов фильтра
  int filterCoefficients[FILTER_ORDER+1];  //память для коэффициентов фильтра
} filter04 = {0,0, B10, B11, B12},          //инициализация 1-го фильтра
 filter06 = {0,0, B20, B21, B22};          //инициализация 2-го фильтра

Массив filterNodes используется как буфер FIFO, в котором сохраняются предыдущие значения входного сигнала. Массив filterCoefficients используется feedforward-коэффициентов (bj) фильтра. После того, как фильтр проинициализирован, может быть вызвана функция фильтра. Функция фильтра задана следующим образом:

int FIR2(struct FIR_filter *myFilter, int newSample);

Сначала функция копирует указатель на структуру FIR_filter в Z-регистр, поскольку он может использоваться непрямой (indirect) адресации данных, например для операций с использованием указателя. Затем основной алгоритм готов к запуску. Выборки (узлы фильтра) загружаются и умножаются (инструкцией ассемблера MUL) с соответствующими коэффициентами. Результаты добавляются в 24-битный аккумулятор. Когда все выборки и коэффициенты умножены и сохранены (multiplied-and-accumulated, операция MAC), результат масштабируется вниз и возвращается. Процесс обработки можно увидеть на Рисунке 4-2, который описывает действия алгоритма фильтра FIR.

Имейте в виду, что несмотря на то, что диаграмма на Рисунке 4-2 показывает алгоритм, реализованный с использованием циклов, на самом деле алгоритм реализован линейным кодом (для увеличения быстродействия). Цикл на диаграмме просто применен для улучшения читаемости алгоритма.

Рисунок 4-2: Generic (традиционный) алгоритм FIR-фильтра
AVR223-fig4-2.PNG

Как сообщалось ранее, два фильтра включены каскадно. В модуле на языке C это делается просто путем передачи фильтру 1 через аргумент входной выборки, и затем путем передачи фильтру 2 в качестве входного аргумента результата фильтра 1. Каждый раз вызывается та же самая функция - и для фильтра 1, и для фильтра 2.

4.1.1 Скорость работы FIR-фильтра

Таблица 4-2 показывает быстродействие одного звена - FIR-фильтра второго порядка. Значение счетчика в таблице показывают затраты времени (в циклах ядра AVR) на выполнение алгоритма фильтра (операции MUL и MAC, обновление узлов), а также на дополнительную обработку при завершении функции (включая масштабирование вниз). Время, затраченное на вызовы (call) и возврат из функции (return), в таблице не учитывается.

Таблица 4-2: затраты процессорного времени на выполнение алгоритма FIR-фильтра второго порядка.

Инструкций (фильтрация + доп. расходы)
Циклов выполнения (фильтрация + доп. расходы) Эффективность фильтра (количество циклов фильтра в пересчете на порядок фильтра)
 50+10  76+10  38

Имейте в виду, что изменение порядка фильтра может принудить к изменению размера аккумулятора, что изменит количество затрачиваемых инструкций/циклов процессора. Эффективность фильтра в пересчете на порядок фильтра (последний столбец таблицы) также поменяется.

4.2 IIR-фильтр второго порядка

Для этой реализации применен полосовой (Band Pass, BP) IIR-фильтр Баттерворта. Параметры фильтра показаны в Таблице 4-3, АЧХ на Рисунке 4-3.

Таблица 4-4: параметры IIR-фильтра второго порядка

Порядок Срез
Коэффициенты (b0,b1,b2;a0,a1,a2)
Масштабирование
Смасштабированные коэффициенты(b0,b1,b2;a0,a1,a2)
 2 0.45 -
0.55
0.1367, 0.0000, -0.1367;
1.0000, 0.0000, 0.7265
 211 280, 0, -280;
2048, 0, 1488

Поскольку коэффициент a0 определяет множитель для масштабирования вниз выхода фильтра, он не задан в коде на языке C, а просто задан в коде ассемблера для масштабирования вниз.

Рисунок 4-3: АЧХ IIR-фильтра 2-го порядка
AVR223-fig4-3.PNG

Структура содержит коэффициенты фильтра и узлы фильтра. Фильтр должен быть проинициализирован перед тем, как будет вызвана функция фильтра. Структура определена следующим образом:

struct IIR_filter
{
  int filterNodesX[FILTER_ORDER];          //узлы фильтра, тут сохраняются входные выборки  x(n-k)
  int filterNodesY[FILTER_ORDER];          //узлы фильтра, тут сохраняются выходные значения y(n-k)
  int filterCoefficientsB[FILTER_ORDER+1]; //feedforward коэффициенты фильтра (bj)
  int filterCoefficientsA[FILTER_ORDER];    //feedback коэффициенты фильтра (ai)
} filter04_06 = {0,0,0,0, B0, B1, B2, A1, A2}; //инициализация фильтра

Массивы filterNodesX и filterNodesY используются как буферы FIFO, сохраняющие соответственно входные и выходные значения сигнала фильтра. Массивы filterCoefficientsB и filterCoefficientsA используются для коэффициентов фильтра соответственно feed-forward и feedback. После инициализации фильтра может быть вызвана функция фильтра. Функция фильтра определена следующим образом:

int IIR2(struct IIR_filter *myFilter, int newSample);

Сначала функция копирует указатель на структуру фильтра в Z-регистр, поскольку он может использоваться непрямой (indirect) адресации данных, например для операций с использованием указателя. Затем основной алгоритм готов к запуску. Выборки входа и данные выхода (узлы фильтра) загружаются и умножаются с соответствующими коэффициентами. Результаты добавляются в 24-битный аккумулятор. Когда все выборки и коэффициенты умножены и сохранены (multiplied-and-accumulated, операция MAC), узлы фильтра в FIFO-буфере обновлены, результат масштабируется вниз и возвращается. Имейте в виду, что результат в аккумуляторе масштабируется вниз перед сохранением его в у[n-1] ячейке буфера FIFO. Процесс обработки можно увидеть на Рисунке 4-4, который описывает действия алгоритма фильтра IIR.

Рисунок 4-4: Generic (традиционный) алгоритм IIR-фильтра
AVR223-fig4-4.PNG

Имейте в виду, что несмотря на то, что диаграмма на Рисунке 4-4 показывает алгоритм, реализованный с использованием циклов, на самом деле алгоритм реализован линейным кодом (для увеличения быстродействия). Цикл на диаграмме просто применен для улучшения читаемости алгоритма.

4.2.1 Скорость работы IIR-фильтра

Таблица 4-4 показывает быстродействие IIR-фильтра второго порядка. Значение счетчика в таблице показывают затраты времени (в циклах ядра AVR) на выполнение алгоритма фильтра (операции MUL и MAC, обновление узлов), а также на дополнительную обработку при завершении функции (включая масштабирование вниз). Время, затраченное на вызовы (call) и возврат из функции (return), в таблице не учитывается.

Таблица 4-4: затраты процессорного времени на выполнение алгоритма IIR-фильтра второго порядка.

Инструкций (фильтрация + доп. расходы)
Циклов выполнения (фильтрация + доп. расходы) Эффективность фильтра (количество циклов фильтра в пересчете на порядок фильтра)
 86+8  132+8  66

Имейте в виду, что изменение порядка фильтра может принудить к изменению размера аккумулятора, что изменит количество затрачиваемых инструкций/циклов процессора. Эффективность фильтра в пересчете на порядок фильтра (последний столбец таблицы) также поменяется.

[5. Оптимизация реализации фильтра]

Фильтры, реализованные в этой статье в качестве примера, сделаны эффективно, однако есть еще резервы для увеличения быстродействия. Причина в том, что фильтры в примерах универсальны, а конкретная реализация узкоспециализированных фильтров может быть сделана более оптимально. Далее описаны пути для оптимизации фильтров по размеру кода и/или быстродействию.

5.1 Уменьшение объема кода и увеличение пропускной способности

Один из путей одновременного уменьшения объема кода и увеличения пропускной способности - нужно убедиться в том, что выполняются только необходимые вычисления. Ассемблерный код для фильтров, реализованный в примерах из статьи, сделан так, что он будет работать с любым набором коэффициентов фильтра. Однако IIR-фильтр второго порядка имеет два нулевых коэффициента. Умножение и последующее накопление с нулевыми коэффициентами может быть, конечно, опущено - что никак не повлияет на работу фильтра, но увеличит быстродействие и уменьшит размер кода.

5.2 Уменьшение размера кода

Уменьшение размера кода может быть достигнуто путем реализации MAC как вызова функции, вместо этой операции, выполненной как макрос. Однако это ударит про пропускной способности, так как на каждый вызов и возврат из функции тратятся дополнительные циклы процессора.

Другой путь уменьшения объема кода - реализация фильтров высокого порядка с помощью каскадирования фильтров меньшего порядка, как продемонстрировано на FIR-фильтре 4-го порядка. Хотя, как отмечалось ранее, это уменьшит точность фильтра из-за промежуточного масштабирования вниз на каждом каскаде. Кроме того, не получится выполнить оптимизацию путем пропуска MAC-операций на нулевых коэффициентах, так как это возможно не для всех реализаций фильтра.

5.3 Уменьшение размера используемой памяти (RAM)

Коэффициенты фильтра в обоих примерах реализаций размещаются в SRAM. Простой путь уменьшения памяти - размещение коэффициентов в FLASH и выборка их по необходимости. Это потенциально почти наполовину уменьшит расход памяти для параметров фильтра, поскольку на коэффициенты тратится почти столько же памяти, как и на узлы (предыдущие состояния входа и выхода) фильтра.

[Зачем все это? (О чем вообще тут говорится?..)]

Если Вы дочитали статью до конца (напомню, что это апноут Atmel AVR223), то значит, что Вас в некоторой степени интересует цифровая обработка сигналов (ЦОС). Если же Вы почти все поняли в этой статье (я, например, не понял только Z-домен, Z-преобразование и все, что с этим связано), то Вы раньше уже интересовались ЦОС, и немного знакомы с общими принципами, но не видели реального способа выполнить какую-нибудь (даже самую простую) задачу ЦОС. Поздравляю! Теперь у Вас в руках готовый инструмент, хорошая точка для старта создания своих собственных программ. Чем мне больше всего понравился апноут AVR223 - дается в сжатом виде именно то, что нужно для начала - просто бери и делай (причем можно делать не только на AVR, если основной принцип понятен).

В заключение хочу привести несколько соображений по поводу предоставленной в апноуте AVR223 информации - как на основе неё сделать свой собственный DSP-фильтр. Все на примере той же платформы AVR, которая и рассматривается в статье.

1. Сначала необходимо понять - чего мы можем, и чего не можем. То есть какую максимальную полосу частот мы сможем обработать, и какой порядок фильтра при этом можно применить (при той же самой разрядности сигнала 10 бит, что применена в примерах). Понятно, что чем выше максимальная рабочая частота, которую мы можем пропустить через фильтр, тем фильтр качественнее, и тем проще делать предварительную аналоговую фильтрацию (об этом позже). От порядка фильтра зависит крутизна характеристики фильтра, т. е. насколько хорошо фильтр ослабляет ненужный сигнал (для упрощения пока не рассматриваем другие характеристики фильтра типа групповой задержки, фазочастотной характеристики и т. п.). Исходя из предположения, что кварц у нас максимально возможный для AVR 20 МГц, по таблицам 4-2 и 4-4 можно подсчитать максимально возможную частоту выборок входного сигнала, которую мы успеем обработать. Например, у нас FIR-фильтр 4-го порядка (т. е. два FIR-фильтра 2-го порядка, соединенные в цепочку - именно так, как описывается в статье). Тогда получается, что полный проход вычислений фильтра займет (по Таблице 4-2), с учетом вызова подпрограммы FIR

2 + 76 + 10 + 2 = 90 циклов.

Если учесть еще время на чтение результатов с АЦП и время на обработку прерывания (в реальном приложении придется читать АЦП в обработчике таймера, и наверное там же делать вызов функции FIR), то грубо придется добавить еще 10 циклов. Итого, имеем 90+10=100 циклов ядра, которые занимает обработка одной выборки АЦП. Что это означает? Это как раз и есть ограничение по максимально возможной частоте дискретизации системы Fs, которая как раз и определяет максимальную частоту сигнала, которую может пропустить через себя фильтр (по теореме Котельникова Fs/2).

Итак, остается только вычислить эту максимально возможную частоту дискретизации Fs, и тогда сразу станет понятно, что мы можем, а что нет. Ядро AVR работает на частоте 20 МГц, т. е. в секунду выполняет 20000000 циклов. У нас прокрутка фильтра занимает 100 циклов, т. е. за секунду мы можем сделать 20000000/100 = 200000 прокруток, т. е. частота дискретизации Fs у нас может быть 200000 Гц, или 200 кГц. Таким образом, мы можем пропускать через фильтр частоты до 100000 кГц. Звучит, конечно, круто, однако необходимо помнить, что это подсчет для идеального случая - когда AVR у нас ничего, кроме расчета фильтра, не делает, а так в реальной жизни, увы, не бывает. Ведь надо еще и опрашивать датчики, кнопки, мигать светодиодами и вообще выполнять какой-никакой общий фоновый алгоритм. В итоге примерно получим максимальную Fs около 100 кГц, т. е. максимальный входной сигнал - до 50 кГц. Все равно что-то слишком круто...

Если вдруг захотим фильтр не 4-го порядка, а 8-го, то понятно, что все автоматически ухудшается в два раза - максимальная Fs 50 кГц, максимальная входная частота 25 кГц и так далее. Надеюсь, теперь Вы в состоянии оценить возможности цифровой обработки на AVR.

2. Необходимо не забывать важное условие - ни в коем случае нельзя на вход цифрового фильтра подавать частоты выше чем Fs/2, иначе это чревато грубыми ошибками в работе фильтра (не спрашивайте меня, почему - в умных книжках все написано). Чтобы выполнить это условие, на входе цифрового фильтра всегда ставят предварительный аналоговый фильтр низкой частоты с частотой среза Fs/2 или ниже (хотя бы простую RC-цепочку). Иначе - никак. Какая ирония - чтобы цифровой фильтр работал, на его входе должен быть обязательно старый добрый аналоговый фильтр... Понятно, что чем меньше частота среза аналогового фильтра по отношению к Fs/2, тем надежнее будет подавление паразитных составляющих сигнала, и тем сильнее можно упростить схему аналогового фильтра. Поэтому если хотим совсем простую схему, то полоса допустимого входного сигнала уменьшается еще больше - в два, в четыре раза по отношению к Fs/2. В идеале входной фильтр должен ослаблять сигнал в паразитном для цифрового фильтра диапазоне до уровня единицы младшего разряда АЦП (т. е. для 10-битного АЦП входной фильтр должен давать ослабление ненужного сигнала в 210 раз, или 60 дБ). Т. е. реально на частоте дискретизации 100 кГц удобно обрабатывать частоты не выше 4..8 кГц, иначе придется городить сложные многоступенчатые аналоговые фильтры... Ну и засада. Теперь понятно, почему AVR еще не "убийца" классических дорогущих DSP - за все надо платить, розовые очки сняты. Так что AVR в цифровой обработке - вовсе не панацея от всех проблем, но AVR вполне может найти применение в радиолюбительской практике для грубой обработки звука (10 бит не ахти какая точность) или - что еще лучше - для декодирования сигналов телеуправления.

Для расчета входных аналоговых фильтров можно пользоваться готовыми инструментами - тем же Matlab или, что еще лучше, онлайн утилитами наподобие WEBENCH от National Semiconductor (см. [7]).

AVR223-webench-filter-design01.PNG AVR223-webench-filter-design02.PNG AVR223-webench-filter-design03.PNG

3. Для узкоспециализированных фильтров можно применить даже однобитное аналогово-цифровое преобразование (с помощью компаратора). Например, такое решение вполне подходит для тональных декодеров (DTMF и т. п.). При этом код можно существенно оптимизировать под выполнение конкретной задачи - например, в случае декодера DTMF просчитывать сразу 8 полосовых фильтров для тональных частот.

Для расчета коэффициентов цифровых фильтров (ai, bj) можно опять-таки применить онлайн-инструменты (см. [4], [5], [6], [9]).

[Ссылки]

1. “Discrete-Time signal processing”, A. V. Oppenheimer & R. W. Schafer. Prentice-Hall International Inc. 1989. ISBN 0-13-216771-9
2. “Introduction to Signal Processing”, S. J. Orfanidis, Prentice Hall International Inc., 1996. ISBN 0-13-240334-X
3. FIR filter design, http://www.iowegian.com/scopefir.htm
4. FIR filter design, http://www.dsptutor.freeuk.com/FIRFilterDesign/FIRFiltDes102.html
5. FIR filter design, http://www.dsptutor.freeuk.com/KaiserFilterDesign/KaiserFilterDesign.html
6. FIR and IIR filter design, http://www-users.cs.york.ac.uk/~fisher/mkfilter/
7. WEBENCH® Designer Tools site:national.com.
8. Проектирование цифровых фильтров site:model.exponenta.ru.
9. Онлайн расчет фильтров разного вида (апплет JAVA) - Баттерворт, Чебышев, эллиптический, Бессель, Кайзер
10. В архиве: А.Б. Сергиенко. Цифровая обработка сигналов. Изд. Питер, Учебник для вузов, 2002   г., ISBN 5-318-00666-3. Айфичер Э.С., Джервис Б.У. Цифровая обработка сигналов: практический подход. 2004 г. ISBN 7-8459-0710-1 и многие другие книги по цифровой обработке сигналов.
11. Исходники примеров из апноута AVR223 с переведенными на русский язык комментариями. И еще несколько лучших, как мне кажется, книжек по ЦОС.
12. Kaiser window FIR filter design site:mathworks.com.

 

Комментарии  

 
0 #3 Radist 11.04.2011 02:35
Автору респект, действительно статья, стоящая перевода :-)
Цитировать
 
 
0 #2 truppik 08.12.2010 21:56
Очень интересно было бы прочесть про применение Быстрого Преобразования Фурье, БПФ, FFT (или его производных) в AVR для разложения сигнала на спектр на языке С.. возможна ли подобная статья в будущем?

microsin: если попадется соответствующий апноут, то его перевод в виде статьи обязательно появится. Но увы... Пока есть только апноут для PIC AN542, который не настолько интересен для перевода.
Цитировать
 
 
0 #1 foxit 08.11.2010 01:27
Где это можно применить?

microsin: для любой цифровой обработки звука. Например, Вам нужно выделить из сигнала, загрязненного шумами, сигнал с известной Вам частотой. Это как раз и может цифровой фильтр - выделить один диапазон спектра и ослабить другой. Это применяется также в тональном телеуправлении (например, тот же DTMF), распознавании сигналов отбоя АТС (PBX). Можно, например, сделать разделение каналов для цветомузыки.
Цитировать
 

Добавить комментарий


Защитный код
Обновить

Top of Page