Реализация алгоритмов вычисления быстрого преобразования Фурье

Курсовая работа по предмету «Программирование»
Информация о работе
  • Тема: Реализация алгоритмов вычисления быстрого преобразования Фурье
  • Количество скачиваний: 78
  • Тип: Курсовая работа
  • Предмет: Программирование
  • Количество страниц: 36
  • Язык работы: Русский язык
  • Дата загрузки: 2019-01-27 00:45:40
  • Размер файла: 506.6 кб
Помогла работа? Поделись ссылкой
Информация о документе

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

Если Вы являетесь автором текста представленного на данной странице и не хотите чтобы он был размешён на нашем сайте напишите об этом перейдя по ссылке: «Правообладателям»

Можно ли скачать документ с работой

Да, скачать документ можно бесплатно, без регистрации перейдя по ссылке:

РЕФЕРАТ

Данная курсовая работа содержит (без учета разделов в приложениях) 32 страницы, 10 рисунков, 1 таблица, 2 приложения. Использовано 8 источников.

Ключевые слова: дискретное преобразование Фурье, быстрое преобразование Фурье, программирование, спектральный анализ, частотно-временной анализ звукового сигнала, цифровая обработка сигналов, микроконтроллеры.

Объектами исследования являются алгоритмы спектрального и частотно- временного анализа на 8-ми битных микроконтроллерах.

Цель работы – реализация алгоритмов вычисления быстрого преобразования Фурье, предназначенных для исполнения на 8-би битных микроконтроллерах, с целью представления спектрального и частотного анализа звукового сигнала.

Задачи работы: аналитический обзор алгоритмов спектрального анализа, изучение программных функций обработки звукового сигнала, рассмотреть основные этапы дискретизации звука, настройку и работу аналого-цифрового преобразователя, практический обзор широтно-импульсной модуляции, с последующим применением на микроконтроллере Atmel с учётом его всех архитектурных особенностей.

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

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

ОБОЗНАЧЕНИЯ И СОКРАЩЕНИЯ

БПФ – быстрое преобразование Фурье;

ДПФ – дискретное преобразование Фурье;

ШИМ – широтно-импульсная модуляция;

МК – микроконтроллер;

АЦП – аналого-цифровой преобразователь;

ЦОС – цифровая обработка сигналов;


Содержание




Введение

Кроме естественного представления сигналов во временной области в анализе сигналов и систем широко используется частотное представление. Задачу представления сигналов в частотной области называют также спектральным анализом, гармоническим анализом, частотным анализом, или Фурье-анализом. Многие физические процессы описываются в виде суммы индивидуальных частотных составляющих. Понятие спектра широко используется в представлении звуков, радио и телевещании, в физике света, в обработке любых сигналов независимо от физической природы их возникновения. На нем базируется исключительно эффективный и очень простой в использовании частотный метод анализа линейных систем.

Начала спектрального анализа заложены в 18-м веке в работах Бернулли, Эйлера, Гаусса. Основные результаты получены французскими учеными Ж. Фурье (1768 – 1830 г.г.) и П. Дирихле (1805 – 1859 г.г.) в 19-м столетии. Как самостоятельная прикладная область спектральный анализ сформировался во второй половине 20-го века.


1 Аналитический раздел

    1. Спектральный анализ

Спектральный анализ – это один из методов обработки сигналов, который позволяет охарактеризовать частотный состав измеряемого сигнала. Преобразование Фурье является математической основой, которая связывает временной или пространственный сигнал (или же некоторую модель этого сигнала) с его представлением в частотной области. Методы статистики играют важную роль в спектральном анализе, поскольку сигналы, как правило, имеют шумовой или случайный характер. Если бы основные статистические характеристики сигнала были известны точно или же их можно было бы без ошибки определить на конечном интервале этого сигнала, то спектральный анализ представлял бы собой отрасль точной науки. Однако в действительности по одному отрезку сигнала можно получить только некоторую оценку его спектра.

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

Таким образом, основная задача спектрального анализа заключается в определении частотного спектра сигнала (функции). Любой сигнал может быть представлен своим частотным спектром. Спектральный анализ основывается на классических рядах Фурье и преобразовании Фурье.

    1. Преобразование Фурье

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

Семейство преобразований Фурье (преобразование Фурье, ряды Фурье, дискретные ряды Фурье и дискретное преобразование Фурье) представлено на рисунке 1. С течением времени принятые определения получили развитие в зависимости от того, является ли сигнал непрерывно-апериодическим, непрерывно-периодическим, дискретно-апериодическим или дискретно-периодическим

Рисунок 1– Семейство преобразований Фурье

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

Фундаментальное уравнение для получения N-точечного ДПФ выглядит следующим образом:

Рисунок 2 – Уравнение N-точечного ДПФ

По отношению к этому уравнению следует сделать некоторые терминологические разъяснения. X(k) (прописная буква X) представляет собой частотный выход ДПФ в k-ой точке спектра, где k находится в диапазоне от 0 до N-1. N представляет собой число отсчетов при вычислении ДПФ. Значение x(n) (строчная буква x) представляет собой n-ый отсчет во временной области, где n также находится в диапазоне от 0 до N-1. В общем уравнении x(n) может быть вещественным или комплексным.

Периодичность анализируемого сигнала при вычислении БПФ может быть лучше всего проиллюстрирована на выполнении N-точечного БПФ с синусоидальным входным сигналом. Рассмотрим две ситуации. В первом случае соотношение между частотой дискретизации и частотой входного синусоидального сигнала таково, что в выборке содержится в точности целое число периодов синусоидального сигнала.

Рисунок 3–БПФ периодичного сигнала

Для спектрального представления непериодических (импульсных) сигналов, заданных на конечном интервале, непосредственно воспользоваться рядом Фурье нельзя. Для гармонического разложения сигнала мысленно дополняют его такими же импульсными сигналами до периодического с некоторым интервалом.

Рисунок 4 – БПФ не периодичного сигнала

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

Рисунок 5 – Применение функции окна на входной сигнал

Все описанные выше этапы преобразования являются обязательными для построения спектрального анализа любого входного сигнала. Также, стоит отметить, что применение БПФ имеет смысл, если число элементов в анализируемой последовательности, т.е. размер самой выборки, является степенью числа 2.

    1. Быстрое Преобразование Фурье. Функции

В данной работе была использована математическая библиотека FastFouriertransform с размером N выборки в 128 точек. Программная библиотека быстрого преобразования Фурье имеет встроенные функции, соответствующие поэтапному преобразованию Фурье. С точки зрения программного кода (Приложение Б), все данные помещаются в один глобальный массив fht_input[],и все последующее преобразование разделяется на 4 основные функции в порядке использования:

fht_window() – Применение окна Ханна (Хеннинга). Эта функция умножает входные данные на функцию окна, чтобы увеличить частотное разрешение данных.

fht_reorder()–Функция переупорядочивания частотных данных. После её применения, все частотные данные распределяются в массиве fht_input[] в порядке увеличения частоты.

fht_run()–Это основной вызов функции БПФ. Он не принимает переменных и не возвращает переменных. Данные хранятся в массиве с именем fht_input [], который содержит 16-битное число для каждой точки данных БПФ.

fht_mag_lin()–Представление данные в линейном виде. Данная функция последняя и она определяет, в каком виде будут выходные частотные данные. Для этого, суммируются квадраты мнимой и вещественной части, а затем берется квадратный корень. Данные берутся из fht_input []и возвращаются в новый массив fht_lin_out []. Все значения находятся в последовательном порядке.



2 Конструкторский раздел

    1. Выбор языка программирования

Для реализации данного курсового проекта был выбран язык программирования C++. Это компилируемый, статически типизированный язык программирования общего назначения. C++ сочетает свойства как высокоуровневых, так и низкоуровневых языков. В сравнении с его предшественником — языком C, — наибольшее внимание уделено поддержке объектно-ориентированного и обобщённого программирования.

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

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

Выбор интегрированной среды разработки был обусловлен моделью микроконтроллера. В нашем случае это 8-битный микроконтроллер Atmel ATMEGA328P и среда разработки AtmelStudio 7.

    1. Микроконтроллер ATMEGA328P

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

Устройства памяти включают оперативную память (RAM), постоянные запоминающие устройства (ROM), перепрограммируемую ROM (EPROM), электрически перепрограммируемую ROM (EEPROM). Таймеры включают, и часы реального времени, и таймеры прерываний. Средства I/O включают последовательные порты связи, параллельные порты (I/O линии), аналого-цифровые преобразователи (A/D), цифроаналоговые преобразователи (D/A), драйверы жидкокристаллического дисплея (LCD) или драйверы вакуумного флуоресцентного дисплея (VFD). Встроенные устройства обладают повышенной надежностью, поскольку они не требуют никаких внешних электрических цепей.

Микроконтроллеры можно встретить в огромном количестве современных промышленных и бытовых приборов: станках, автомобилях, телефонах, телевизорах, холодильниках, стиральных машинах и даже кофеварках. Среди производителей микроконтроллеров можно назвать Intel, Motorola, Hitachi, Microchip, Atmel, Philips, TexasInstruments и многих других.

Основным классификационным признаком микроконтроллеров является разрядность данных, обрабатываемых арифметико-логическим устройством (АЛУ). По этому признаку они делятся на 4-, 8-, 16-, 32- и 64-разрядные. Сегодня наибольшая доля мирового рынка микроконтроллеров принадлежит восьмиразрядным устройствам (около 50 % в стоимостном выражении). За ними следуют 16-разрядные и DSP-микроконтроллеры (DSP - DigitalSignalProcessor - цифровой сигнальный процессор), ориентированные на использование в системах обработки сигналов (каждая из групп занимает примерно по 20 % рынка). Внутри каждой группы микроконтроллеры делятся на CISC- и RISC-устройства. Наиболее многочисленной группой являются CISC-микроконтроллеры, но в последние годы среди новых чипов наметилась явная тенденция роста доли RISC-архитектуры.

Тактовая частота, или, более точно, скорость шины, определяет, сколько вычислений может быть выполнено за единицу времени. В основном производительность микроконтроллера и потребляемая им мощность увеличиваются с повышением тактовой частоты. Производительность микроконтроллера измеряют в MIPS (MillionInstruсtionsperSecond - миллион инструкций в секунду).

Данный проект реализован на плате ArduinoNANOс 8-битным микроконтроллером ATmega328Pамериканской фирмы Atmel. Ниже приведены некоторые его характеристики.

Таблица 1– Основные характеристики МК ATmega328P

Архитектура ядра

AVR

Разрядность шины данных

8 бит

Тактовая частота, МГц

16

Напряжение питания, В

1,8…5,5

Объем памяти, Кб

32

Встроенная периферия

PWM, POR, WDT

Рабочая температура, ̊С

-40…+85

    1. Аналого-цифровое преобразование

Число в цифровой форме определяется на основании отношения входного напряжения к полному номиналу напряжения аналого-цифрового преобразователя (АЦП). Например, если на вход АЦП с номинальным напряжением 5 Вольт подать напряжение 1 Вольт то на цифровом выходе появится число, соответствующее 1/5=0,2 разрешающей способности преобразователя. Так, если используется АЦП с разрешением 8 бит, то максимальное возможное значение на его выходе 256 – 1 = 255. Таким образом, напряжению 1 В на аналоговом входе соответствует 0,2 * 255 = 51 на цифровом выходе.

Встроенный АЦП микроконтроллеров AVR и PIC имеет разрешение 10 бит и позволяют считывать напряжение на одном из восьми (в некоторых моделях – пяти) аналоговых входов (обычно – порт А).

АЦП преобразует аналоговый сигнал в цифровой, но для этого является обязательным условие, чтобы измерения проводились точно там, где есть сигнал. Иначе будут потери данных и вовсе его полное некорректное преобразование. Для достижения данной задачи, нужно правильно установить опорное напряжение 10-битного АЦП и входного сигнала. Сделать это можно 2 способами:

  1. Поднять входной сигнал до опорного напряжения АЦП

  2. Изменить само опорное напряжение АЦП до уровня входного сигнала

Рисунок 6 – Изменение опорного напряжения

В нашем курсовом проекте был использован второй вариант. С помощью встроенного в МК стабилитрона, в регистре ADMUX, было установлено опорное напряжение равное 1.1 Вольт. Что соответствует максимальному напряжению входного звукового сигнала.

Далее все дискретные входные данные будут рассчитываться так, что 1 единица данных в настоящий момент времени будет равна 1,1/1024 = 0,001 Вольт.

    1. Дискретизация звукового сигнала

Дискретизация входного сигнала происходит в методе voidcapture_wave. В процессе настройки АЦП мы выбрали частоту дискретизации звука, путем деления тактовый частоты МК на делитель АЦП, равный 64. Получаем следующую частоту 16 000 000/64 = 250 000 ГЦ, но, на обработку только одного отсчета у АЦП уйдет 13 тактов МК, согласно рисунку 7 преобразования.

Рисунок 7 – Потактовая схема работы АЦП

В результате, делим 250000Гц /13 = 19230 Гц. Именно столько отсчетов сможет сделать АЦП за одну секунду, но, согласно теореме Котельникова-Найквиста-Шеннона, которая гласит о том, чтобы восстановить или дискретизировать сигнал без потерь, частота дискретизации должна быть в 2 раза больше самой высокой частоты восстанавливаемого сигнала.

То есть, самую высокую частоту в сигнале, которую сможет оцифровать АЦП, равна 19230 / 2 = 9615 ГЦ

Это и будет являться границей нашего преобразования и отображения спектра звукового сигнала. Шаг дискретизации согласно всем условиям будет равен 9615 Гц/128 = 75 Гц.


3 Технологический раздел

    1. Программная широтно-импульсная модуляция

ШИМ – это метод, в котором ширина импульса изменяется с фиксированной частотой ШИМ для достижения аналогового выхода в диапазоне от 0 до 100 процентов. Несмотря на то, что многие МК имеют встроенные аппаратные инструменты ШИМ, они обладают определенными ограничениями, такими как ограниченное число на выводах МК и разрядностью.

Для решения это проблемы, был реализован программный ШИМ, на каждом из 8 цифровых выводов МК. Желаемый уровень скважности, а, следовательно, и яркости свечения светодиодов, достигается путем изменения значений из массива peak[].

Рисунок 8 – Принцип работы программного ШИМ

В данном проекте был реализован программный широтно-импульсный модулятор, с частотой 60 Гц, и разрядностью 10 бит, т.е. 210= 1024. Разрядность формирует длину цикла модуляции, который равен 16,6 мс. При помощи счетчика pwm_cnt аналоговое значение преобразуется в двоичное представление сигнала во времени. Данный тип модуляции был реализован, используя один встроенный в МК таймер по совпадению Timer1 COMP.

    1. Прерывания и настройка таймеров

Тактовая частота МК равна 16 МГц, значит, время возникновения нового такта равна 1/16 000 000 = 62,5*10-9=62,5 нс. Делитель тактовой частоты выбран 1, то есть МК работает на максимальной частоте.

В данном проекте был использован один встроенный таймер.Timer1 COMP–встроенный 16-битный таймер, работающий в режиме «сброс по совпадению с А или В», при максимальном допустимом числе в таймере равным 216 = 65536. Данный таймер будет выполнять написанный в нем код тогда и только тогда, когда регистр TCNT1 станет равным числу в регистре OCR1A или OCR1B (для чисел А и В соответственно). Это помогает установить желаемое время или событие для срабатывания таймера и выполнения кода внутри него.

Таким образом, первый таймерTIMER1_COMPA_vect, работающий по совпадению с числом А, выполняется на скорости 16,6 мс или 60 Гц. Он же и задаёт ширину импульса и в целом ШИМ на всех 8 цифровых выводах МК.

Регистр OCR1A, равен 16 000 000/(60*1024) = 260,4. Почему же именно такое число? Умножаем на скорость тактирования МК и получим ширину одного импульса 260,4*62,5 = 0,0000163 = 16 мкс. Далее умножим на разрядность ШИМ и получим время одного полного цикла ШИМ 16 мкс*1024 = 0,0166656 с = 16,6 мс. Что и соответствует частоте 60 Гц.

Второй регистр OCR1Bравен UINT16_MAX = 65535. Это означает, что скорость срабатывания данного таймера равна 62,5 нс*65535 = 0,004096с=4,1 мс. Отсюда следует, что таймерTIMER1_COMPB_vect, работающий по совпадению с числом В, выполняется каждые 4,1 мс или 244 раза в секунду.

Данные вычисления помогли определить время и внедрить промежуточный счетчик «almostsec» внутри таймера для отсчета целых секунд времени.

    1. Режимы представления спектрального преобразования

Для более корректного и полного отображения спектра были реализованы 3 режима обработки частотной области входного звукового сигнала.

  1. Спектр звукового сигнала.

В данном режиме все частоты складываются и перераспределяются в новый массив capture[]. Далее каждый элемент данного массива будут соответствовать выводу порта D и подключенным к ним светодиодам соответственно.

Согласно программному преобразованию Фурье, массив распределен на 2 половины, поэтому мы будем брать только действительные данные о частотах в первой половине массива с шагом в 9615 Гц/64 = 150 Гц.

Отсюда, диапазон спектра на каждый из 8 выводов будет равен

  1. 150 – 600 Гц

  2. 600 – 1350 Гц

  3. 1350 – 2250 Гц

  4. 2250 – 3600 Гц

  5. 3600 – 5100 Гц

  6. 5100 – 6600 Гц

  7. 6600 – 8100 Гц

  8. 8100 – 9615 Гц

  1. Зеркальный 4-х канальный режим.

В данном режиме частотная область была распределена на 4 части, и отображена в симметричном виде.

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

Частотный диапазон в данном режиме будет описываться на каждый светодиод как

  1. 150 – 1200 Гц

  2. 1200 – 2250 Гц

  3. 2250 – 5850 Гц

  4. 5850 – 9615 Гц

  1. Режим частотной суммы звукового сигнала.

Особенностью данного режима является то, что на выходе порта D отображается вся частотной область в виде нарастающей шкалы.

Все частоты складываются в одну переменную vmetr, затем умножаются на понижающий коэффициент, и делятся на 8 частей. Каждой части соответствует свой вывод на порту D и подключенные к нему светодиоды.

Частотный диапазон в данном режиме будет отображаться следующим описанием с равным шагом в 1201 Гц

  1. От 0 Гц и более

  2. От 1201 Гц и более

  3. От 2402 Гц и более

  4. От 3603 Гц и более

  5. От 4804 Гц и более

  6. От 6005 Гц и более

  7. От 7206 Гц и более

  8. От 8407 Гц до 9615 Гц

В результате получается «шкала частотной насыщенности звукового сигнала».

    1. Обработка и вывод частотных данных на светодиоды

После распределения частот согласно установленному режиму, все данные проходят последнюю процедуру обработки.

Сначала каждый «канал» или элемент массива проверяется на минимальные и максимальные пороговые значения переменными min_value и max_value соответственно. Эти переменные содержат определенные значения для каждого режима, и при его изменении, устанавливаются в методе void SetValueMode. Это сделано для предотвращения некорректного вывода, в случаях непредсказуемых изменений, как в исходных, так и в выходных данных.

Затем, для каждого из каналов происходит проверка, если настоящее значения канала больше предыдущего, то выводится новое значение, иначе отображается предыдущее.

Рисунок 9 – Экспоненциальное соотношение восприятия света человеческим глазом

В силу того, что человеческий глаз воспринимает свет не линейно, а экспоненциально, для равномерного и плавного отображения света, согласно рисунку 9, была подобрана экспоненциальная таблица яркости ШИМ для всех целых значений, и занесены в массив. После, устанавливается соответствующее значение яркости ШИМ из массива pwmtable_10[].


4 Экспериментальный раздел

  1. Контроль качества разрабатываемого устройства

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

Тестирование можно разделить на три основных этапа:

  1. проверку основных частей устройства (процессора, памяти, прочих модулей);

  2. проверку программных и периферийных интерфейсов;

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

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

  1. Алиасинг эффект

Алиасинг — одна из главных проблем при аналого-цифровом преобразовании видео - и аудиосигналов. Неправильная дискретизация аналогового сигнала приводит к тому, что его высокочастотные составляющие накладываются на низкочастотные. В результате чего восстановление сигнала во времени приводит к его искажениям. Эффект Алиасинга хорошо продемонстрирован на рисунке 10.

Рисунок 10 –Алиасинг эффект

Алиасинг эффект возникает по причине того, что нарушается теорема Котельникова-Найквиста.

Частота Найквиста – это максимально высокая частота звука умноженная на 2. Поэтому частота Найквиста, а, следовательно, и частота дискретизации должны быть 9615 Гц*2 =19230 Гц. Иначе, если же оцифрован сигнал с частотой большей, чем половина частоты дискретизации, возникает частотный сдвиг, а именно, высокие частоты будут накладываться на низкие.

Другими словами, если попытаться дискретизировать сигнал с частотой более 9615 Гц, то возникнет зеркальный эффект. Не впадая в глубокое математическое описание этого эффекта, рассмотрим итог аналогово-цифрового преобразования на частоте 12000 Гц.

(12000 - 9615) = 2385 Гц.

Так что при 12000 Гц будет 2385 Гц поверх частоты Найквиста, результирующая волна будет 7230 Гц (9615 – 2385).То есть, АЦП будет оцифровывать сигнал с частотой 12000 ГЦ как 7230 Гц.

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

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

  1. Стабилизация работы устройства

Так как, в устройстве присутствует такие радиоэлементы как светодиоды и кнопка переключения, был произведен расчет резисторов, а также программная «защита от дребезга» переменными ScanPeriodButton, bButton и bOldButton. В силу природы возникновения дребезг контакта, который возникает при замыкании коммутатора, имеет определенное среднее время возникновения, равное 5 мс. Для предотвращения этого явления, было выбрано значение переменной ScanPeriodButton = 4, и, как упоминалось ранее, TIMER1_COMPB_vect работает на частоте 244 Гц или каждые 4,1 мс. Отсюда следует, что время возникновения опроса кнопки равно 4*4,1 = 16,4 мс, т.е. более чем в 3 раза времени потенциального размыкания коммутатора, что сводит к минимуму неправильную работу кнопки переключения режимов.

Основная формула для расчета резисторов представлена выше. Где R- сопротивление резистора, Uип–напряжение источника питания, Uvd2–падение напряжение на светодиоде, Ivd2–номинальный ток потребления светодиода.

Также, для стабилизации и ускорения работы микроконтроллера, программно была создана проверка наличия входного сигнала переменными no_audio и pause. При его отсутствии прекращается выполнение основного тела программы, и производится переход работы в таймер TIMER1_COMPB_vect. В нем же реализована «защита от дребезга» кнопки и эффект бегущих огней, который можно наблюдать при отсутствии аудио сигнала.

Заключение

В результате выполнения данного курсового проекта было разработано программное устройство для получения спектрального анализа звукового сигнала на основе микроконтроллера ATMEGA328P. В ходе работы были сделаны следующие выводы:

  • Разрешение по частоте F, получаемое при спектральном анализе с помощью БПФ, вычисляется по формуле (1): F = Fs/(13*Т), где Т – делитель АЦП, 13 – тактовая скорость преобразования АЦП, Fs – частота работы МК.

  • Частота дискретизации должна удовлетворять условиям теоремы Котельникова, то есть быть как минимум в 2 раза больше максимально необходимого для спектрального анализа частотного компонента входного сигнала.

Также было проведено исследование полученного программного устройства. В результате были выявлены следующие достоинства и недостатки:

Достоинства:

  1. Простота использования и монтажа, для потенциального внедрения в иные системы и проекты;

  2. Реализация в проекте ШИМ и различных режимов отображения спектра позволяет детально отобразить частотную составляющую входного сигнала, и, в целом, возможности спектрального анализа.

Недостатки:

  1. Выходные данные полностью зависят от номинального уровня напряжения входного сигнала;

  2. Невозможность отобразить спектр входного сигнала более 9615 Гц.

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

Список источников

  1. http://www.getchip.net/wp-content/uploads/Measured_vs_Perceived.pdf

  2. Brent Edstrom. Arduino for Musicians: A Complete Guide to Arduino and Teensy Microcontrollers Oxford University Press, 2016. 304 с.

  3. ГолдБ., Рэйдер Ч. Цифровая обработка сигналов / Пер. с англ. под ред. А.М. Трахтмана. – М: Советское радио, 1973. – 368 с.

  4. Куприянов М.С., Матюшкин Б.Д. Цифровая обработка сигналов: процессоры, алгоритмы, средства проектирования. –СПб.: Политехника, 1998. – 592 с.

  5. Лебедев Е.К. Быстрые алгоритмы цифровой обработки сигналов. – Красноярск, Красноярский университет, 1989. – 192 с.

  6. Сергиенко А.Б. Цифровая обработка сигналов 2-е издание. Учебник для вузов. – СПб.: Питер, 2007. – 751 с.

  7. Баскаков С.И. Радиотехнические цепи и сигналы: Учебник для вузов. -М.: Высшая школа, 2000. -462 с

  8. Солонина А.И. и др. Основы цифровой обработки сигналов. Учебное пособие. - СПб.: БХВ Петербург, 2005. - 768 с.



Приложение А. Принципиальная схема устройства

Рисунок 1 – Принципиальная схема устройства


Приложение Б. Листинг программы

/*------------------------------------------------*/

#define FHT_N 128


#include <string.h>

#include <avr/io.h>

#include <avr/interrupt.h>

#include "FHT.h"


#define F_CPU 16000000UL

#define CHANNELS 8

#define PWM_HZ 60UL // ЧастотаШИМ 60 Герц

#define PWM_STEPS 1024 // РАзрядностьШИМ 1024

#define T_PWM (F_CPU / (PWM_HZ * PWM_STEPS)) // ШиринаимпульсаШИМ


/*------------------------------------------------*/

/* Глобальныепеременные */


#define LED_PORT PORTD

#define LED_DIR DDRD


#define LED1 (1 << PD0)

#define LED2 (1 << PD1)

#define LED3 (1 << PD2)

#define LED4 (1 << PD3)

#define LED5 (1 << PD4)

#define LED6 (1 << PD5)

#define LED7 (1 << PD6)

#define LED8 (1 << PD7)


int16_t capture[CHANNELS]; // МассиввходногосигналапослепреобразованияФурье

volatile uint16_t pwm_setting[CHANNELS]; // МассиввыходногозначенияШИМ

volatile uint8_t peak[CHANNELS]; // МассивпиковыхзначенийШИМ

volatile static uint16_t vmetr=0; // ОбщийканалдлярежимаvMetr


volatile static uint8_t mode = 1; // Номеррежима

volatile static uint8_t soundSpectr = 1; // Режимспектрапоумолчанию

volatile static uint8_t colorMusic = 0; //ФлагрежимаЦветомузыки

volatile static uint8_t vuMetr = 0; // ФлагрежимаВольтметр


volatile uint8_t no_audio; // глобальныйфлаготсутствияаудио

volatile uint8_t pause; // глобальный флаг включения бегущих огней


volatile uint16_t min_value ; // минимальное пороговое значение каналов

volatileuint16_tmax_value ; // максимальноепороговое значение каналов

volatile uint8_t fourChannels; //4 каналадля 2 режима

volatile uint16_t devider = 180; // делитель

volatile uint16_t fade = 0;

volatile static uint16_t fadespeed = 300; // скоростьзатуханияогней

volatile static unsigned char second = 0;

volatile static unsigned char changeValue = 1;


const volatile static uint8_t MaxBright = 63; // константамаксимальногоадресавтаблицеяркости


//матрица ШИМ на каждый канал (яркости)

const uint16_t pwmtable_10[64] = { 0, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6, 6, 7, 8, 9, 10, 11, 12, 13, 15, 17, 19, 21,

23, 26, 29, 32, 36, 40, 44, 49, 55, 61, 68, 76, 85, 94, 105, 117, 131, 146, 162, 181, 202, 225, 250, 279, 311, 346, 386, 430,

479, 534, 595, 663, 739, 824, 918, 1023 };


/*------------------------------------------------*/

/* Timer 1 Output COMPARE A Interrupt */


ISR( TIMER1_COMPA_vect ) {

static uint16_t pwm_cnt = 0; // счетчикШИМ

uint8_t tmp = 0; //маска порта D

OCR1A += (uint16_t) T_PWM; //задаем ширину импульса


//==================================================+

// Широтно-Импульсная Модуляция |

//==================================================+


if (colorMusic)

{

if(pwm_setting[0] >pwm_cnt) {

tmp |= LED1;

tmp |= LED8;

}

if(pwm_setting[1] >pwm_cnt) {

tmp |= LED2;

tmp |= LED7;

}

if(pwm_setting[2] >pwm_cnt) {

tmp |= LED3;

tmp |= LED6;

}

if(pwm_setting[3] >pwm_cnt) {

tmp |= LED4;

tmp |= LED5;

}

}

else{

if(pwm_setting[0] >pwm_cnt) tmp |= LED1;

if(pwm_setting[1] >pwm_cnt) tmp |= LED2;

if(pwm_setting[2] >pwm_cnt) tmp |= LED3;

if(pwm_setting[3] >pwm_cnt) tmp |= LED4;

if(pwm_setting[4] >pwm_cnt) tmp |= LED5;

if(pwm_setting[5] >pwm_cnt) tmp |= LED6;

if(pwm_setting[6] >pwm_cnt) tmp |= LED7;

if(pwm_setting[7] >pwm_cnt) tmp |= LED8;

}

PORTD = tmp;

// непосредственносчетчикдляотрисовкиШИМ( pwm_setting[y] >pwm_cnt )

if(pwm_cnt == (1024 - 1)) pwm_cnt = 0;

else pwm_cnt++;

if( fade == fadespeed) {

for(uint8_t y = 0; y < CHANNELS; y++)

if(peak[y]) peak[y]--;


fade = 0;

}

fade++;

}


ISR( TIMER1_COMPB_vect ) {

static unsigned char ScanPeriodButton=4; // защитаот "дребезга"

static unsigned char bButton, bOldButton; // флагидляраспознаваниянажатиякнопки

static unsigned char changeMode = 1; // флагсменырежима

staticunsignedcharalmostsec = 0; //"почтисекунда" - условная временная единица.

staticunsignedcharsecond = 0; // переменнаядляотсчетацелых секунд

staticunsignedcharevent = 0; // флагсрабатывания/действия

staticunsignedcharvector = 1; // флагнаправлениябегущегоогня

static int8_t chanelfx; // бегущийогонь


OCR1B += (uint16_t) UINT16_MAX; // таймерпрерывания

if (ScanPeriodButton) ScanPeriodButton--; // отсчетпериодичностиопросакнопки

else{ // по истечению периода опроса проверяем состояния кнопки

ScanPeriodButton=4; // перезагружаем счетчик периода опроса

if ((!(PINB & (1<<PB5)))) {

bButton = 1;

bOldButton = 1;

}

else bButton = 0;

if ((bOldButton == 1) & !(bButton == 1)) {

changeMode = 1; // флаг смены режима для индикации

changeValue = 1; // флаг смены режима для установки значений

mode++;

if (mode > 3) mode = 1;

bOldButton = 0;

}

}

if (changeMode)

{

switch (mode)

{

case 1:

soundSpectr = 1;

colorMusic = 0;

vuMetr = 0;

PORTC |= (1 << PB3);

PORTC &= ~(1<<PB2);

PORTC &= ~(1<<PB1);

break;

case 2:

soundSpectr = 0;

colorMusic = 1;

vuMetr = 0;

PORTC |= (1 << PB2);

PORTC &= ~(1<<PB1);

PORTC &= ~(1<<PB3);

break;

case 3:

soundSpectr = 0;

colorMusic = 0;

vuMetr = 1;

PORTC |= (1 << PB1);

PORTC &= ~(1<<PB2);

PORTC &= ~(1<<PB3);

break;

}

changeMode = 0;

}

if ((no_audio == 1) && (pause == 0)) { // если звука нет и нам надо определить переходить ли в "паузу"

almostsec++; // счетчик "почтисекунд"

if (almostsec == 244) { // условно 244 почтисекунд = 1 секунде

second++; // считаем секунды

almostsec = 0;

}

if (second == 5) { // если 5 условных секунд нету сигнала переходим в паузу

pause = 1;

second = 0;

if (vector) vector = 0;

elsevector = 1;

}

}


if (pause == 1) { // если пауза включена - обработка эффектов, иначе обходим стороной

almostsec++; //

fadespeed = 1000;

if (almostsec == 60) {

event = 1;

almostsec = 0;

}


if (event == 1) {

if (vector == 1) {

peak[chanelfx] = MaxBright-15;

chanelfx++;

if (chanelfx> (CHANNELS-1)) chanelfx = 0;

}

else {

peak[chanelfx] = MaxBright-15;

chanelfx--;

if (chanelfx< 0) chanelfx = CHANNELS-1;

}

event = 0;

}

} else fadespeed = 320;

}


void capture_wave(int16_t *buffer, uint16_t count) {

ADMUX = _BV(ADLAR)|_BV(MUX2); // Опорное напряжение с AREF, вход аудио с 4 аналоговой ножки


for (uint16_t y = 0; y < count; y++)

{

ADCSRA = _BV(ADEN)|_BV(ADSC)|_BV(ADATE)|_BV(ADIF)|_BV(ADPS2)|_BV(ADPS1); //ЧАЦП = 250кГц (16000000 / 64)

while ((ADCSRA & (1 << ADIF)) == 0); // Не идем дальше, пока не закончилось преобразование АЦП

*buffer++ = ADC - 32768; //Убираем отрицательную часть сигнала

}

ADCSRA = 0;

}


void SetValueMode(){

if (colorMusic)

{

devider = 350;

min_value = 3000;

fourChannels = 4;

}

if (soundSpectr) {

devider = 150;

min_value = 2500;

fourChannels = 0;

}

if (vuMetr){

devider = 80;

min_value = 2000;

fourChannels = 0;

}

max_value = ((UINT16_MAX / 2) + min_value); // установка нового максимума

}


void CheckPause(){

if((capture[0] > 0) || (capture[1] > 0) || (capture[2] > 0) || (capture[3] > 0) || (capture[4] > 0) || (capture[5] > 0)

|| (capture[6] > 0) || (capture[7] > 0) ) { // если сигнал есть, то паузы не будет.


if (pause != 0) fade = 0;

no_audio = 0;

pause = 0;

second = 0;

}

else{ // если сигнала нет, то в прерывании начнется отсчет псевдосекунд до включения паузы.

no_audio = 1;

}

}


int main (void) {

uint16_t spectrum;

LED_DIR |= (LED1 | LED2 | LED3 | LED4 | LED5 | LED6 | LED7 | LED8);

LED_PORT &= ~(LED1 | LED2 | LED3 | LED4 | LED5 | LED6 | LED7 | LED8);

PORTB |= (1<<PB5); // Кнопка переключения режимов

DDRC = 0b00001111; // Установка 0 аналогового пина как GND

TCCR1B = (1<<CS10); // Таймер работает на полной частоте системы

TIMSK1 |= _BV(OCIE1A) | _BV(OCIE1B); // Разрешить прерывания по совпадению с А и B

sei(); // Разрешить прерывания глобально

for(;;) {

// чистка массива перед повторным использованием

memset(fht_input, 0, sizeof(fht_input) );


capture_wave(fht_input, FHT_N); // захват входного сигнала

fht_window(); //применение функции окна Ханна

fht_reorder(); // переупорядочивание частотных данных

fht_run(); //быстрое преобразование Фурье

fht_mag_lin(); // получение частотных данных в линейном виде


memset( capture, 0, sizeof(capture) ); // чистка массива перед повторным использованием

vmetr = 0;

if (changeValue){

SetValueMode(); // установка значений для разных режимов

changeValue = 0;

}

//==================================================+

// Разложение спектра на каналы |

//==================================================+

for (uint16_t n = 2; n < FHT_N / 2; n++) {


spectrum = fht_lin_out[n];

if (colorMusic)

{

switch (n)

{

case 2 ... 8: capture[0] += spectrum; // низкиечастоты

break;

case 9 ... 15: capture[1] += spectrum;

break;

case 16 ... 39: capture[2] += spectrum;

break;

case 40 ... 63: capture[3] += spectrum; // высокиечастоты

break;

}

}

else{

switch (n)

{

case 2 ... 4: capture[0] += spectrum; // низкиечастоты

break;

case 5 ... 9: capture[1] += spectrum;

break;

case 10 ... 15: capture[2] += spectrum;

break;

case 16 ... 24: capture[3] += spectrum;

break;

case 25 ... 34: capture[4] += spectrum;

break;

case 35 ... 44: capture[5] += spectrum;

break;

case 45 ... 54: capture[6] += spectrum;

break;

case 55 ... 63: capture[7] += spectrum; // высокиечастоты

break;

}

}

}

//==================================================+

// Установка значений для обработки через ШИМ | //==================================================+


for(uint8_t led = 0; led < (CHANNELS - fourChannels); led++) {

if ( capture[led] >max_value) capture[led] = max_value; // избавляемсяотситуации, где capture[] будетбольшемакс.значения

if(capture[led] >min_value) capture[led] -= min_value; // убираем все, что не дотянуло до порогового значения

else capture[led] = 0;

capture[led] = capture[led] / devider; // Используемделитель

if(capture[led] >MaxBright) capture[led] = MaxBright; // избавляемсяотситуации, где capture[] будетбольше 63


if (vuMetr) // РежимVUMetr

{

vmetr += capture[led];

for (uint8_t z =0; z < CHANNELS; z++)

if ((vmetr/(MaxBright)) > z)

peak[z] = MaxBright-5;

} else

{

if(capture[led] >= peak[led])

peak[led] = capture[led]; // установкановогопика

}

pwm_setting[led] = pwmtable_10[peak[led]]; // передаем в pwm_setting[] уровень яркости для обработки ШИМ

}

CheckPause(); // Проверка сигнала и переход в паузу

}

}