Оглавление:
- Шаг 1. Введение в преобразование частоты
- Шаг 2: быстрое преобразование Фурье
- Шаг 3: объяснение кода
- Шаг 4: Объяснение кода: функция БПФ
- Шаг 5: Тестирование кода
- Шаг 6: Заключение
Видео: EasyFFT: быстрое преобразование Фурье (БПФ) для Arduino: 6 шагов
2024 Автор: John Day | [email protected]. Последнее изменение: 2024-01-30 11:48
Измерение частоты по захваченному сигналу может быть сложной задачей, особенно для Arduino, поскольку он имеет меньшую вычислительную мощность. Существуют методы, позволяющие зафиксировать переход через нуль, при котором частота фиксируется путем проверки того, сколько раз сигнал пересекает нулевую линию за заданное время. Такой метод может не работать, если сигнал представляет собой комбинацию различных частот.
Это как-то сложно закодировать, если у вас нет такого опыта. Но будучи мастером, этот код может быть очень полезен для различных проектов, связанных с музыкой, анализом сигналов. Мотив этого проекта состоял в том, чтобы подготовить код, который легко реализовать на Arduino, не вдаваясь в его предысторию.
Этот проект не объясняет работу БПФ, но объясняет применение функции БПФ. Тот же процесс также объясняется в прилагаемом видео.
Если вас интересует только применение кода, а не его объяснение. Вы можете сразу перейти к шагу 3.
Шаг 1. Введение в преобразование частоты
Любой сигнал может состоять из комбинации различных синусоидальных волн. Таким образом, любой сигнал, основанный на времени, также может быть показан как комбинация различных синусов разной амплитуды.
Я попытался объяснить работу DFT (дискретного преобразования Фурье) в одном из предыдущих инструкций (https://www.instructables.com/id/Arduino-Frequency…). Эти методы чрезвычайно медленны для любого приложения реального времени. что делает его почти бесполезным.
На изображении показан сигнал, который представляет собой комбинацию двух частот f2 и f5. Этот сигнал умножается на тестовые синусоидальные волны значений от f1 до f5.
Математически можно показать, что -сумма умножения двух наборов данных гармоник, имеющих разную частоту, стремится к нулю (большее количество данных может привести к результату теста). В нашем случае, если эти две частоты умножения имеют одинаковую (или очень близкую) частоту, сумма умножения является ненулевым числом.
Таким образом, если наш сигнал умножается на f1, сумма умножения будет равна нулю (близка к нулю для реального приложения). Аналогично обстоит дело с f3, f4. Однако для значения выходные значения f2 и f5 не будут равны нулю, а будут значительно выше остальных значений.
Здесь сигнал тестируется на 5 частотах, поэтому сигнал необходимо умножить на пять частот. Такой интенсивный расчет требует больше времени. Математически показано, что для количества выборок N требуется комплексное умножение N * N.
Шаг 2: быстрое преобразование Фурье
Чтобы сделать вычисления ДПФ более быстрыми, Джеймс Кули и Джон Тьюки разработали алгоритм БПФ. Этот алгоритм также считается одним из важнейших алгоритмов 20 века. Он разделяет сигнал на нечетную и четную упорядоченную часть, что сокращает количество требуемых вычислений. С его помощью общее требуемое комплексное умножение может быть уменьшено до NlogN. что является значительным улучшением.
Вы можете обратиться к нижеприведенным ссылкам, на которые я ссылался при написании кода, для подробного понимания математики, лежащей в основе БПФ:
1.
2.
3.
4.
Шаг 3: объяснение кода
1. Быстрый синус и косинус:
Расчет БПФ принимает значения различных синусов и косинусов несколько раз. Встроенная функция Arduino работает недостаточно быстро и требует много времени, чтобы обеспечить необходимое значение. Что делает код значительно медленнее (удваивает время для 64 образцов). Чтобы решить эту проблему, значение синуса от 0 до 90 градусов сохраняется как кратное 255. Это избавит от необходимости хранить числа в виде числа с плавающей запятой, и мы можем сохранить его как байт, который занимает 1/4 пространство на Arduino. Sine_data необходимо вставить в начало кода, чтобы объявить его как глобальную переменную.
Помимо sine_data, массив с именем f_peaks объявлен как глобальная переменная. После каждого запуска функции БПФ этот массив обновляется. Где f_peaks [0] - самая доминирующая частота и дальнейшие значения в порядке убывания.
байт sine_data [91] = {0, 4, 9, 13, 18, 22, 27, 31, 35, 40, 44, 49, 53, 57, 62, 66, 70, 75, 79, 83, 87, 91, 96, 100, 104, 108, 112, 116, 120, 124, 127, 131, 135, 139, 143, 146, 150, 153, 157, 160, 164, 167, 171, 174, 177, 180, 183, 186, 189, 192, 195, 198, 201, 204, 206, 209, 211, 214, 216, 219, 221, 223, 225, 227, 229, 231, 233, 235, 236, 238, 240, 241, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 253, 254, 254, 254, 255, 255, 255, 255}; float f_peaks [5];
Поскольку мы сохранили значение синуса от 0 до 90 градусов, можно вычислить любое значение синуса или косинуса. Ниже функция первого раунда числа до нуля десятичной точки и возврата значения из сохраненных данных. для этого метода требуется только одно плавающее деление. Это можно еще больше уменьшить, напрямую сохраняя значения синуса (не кратные 255). но это съедает большую память на Arduino.
Использование описанной выше процедуры снижает точность, но увеличивает скорость. Для 64 баллов это дает преимущество 8 мс, а для 128 баллов - 20 мс.
Шаг 4: Объяснение кода: функция БПФ
БПФ может выполняться только для размера выборки 2, 4, 8, 16, 32, 64 и так далее. если значение не 2 ^ n, то оно будет принимать меньшую сторону значения. Например, если мы выберем размер выборки 70, тогда будут учитываться только первые 64 выборки и пропустить остальные.
Всегда рекомендуется иметь размер выборки 2 ^ n. который может быть:
2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, …
Два числа с плавающей запятой out_r и out_im займут много памяти. для Arduino nano не будет работать для образцов выше 128 (а в некоторых случаях 128) из-за нехватки доступной памяти.
данные типа int без знака [13] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048};
int a, c1, f, o, x; а = N; for (int i = 0; i <12; i ++) // вычисление уровней {if (data <= a) {o = i;}} int in_ps [data [o] = {}; // ввод для упорядочивания float out_r [data [o] = {}; // вещественная часть преобразования float out_im [data [o] = {}; // воображаемая часть преобразования
Дальнейший поток выглядит следующим образом:
1. Код генерирует бит в обратном порядке для заданного размера выборки (подробности об изменении бит в ссылках: шаг 2)
2. Введите данные, упорядоченные в соответствии с созданным заказом, 3. Выполнено БПФ.
4. Рассчитанная амплитуда комплексного числа, 5. Пики обнаруживаются и упорядочиваются в порядке убывания.
6. Результаты можно получить из f_peaks.
[для доступа к другим данным (кроме пиковой частоты) необходимо изменить код, чтобы локальную переменную можно было скопировать в некоторую предопределенную глобальную переменную]
Шаг 5: Тестирование кода
В качестве входных данных используется образец треугольной волны. для этой волны частота дискретизации составляет 10 Гц, а частота самой волны составляет 1,25 Гц.
Как видно из необработанных выходных данных, значение совпадает с БПФ, вычисленным Scilab. однако эти значения не совсем такие же, как у нас с низкой точностью, но с более быстрой синусоидой.
В частотном массиве выходная частота составляет 1,25 и 3,75. нет необходимости каждый раз получать точное значение. обычно эти числа называются частотными ячейками. поэтому выходное значение может быть где угодно в пределах указанных ячеек.
Скорость:
для Arduino nano требуется:
16 точек: 4 мс 32 точки: 10 мс 64 точки: 26 мс 128 точек: 53 мс
Шаг 6: Заключение
Этот код БПФ можно использовать в приложениях реального времени. Поскольку для завершения расчета требуется около 30 мс. Однако его разрешение ограничено рядом образцов. Количество сэмплов ограничено памятью Arduino. Используя Arduino Mega или другую плату с более высокой производительностью, можно повысить точность.
если у вас есть какие-либо вопросы, предложения или исправления, не стесняйтесь комментировать.
Обновление (05.02.21)
Обновления: // ----------------------------- Функция БПФ --------------- ------------------------------- // БПФ с плавающей запятой (int in , int N, float Frequency)
Тип данных N изменен на Integer (существующий байт) для поддержки размера выборки> 255. Если размер выборки <= 128, следует использовать байтовый тип данных.
Рекомендуемые:
Визуализатор БПФ Arduino с адресуемыми светодиодами: 4 шага
Визуализатор Arduino FFT с адресуемыми светодиодами: в этом руководстве объясняется, как создать аудиовизуализатор с Arduino Uno и некоторыми адресуемыми светодиодами. Это проект, которым я хотел заняться в течение некоторого времени, потому что я любитель звукового реактивного света. Эти источники света используют БПФ (Fast Fou
QuickFFT: высокоскоростной БПФ для Arduino: 3 шага
QuickFFT: высокоскоростное БПФ для Arduino: Типичный Arduino имеет ограниченную оперативную память и вычислительную мощность, а БПФ - это процесс, требующий больших вычислительных ресурсов. Для многих приложений реального времени единственное требование - получить частоту с максимальной амплитудой или обнаруживать пики частоты. В одном из
Анализатор спектра БПФ с 1024 отсчетами с использованием Atmega1284: 9 шагов
Анализатор спектра БПФ на 1024 отсчета с использованием Atmega1284: это относительно простое руководство (учитывая сложность этого предмета) покажет вам, как можно сделать очень простой анализатор спектра на 1024 отсчета с использованием платы типа Arduino (1284 Narrow) и последовательного плоттера. Любой вид Arduino compa
Быстрое и простое зарядное устройство для iPod / портативный разъем для аксессуаров постоянного тока: 3 шага
Quick & Easy IPod Charger / Portable DC Accessory Jack: это простой дизайн, который позволит вам запускать множество различных аксессуаров постоянного тока от простой аккумуляторной батареи
Быстрое, быстрое, дешевое, красивое светодиодное освещение комнаты (для всех): 5 шагов (с изображениями)
Быстрое, быстрое, дешевое, красивое светодиодное освещение комнаты (для всех): Приветствую всех :-) Это мое первое руководство, поэтому комментарии приветствуются :-) Я надеюсь показать вам, как быстро сделать светодиодное освещение на Крошечный жучок. Что вам понадобится: кабели, светодиоды, резисторы (510 Ом на 12 В), скобы, паяльник, резцы и прочее