Преобразование Фурье(Проблема в понимании библиотеки)

m.daurtseff

✩✩✩✩✩✩✩
5 Апр 2020
3
1
Всем привет ! Проблема такая. Мы начали школьный проект который заключался в динамическом изменений цвета RGB светодиодов в зависимости от показаний ЭЭГ человека. Нам предоставили оборудование. Мы успешно запустили ЭЭГ и получили сырые графики. Обрабатывать конечно их нужно но я решил сначала разложить его на спектр чтобы выделить конкретные частоты (Альфа/Бета).Учусь я в 10 классе и в принципе физический и математический смысл преобразования Фурье я понял. Но вот проблема в том что программированием к сожалению я мало занимаюсь и конкретно сейчас не могу понять что выводит мне библиотека FFT (Позже я нашел уже библиотеку FHT). Суть такая:
Изучал я её работу на основе тестовой проги от AlexGyver(Анализатор аудио-спектра)

#define LOG_OUT 1 // use the log output function
#define FHT_N 256 // set to 256 point fht
#include <FHT.h>
#define MIC_PIN 0
double prevVolts = 100.0;

#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))

void setup() {
Serial.begin(9600);

sbi(ADCSRA, ADPS2);
cbi(ADCSRA, ADPS1);
sbi(ADCSRA, ADPS0);

analogReference(EXTERNAL);
}

void loop() {
for (int i = 0 ; i < FHT_N ; i++) {
int sample = analogRead(MIC_PIN);
fht_input = sample; // put real data into bins
}
fht_window(); // window the data for better frequency response
fht_reorder(); // reorder the data before doing the fht
fht_run(); // process the data in the fht
fht_mag_log(); // take the output of the fht

for (int curBin = 0; curBin < FHT_N / 2; ++curBin) {
Serial.print(fht_log_out[curBin]);
Serial.print(" ");
}
Serial.println("");
delay(500);
}
У меня конечно оно работало но я понял что частота, которая мне нужна лежит совсем в другом диапазоне.
#define FHT_N 256 // set to 256 point fht - Я так понимаю частота оцифровки раскладывается на 256 ячеек с определенным интервалом.

sbi(ADCSRA, ADPS2);
cbi(ADCSRA, ADPS1);
sbi(ADCSRA, ADPS0); - Увеличение частоты оцифровки

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

  • Можно ли уменьшить частоту оцифровки, т.к мне не нужен диапазон до 16000 кГц а идеально в интервале от 0 до 100 Гц ?
  • Как понять, какая частота оцифровки сейчас имеется чтобы разложить его в 256 ячеек и самое главное понять какой шаг имеет ?

 

Kir

★✩✩✩✩✩✩
28 Мар 2020
69
16
fht_input = sample; // put real data into bins
Это явно не правильная запись, индекс куда-то потерялся, должно быть так fht_input[i][I] = sample;[/I]

Частота семплирования у тебя вообще непонятно какая, но если прикинуть = 1/(время_работы АЦП + время выполнения кода в цикле). И не факт, что там 16кГц. Тебе нужно выполнять int sample = analogRead(MIC_PIN); с заданным периодом, самое тупое простое, что можно использовать для установки периода семплироания - delay(N_ms), но лучше что-нибудь поточнее, например аппаратный таймер. Частота семплирования выбирается = 2 * Частота Самой высокой гармоники в сигнале, подробнее ищи по запросу "Теорема Котельникова". Т.е. если у тебя сигнале самая высокая гармоника 100Гц, то достаточно взять частоту семплирования равную 200Гц. Таким образом период семплирования будет равен 5мс. Но тут есть важный момент. Нужно позаботиться о том чтобы гармоники выше 100Гц отсутствовали, т.е. нужен аналоговый фильтр HЧ, который порежет все что выше 100Гц, иначе будут проблемы, подробнее можешь почитать по запросу "Алиасинг при дискретизации сигналов".

Теперь про шкалу. У тебя в примере используется 256 отсчетов. На выходе полезных останется только 128 (поэтому в примере for (int curBin = 0; curBin < FHT_N / 2; ++curBin) ). Для сопоставления индекса массива с частотой гармоники: freq = индекс * частота семплироания/количество отсчетов. Для твоего примера freq = индекс * 200/256. Но для твоего случая можно выбрать частоту семплирования равную 256Гц, тогда индекс будет соответствовать частоте гармоники.
 

m.daurtseff

✩✩✩✩✩✩✩
5 Апр 2020
3
1
Этот скетч я взял с примеров библиотеки. На самом деле на Arduino поступает сигнал от Raspberry pi по UART протоколу, но это не важно. Спасибо большое за наводки.
 

Kir

★✩✩✩✩✩✩
28 Мар 2020
69
16
Этот скетч я взял с примеров библиотеки. На самом деле на Arduino поступает сигнал от Raspberry pi по UART протоколу, но это не важно. Спасибо большое за наводки.
Весьма странное решение с Raspberry pi отдавать расчет спектра в ардуино, я бы делал прямо на Raspberry pi.
 

m.daurtseff

✩✩✩✩✩✩✩
5 Апр 2020
3
1
Да но по заданию положено использовать именно Arduino. Ведь Raspberry pi они кривейшим образом модифицировали заблокировав функции записи. Концепция такая была, что это просто черный ящик, в который мы не лезем и который тупо отправляет данные.
 
  • Лойс +1
Реакции: technotrasher