Промышленное производство
Промышленный Интернет вещей | Промышленные материалы | Техническое обслуживание и ремонт оборудования | Промышленное программирование |
home  MfgRobots >> Промышленное производство >  >> Manufacturing Technology >> Производственный процесс

EasyFFT:быстрое преобразование Фурье (БПФ) для Arduino

Компоненты и расходные материалы

Arduino Nano R3
× 1

Приложения и онлайн-сервисы

IDE Arduino

Об этом проекте

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

Это как-то сложно закодировать, если у вас нет такого опыта. Но будучи мастером, этот код может оказаться весьма полезным для различных проектов, связанных с музыкой, анализом сигналов. Мотив этого проекта состоял в том, чтобы подготовить код, который легко реализовать на Arduino, не вдаваясь в его предысторию.

Этот проект не объясняет работу БПФ, но объясняет применение функции БПФ. Тот же процесс также объясняется в прикрепленном видео.

Если вас интересует только применение кода, а не его объяснение. Вы можете сразу перейти к шагу 3.

Если вам нужно выполнить БПФ с высокой скоростью (3x) с небольшим компромиссом в точности (около 5%), обратитесь к моей другой статье о ApproxFFT.

https://create.arduino.cc/projecthub/abhilashpatel121/approxfft-fastest-fft-function-for-arduino-fd4917?ref=user&ref_id=1593632&offset=0

Шаг 1. Быстрое преобразование Фурье

Чтобы сделать вычисления ДПФ более быстрыми, Джеймс Кули и Джон Тьюки разработали алгоритм БПФ. Этот алгоритм также считается одним из важнейших алгоритмов 20 века. Он разделяет сигнал на нечетную и четную упорядоченную часть, что сокращает количество требуемых вычислений. С его помощью общее требуемое комплексное умножение может быть уменьшено до NlogN. что является значительным улучшением. Типичное ДПФ требует комплексного умножения N * N для результатов, тогда как БПФ требует только N * logN. это значительное преимущество при большом количестве образцов.

Вы можете сослаться на нижеприведенные ссылки, на которые я ссылался при написании кода, для детального понимания математики, лежащей в основе БПФ:

1. https://flylib.com/books/en/2.729.1/derivation_of _...

2. https://jakevdp.github.io/blog/2013/08/28/understa ...

3. https://cnx.org/contents/[email protected]:zmcmahhR @ 7 / D ...

4. https://en.wikipedia.org/wiki/Fast_Fourier_transfo ...

Шаг 2. Объяснение кода

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 мс.

Шаг 3:Объяснение кода:функция БПФ

БПФ может выполняться только для размера выборки 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; a =N; for (int i =0; i <12; i ++) // вычисление уровней {if (data [i] <=a) {o =i;}} int in_ps [data [o]] ={}; // ввод для упорядочивания float out_r [data [o]] ={}; // действительная часть transformfloat out_im [data [o]] ={}; // воображаемая часть преобразования  

Дальнейший поток выглядит следующим образом:

1. Код генерирует бит с обратным порядком для заданного размера выборки (подробности об изменении битов в ссылках:шаг 2)

2. Введите данные, упорядоченные в соответствии с созданным заказом,

3. Выполнено БПФ

4. Вычисленная амплитуда комплексного числа

5. Пики обнаруживаются и упорядочиваются в порядке убывания

6. Результаты можно получить из f_peaks [].

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

Шаг 4. Тестирование кода

В качестве входных данных используется образец треугольной волны. для этой волны частота дискретизации составляет 10 Гц, а частота самой волны составляет 1,25 Гц.

Как можно увидеть из необработанных выходных данных, значение соответствует БПФ, вычисленному Scilab. однако эти значения не совсем такие же, как у нас с низкой точностью, но с более быстрой синусоидой.

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

Скорость:

для Arduino nano требуется:

  • 16 баллов:4 мс
  • 32 точки:10 мс
  • 64 балла:26 мс
  • 128 баллов:53 мс

Шаг 5. Заключение

Этот код БПФ можно использовать в приложениях реального времени. Поскольку для завершения расчета требуется около 30 мс. Однако его разрешение ограничено рядом образцов. Количество сэмплов ограничено памятью Arduino. Используя Arduino Mega или другую плату с более высокой производительностью, можно повысить точность.

Если у вас есть какие-либо вопросы, предложения или исправления, не стесняйтесь комментировать.

Код

  • EasyFFT
EasyFFT Arduino
Этот код выполняет БПФ и обновляет массив F_peasks с пятью наиболее доминирующими частотами.
 / * // Пример данных:int data [64] ={14, 30, 35, 34, 34, 40, 46, 45, 30 , 4, -26, -48, -55, -49, -37, -28, -24, -22, -13, 6, 32, 55, 65, 57, 38, 17, 1, -6, - 11, -19, -34, -51, -61, -56, -35, -7, 18, 32, 35, 34, 35, 41, 46, 43, 26, -2, -31, -50, -55, -47, -35, -27, -24, -21, -10, 11, 37, 58, 64, 55, 34, 13, -1, -7}; * /// ---- -------------------------------------------------- --------------------- // байт 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]; // 5 максимальных частот в порядке убывания // --------------------------------------- ------------------------------------ // void setup () {Serial.begin (250000); } void loop () {/ * // exampleFFT (данные, 64,100); // для получения пяти верхних значений частот X, имеющих 64 отсчета при 100 Гц samplingSerial.println (f_peaks [0]); Serial.println (f_peaks [1]); delay (99999); * // * после отказа выше FFT ( ), частоты доступны в f_peaks [0], f_peaks [1], f_peaks [2], f_peaks [3], f_peaks [4], * /} // --------------- -------------- Функция БПФ ---------------------------------- ------------ // БПФ с плавающей запятой (int in [], int N, частота с плавающей запятой) {/ * Код для выполнения БПФ на Arduino, настройка:вставьте sine_data [91] в начало программы [ глобальная переменная], вставьте функцию БПФ в конец программы Срок:1. in []:массив данных, 2. N:номер выборки (рекомендуемый размер выборки 2,4,8,16,32,64,128 ...) 3. Частота:частота дискретизации, требуемая на входе (Гц). Если размер выборки не равен 2, он будет обрезан до нижней части числа. т.е. для 150 выборок код будет рассматривать первые 128 выборок, оставшаяся выборка будет опущена. Для Arduino nano БПФ более 128 выборок невозможно из-за ограничений (рекомендуется 64). Для большего количества выборок может возникнуть проблема с памятью. проблема, код от ABHILASH Контактная информация:[email protected] Документация:https://www.instructables.com/member/abhilash_patel/instructables/2/3/2021:изменить тип данных N с float на int для> =256 выборок * / беззнаковые данные int [13] ={1,2,4,8,16,32,64,128,256,512,1024,2048}; int a, c1, f, o, x; a =N; for (int i =0; i <12; i ++) // вычисление уровней {if (data [i] <=a) {o =i;}} int in_ps [data [o]] ={}; // ввод для упорядочивания float out_r [data [o]] ={}; // действительная часть transformfloat out_im [data [o]] ={}; // мнимая часть преобразования x =0; for (int b =0; b  a) {out_r [i] =in [in_ps [i] -a];}} int i10, i11, n1; float e, c, s, tr, ti; for (int i =0; i  здесь далее out_r содержит амплитуду, а our_in содержит частоту (Гц) for (int i =0; i  out_r [i-1] &&out_r [i]> out_r [i + 1] ) {in_ps [x] =я; // массив in_ps, используемый для хранения номера пика x =x + 1;}} s =0; c =0; for (int i =0; i  360) {j =j-360;} if (j> -1 &&j <91) {out =sine_data [j];} else if (j> 90 &&j <181) {out =sine_data [180-j];} else if (j> 180 &&j <271) {out =-sine_data [j-180];} else if (j> 270 &&j <361) {out =-sine_data [360-j];} return (out / 255);} косинус с плавающей точкой (int i) {int j =i; всплывать; while (j <0) {j =j + 360;} while (j> 360) {j =j-360;} if (j> -1 &&j <91) {out =sine_data [90-j];} else if (j> 90 &&j <181) {out =-sine_data [j-90];} else if (j> 180 &&j <271) {out =-sine_data [270-j];} else if (j> 270 &&j <361) {out =sine_data [j-270];} return (out / 255);} // ---------------------- -------------------------------------------------- ------------ // 

Схема


Производственный процесс

  1. Что такое преобразование Фурье?
  2. Декодер DTMF с использованием только Arduino
  3. Система сигнализации Arduino:SERENA
  4. Связь Python3 и Arduino
  5. Мониторинг температуры SMART для школ
  6. 8-битная библиотека портов ввода-вывода для Arduino
  7. 64-клавишная матрица клавиатуры для прототипирования для Arduino
  8. Изолированный аналоговый вход для Arduino
  9. Робот для супер-крутой навигации внутри помещений
  10. Что такое код ТН ВЭД для гидравлического насоса?