FFT-спектральный анализатор низких частот

denysKo_O
Offline
Зарегистрирован: 07.01.2017

Решил реализовать анализ звукого сигнала, особенно низких частот. За основу взял вот эту статью 

http://wiki.amperka.ru/slot-box:light-show?utm_source=proj&utm_campaign=...

переписал код таким образом:

// включаем функцию для логарифмического формата
#define LOG_OUT           1
// задаем количество выходных отсчетов
#define FFT_N             384
// подключаем библиотеку FFT — быстрое преобразование Фурье
#include <FFT.h>
// номер пина датчика микрофона
#define MIC_PIN           A0

long previousMillis = 0;
void setup()
{
  // открываем последовательный порт
  Serial.begin(115200);
  // назначаем пины светодиодов в режим выхода
}

void loop()
{
  // считываем заданное количество отсчётов
  for (int i = 0 ; i < FFT_N; i++) {
    // считываем показания микрофона и вычитаем отрицательную полу-волну
    int sample = analogRead(MIC_PIN) - 511;//153
    // игнорируем помехи АЦП
    if (sample < 5 && sample > -5) {
      sample = 0;
    }
    // сохраняем действительные значения в четные отсчеты
    fft_input[i++] = sample;
    // задаем нечетным отсчетам значение «0»
    fft_input[i] = 0;
  }
  // функция-окно, повышающая частотное разрешение
  fft_window();
  // реорганизовываем данные перед запуском FFT
  fft_reorder();
  // обрабатываем данные в FFT
  fft_run();
  // извлекаем данные, обработанные FFT
  fft_mag_log();
  // выводим значения преобразования Фурье
 // Serial.print("<");
 // Serial.print(FFT_N / 2);
 // Serial.print(":");
  int max = 1;
  int curr = 0;
  for (int curBin = 0; curBin < FFT_N / 2; ++curBin) {
    if (curBin > 0) {
      //Serial.print(",");
    }
    if (fft_log_out[curBin] > max)
    {
      max = fft_log_out[curBin];
      curr = curBin;
    }
    // Serial.print(fft_log_out[curBin]);
  }
//  Serial.println(">");

 if (millis() - previousMillis > 800)
  {
      Serial.println(curr*35.7142);
  }
}

Микрофон использую Sound Detection Sensor KY-037 и ардуино НАНО(328). Частоты выше 100 герц-находит почти замечательно(погрешность +-10 герц, нужно доделать усреднение просто, примен на 1000 герцах показывает 989,1002,1012,995 и т д.)
но вот ниже-не меряет частоту
проблема не в мирофоне!
отображал синусоиду на график на компе, с помощью SerialPortPlotter. Микрофон понимает до 40 герц.
из кода, Serial.println(curr*35.7142); константа 35,7142 была найдена експерементальным путем, и умножая curr на нее, можно находить частоту.

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

denysKo_O
Offline
Зарегистрирован: 07.01.2017

сделал ошибку в коде, 
4 строчка правильная:
#define FFT_N             256

negavoid
Offline
Зарегистрирован: 09.07.2016

В общем-то, и 40 Гц для этого микрофона - это уже довольно удивительно.

https://www.google.com/search?q=частотная+характеристика+электретного+микрофона&newwindow=1&source=lnms&tbm=isch&sa=X

denysKo_O
Offline
Зарегистрирован: 07.01.2017

пробывал пускать синусоду через схему на лм258
сигнал навыходе синусоида со смещеним 0 на +2,5в
по сути тот же сигнал что и с микрофона
но все равно ниже 40 герцов не меряет

Волшебник
Offline
Зарегистрирован: 22.12.2016

Возможно две проблемы, первая - вы не правильно цифруете вход, нужно синхронное сэмплирование. Если просто аналогРеад в лупе то будет джиттер, и он как раз на низких частотах проявляется сильнее всего. Перепишите код для запуска АЦП от таймера 1 канал Б.

Тут пример для меги2560, вкладка АЦП. 

Вторая причина в самом коде БПФ, но до устранения проблемы 1 это подтвердить нельзя.

denysKo_O
Offline
Зарегистрирован: 07.01.2017

Спасибо, будем изучать
да, сейчас в кода аналогРеад

int sample = analogRead(MIC_PIN) - 511;//153

denysKo_O
Offline
Зарегистрирован: 07.01.2017

это актуально для встроенного ацп
а если буду использовать внешний ацп?

Волшебник
Offline
Зарегистрирован: 22.12.2016

denysKo_O пишет:

это актуально для встроенного ацп
а если буду использовать внешний ацп?

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

Мне вот пришли MCP3002/3202/3304, неплохие ацп-эшки, но пришлось напрягать мозги пока я смог их в синхрон загнать. А так ЕНОБ никак не мерялся. Даже SPI не вариант, эта шина тоже без синхронизации старт-стоп.

denysKo_O
Offline
Зарегистрирован: 07.01.2017

ну я использовал ads1115 и есть еще такой же в наличии, он і2с

просто в любом случаи нужно будет внешний ацп, встроенного от ардуино будет мало...

Волшебник
Offline
Зарегистрирован: 22.12.2016

denysKo_O пишет:

ну я использовал ads1115 и есть еще такой же в наличии, он і2с

просто в любом случаи нужно будет внешний ацп, встроенного от ардуино будет мало...

Мало для чего?

У меня сложилось впечатление, что у ардуино и других микро-цпу всё пропорционально грамотно подобрано. А именно АЦП->размер памяти->частота процессора. Там очень редко требуется другой АЦП - > тогда проц и считать не успевает, и округляет на 8-битах так что ацп-10 ему как раз. Тем более если ацп исползуется для БПФ

denysKo_O
Offline
Зарегистрирован: 07.01.2017

мало для точности, решил использовать внешний цпу, так как там больше бит, соответсвенно можно будет изерить с десятіми, и сотыми. нужно в дальнейшем мерить не только частоту(для частоты достаточно и и родного ацп), а мощность подаваемого сиграла, вот тут нужно будет несколько знаков после запятой,а встроенный АЦП такого не может позволить....

nik182
Offline
Зарегистрирован: 04.05.2015

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

denysKo_O
Offline
Зарегистрирован: 07.01.2017

ацп нужен для большей точности замера мощности сигнала
для частоты сигнала-можно и встроенный АЦП ардуино
тут я так понимаю на нано и на про мини не сделать
нужно брать полноценную 2560....