arduino uno , FFT-спектральный анализатор .

gmaxi
Offline
Зарегистрирован: 02.04.2017

Добрый день .
Как реализовать вывод максимальных пиков частоты на промежутке от 20 до 120Гц , на lcd 16x02.
Сигнал будет подаваться на ацп .
Допустим играет музыка , раз максимальная амплитуда 77Гц потом второй пик 35Гц и так далее . Вот эти показания мне и надо в цифрах и выводить на lcd .

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Если Вы хотите сделать это сами, то, судя по названию темы, мыслите в верном направлении. Осталось только выложить скетч и схему.

Если же хотите, чтобы кто-то сделал за Вас, то ошиблись разделом.

gmaxi
Offline
Зарегистрирован: 02.04.2017

Может есть у кого библиотека fft ?

ulis
ulis аватар
Offline
Зарегистрирован: 09.03.2011

gmaxi пишет:

Может есть у кого библиотека fft ?

Библиотек по бпф для ардуино на просторах инете не мало .... другое дело, понять это и прикрутить конкретно к железу

gmaxi
Offline
Зарегистрирован: 02.04.2017

В том то и дело что понять проблематично , возможно кто то разжуёт .

ulis
ulis аватар
Offline
Зарегистрирован: 09.03.2011

gmaxi пишет:

В том то и дело что понять проблематично , возможно кто то разжуёт .

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

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

Logik
Offline
Зарегистрирован: 05.08.2014

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

Дето так (насколько помню оно работало когдато).

01#include <fix_fft.h>
02#define AUDIOPIN A2
03 
04char im[128], data[128];
05int i=0, val;
06int outlow = 0;
07int outmid = 0;
08int outhi = 0;
09 
10int redPin = 5;          // pins that the LED are attached to
11int greenPin = 6;
12int bluePin = 3;
13 
14void setup() {
15  Serial.begin(19200);
16}
17 
18void loop() {
19    for (i=0; i < 128; i++){
20      val = analogRead(AUDIOPIN);
21      delayMicroseconds(200);
22      data[i] = val/4 -128;
23      im[i] = 0;
24    }
25 
26    fix_fft(data,im,7,0);
27 
28 
29 
30  for (i=0; i<10;i++)
31  {
32          Serial.print((byte)(sqrt(data[i] * data[i]+im[i]*im[i])));
33      Serial.print("\t");
34 
35  }
36  Serial.println();
37 
38 }

ПС. Нафига оно вам нада, весна на улице, пивка лучше бахните.

ulis
ulis аватар
Offline
Зарегистрирован: 09.03.2011

Logik пишет:

ПС. Нафига оно вам нада, весна на улице, пивка лучше бахните.

ИДЕ ругается на библиотеку fft ... нет пока времени разбираться, нужно ардуин-метеостанцию доделать

Logik
Offline
Зарегистрирован: 05.08.2014

Наверно на её отсутствие ругается.

ulis
ulis аватар
Offline
Зарегистрирован: 09.03.2011

Logik пишет:

Наверно на её отсутствие ругается.

:) Ценю ваш юмор ...

C:\Users\ulis\Documents\Arduino\libraries\FFT/fix_fft.h:6:22: fatal error: WProgram.h: No such file or directory

Инет рекомендует WProgram.h заменить на Arduino.h ... не помогает, замена дает еще целый букет ошибок

Logik
Offline
Зарегистрирован: 05.08.2014

Открыл fix_fft.h, таки да WProgram.h инклудит. Но у меня не ругается с ИДЕ  1.0.6. Остерегайтесь слишком нового софта.

Вобще  первое чего бы я сделал - как раз и заменил на Arduino.h.... А чего пишет то? Либке там вобще мало что надо..

ulis
ulis аватар
Offline
Зарегистрирован: 09.03.2011

ИДЕ конечно у меня почти самая последняя - 1.8.1 Если WProgram.h заменить на Arduino.h - имеем:

In file included from C:\Users\ulis\Documents\Arduino\libraries\FFT\fix_fft.cpp:1:0:

C:\Users\ulis\Documents\Arduino\libraries\FFT\fix_fft.cpp: In function 'int fix_fft(char*, char*, int, int)':

C:\Users\ulis\Documents\Arduino\libraries\FFT\fix_fft.cpp:199:37: error: 'Sinewave' was not declared in this scope

            wr =  pgm_read_word_near(Sinewave + j+N_WAVE/4);

                                     ^

C:\Users\ulis\Documents\Arduino\libraries\FFT\fix_fft.cpp:209:37: error: 'Sinewave' was not declared in this scope

            wi = -pgm_read_word_near(Sinewave + j);

Logik
Offline
Зарегистрирован: 05.08.2014

хммм.. а Sinewave как

const prog_int8_t Sinewave[N_WAVE-N_WAVE/4] PROGMEM = {

либо мутный тип prog_int8_t  либо PROGMEM. Или указатель не может привести

Ну попробуйте

const uint8_t Sinewave[N_WAVE-N_WAVE/4] PROGMEM = {

или

const char Sinewave[N_WAVE-N_WAVE/4] PROGMEM = {

или без const (он итак  PROGMEM)

ulis
ulis аватар
Offline
Зарегистрирован: 09.03.2011

а ведь действительно, что за тип prog_int8_t, заменил на uint8_t, компиляция прошла без ошибок ... спасибо, буду дальше разбираться ....

gmaxi
Offline
Зарегистрирован: 02.04.2017

Поделитесь со мною чтоль библиотекой буду тоже мучать может совместными усилиями что нибудь и получиться .

Logik
Offline
Зарегистрирован: 05.08.2014

Та ненадо никого мучить. Я тот скетч заливал, палец к выводу подносил и наблюдал разложение пальца в спектр )) С гармониками кратными 50Гц. А дальше уже творите чего знаете, но помните что все совсем не так просто как кажется. Все не идеально и чтоб получить что хочется прийдется думать и одним БПФ как правило не обходится.

ulis
ulis аватар
Offline
Зарегистрирован: 09.03.2011

Logik пишет:

но помните что все совсем не так просто как кажется

Мы знаем, что жизнь не так проста :)

Собрал простейшую схемку:

На вход подал сигнал со звуковой карты ... получил такую "картину"

Осталось понять, ну а вывод на подходящий экранчик - дело техники

Logik
Offline
Зарегистрирован: 05.08.2014

ulis пишет:

Logik пишет:

но помните что все совсем не так просто как кажется

Мы знаем, что жизнь не так проста :)

Это Вам только кажется )) учитывая что сигнал со звуковой карты двуполярный, а вход АЦП  - нет, то вы очень многого не знаете ;)

ulis
ulis аватар
Offline
Зарегистрирован: 09.03.2011

Logik пишет:

Это Вам только кажется )) учитывая что сигнал со звуковой карты двуполярный, а вход АЦП  - нет, то вы очень многого не знаете ;)

:) Наверно, вы имеете в виду, что сигнал с карты имеет постоянную составляющую? Нет повода для волнения, все будет учтено в лучших традициях аналоговой техники

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

ulis пишет:

Logik пишет:

Это Вам только кажется )) учитывая что сигнал со звуковой карты двуполярный, а вход АЦП  - нет, то вы очень многого не знаете ;)

:) Наверно, вы имеете в виду, что сигнал с карты имеет постоянную составляющую? Нет повода для волнения, все будет учтено в лучших традициях аналоговой техники

откуда там постоянная составляющая? постоянный ток через конденсаторы не ходит жеж

ulis
ulis аватар
Offline
Зарегистрирован: 09.03.2011

Logik пишет:

учитывая что сигнал со звуковой карты двуполярный, а вход АЦП  - нет

Что вы имеете в виду? Относительно земли сигнал "гуляет" в плюс и минус или что-то еще? Мне никто не мешает податьсмещение на аналоговоый вход ардуины ... ладно, мне пора на горшок и спать :)

Logik
Offline
Зарегистрирован: 05.08.2014

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

ПС. кстати этот эффект уже виден в результатах, элемент 0 в выходном массиве БПФ - это постоянная составляющая, она есть! А поидее с выхода звуковухи ей быть недолжно.

ulis
ulis аватар
Offline
Зарегистрирован: 09.03.2011

Вот библиотека, которая работает у меня на иде 1.8.1 (это для gmaxi)

https://yadi.sk/d/Li0lnTwM3Ghcvn

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

Спасибо большое за код
все отлично, но есть пару вопросов, как с помощью вашего скетча  узнать текущую частоту?
как датчик переменного напряжения использую вот такую схему на ОУ http://redblot.ru/archives/406
у меня идет смещение нуля на 2,5 вольта, соответственно для анализа есть полная синусоида звука.
 

ulis
ulis аватар
Offline
Зарегистрирован: 09.03.2011

denysKo_O пишет:

Спасибо большое за код
все отлично, но есть пару вопросов, как с помощью вашего скетча  узнать текущую частоту?
как датчик переменного напряжения использую вот такую схему на ОУ http://redblot.ru/archives/406
у меня идет смещение нуля на 2,5 вольта, соответственно для анализа есть полная синусоида звука.
 

Т.е. я так понимаю, что вы на вход подаете не сложный сигнал, типа музычки, а чистую синусоиду?

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

да, для примера, вот 50 герц

ulis
ulis аватар
Offline
Зарегистрирован: 09.03.2011

Так тогда зачем вам вообще БПФ?

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

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

ulis
ulis аватар
Offline
Зарегистрирован: 09.03.2011

denysKo_O пишет:

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

В таком случае, я вообще не понял, что вы хотите и причем здесь ваше ПО

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

мне нужно узанть частоту синусоиды с помощью ардуино

а по-уже буду писать дальше)

ulis
ulis аватар
Offline
Зарегистрирован: 09.03.2011

Узнать частоту - множество вариантов, особенно, если частота не высока. Например, померить длительность периода и взять обратную величину, даже оцифровывать не нужно. Посмотрите, например: http://arduino.ru/forum/programmirovanie/kak-schityvat-chastotu-posredstvom-arduino

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

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

ulis
ulis аватар
Offline
Зарегистрирован: 09.03.2011

denysKo_O пишет:

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

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

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

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

ulis
ulis аватар
Offline
Зарегистрирован: 09.03.2011

Ставьте на вход аналоговый фильтр нижних частот нечетного порядка (3 или 5), с частотой среза 200 Гц и уж потом с помощью дуни получайте спектр. Конкретную реализацию БПФ для вашего случая пока не знаю как реализовать .... может кто подскажет

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

фильтрация частот будет происходить на самом УНЧ, а вот с FFT сейчас разбираюсь

Logik
Offline
Зарегистрирован: 05.08.2014

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

Самый первый элемент с индексом 0 показывает постоянную составляющую сигнала, то есть, насколько он в среднем "приподнят" над осью времени. Остальные элементы представляют гармоники видаA cos(2πνt + φ), где ν - это частота, которая для гармоники с индексом k будет равна:

ν = k / T

Часто бывает дано не суммарное время сигнала T, а частота дискретизации: сколько отсчетов приходится на одну секунду. Обозначим ее S. Тогда частота для гармоники с индексом k будет равна:

ν = S k / N

 

. Т.е. каждый коэффициент в результатах БПФ отвечает за наличие сигнала на некоторой частоте. Если входной сигнал дискретизирован с частотой 8000Гц и мы обработали по 128 отсчетам то первый коэффициент - уровень сигнала на частоте 8000*1/128, второй на частоте 8000*2/128 и т.д. Т.е. частоты уже получены, но...

Это очень важно понимать: FFT раскладывает функцию не на её гармоники, а насвои гармоники. Допустим, в исходной функции была лишь частота точно 100 Гц, а мы с помощью FFT раскладываем функцию в частоты 96, 99, 102, 105 Гц - как вы думаете, что получится в результате? :) ......... полученный нами спектральный состав будет бестолковым:

Удачный FFT Неудачный FFT
Частоты Коэффициенты
(амплитуда)
Частоты Коэффициенты
(амплитуда)
95 0 91 0.04
96 0 93 0.11
97 0 96 0.14
98 0 99 0.85
99 0 102 0.19
100 1 105 0.15
101 0 108 0.09
102 0 111 0.02
103 0 114 0.001

Как видно, удачный FFT, который полностью 'попал' в искомую частоту, дал хороший, правильный, с нашей точки зрения, спектр. Неудачный же - нехороший спектр. Мы можем только догадываться, что в исходном сигнале была сильная частота в примерно 100 Гц.

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

ПС. В сомнительной части, которую я не цитировал утверждалось о возможности восстановления по неудачному БПФ исходного сигнала. "полностью точно восстановить". Почему это сомнительно. Да потому что даже после дискретизации есть потеря информации и восстановление всего спектра невозможно, а по результатам БПФ еще и с конечной точностью - тем более. И хочется спросить, а что будет если на входе БПФ окажется не синус 100Гц, а сумма сигнала с частотами и амплитудами 91Гц и 0,04 + 93Гц и 0,11+ т.д. по таблице? Что восстановится из результатов разложения такого сигнала, 100Гц или сумма ;)? 

ulis
ulis аватар
Offline
Зарегистрирован: 09.03.2011

Спасибо, за инфу ... осталось только выяснить, согласно желанию ТС, как задать параметры бииблиотеки, чтобы она раскладывала в свой спектр в диапазоне до 200 Гц?

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

Спасибо за инфу
но все равно не очень ясно)
на выходе после FFT имею матрици, к примеру:
вот частотат 40 герц:
 

вот 20 герц:
 

 

Визуально видно как меняется показания, и можно "угадать" какая частота, но как програмно вычислить? 

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

https://www.arduino.cc/en/Tutorial/SimpleAudioFrequencyMeter
по топику еще, есть идеально подходящая мне библиотека, но она не работает с даной версией ардуно(
используется ардуино нано, с возмоностью подальшого переноса проэкта на stm32