【发布时间】:2016-01-19 16:12:29
【问题描述】:
我们目前与 Arduino 合作。
我正在使用“开放音乐实验室FFT库”的fft库
我的问题是两件事。
Arduino 代码问题
-
Matlab 中的反 fft(使用 Arduino 的 FFT 结果)
以下代码使用 Arduino FFT 库进行 FFT(快速傅里叶变换)
/* fft_adc_serial.pde guest openmusiclabs.com 7.7.14 example sketch for testing the fft library. it takes in data on ADC0 (Analog0) and processes them with the fft. the data is sent out over the serial port at 115.2kb. */ //#define LOG_OUT 1 // use the log output function #define FFT_N 256 // set to 256 point fft void setup() { Serial.begin(115200); // use the serial port TIMSK0 = 0; // turn off timer0 for lower jitter ADCSRA = 0xe5; // set the adc to free running mode ADMUX = 0x40; // use adc0 DIDR0 = 0x01; // turn off the digital input for adc0 } void loop() { while(1) { // reduces jitter cli(); // UDRE interrupt slows this way down on arduino1.0 for (int i = 0 ; i < 512 ; i += 2) { // save 256 samples while(!(ADCSRA & 0x10)); // wait for adc to be ready ADCSRA = 0xf5; // restart adc byte m = ADCL; // fetch adc data byte j = ADCH; int k = (j << 8) | m; // form into an int k -= 0x0200; // form into a signed int k <<= 6; // form into a 16b signed int fft_input[i] = k; // put real data into even bins fft_input[i+1] = 0; // set odd bins to 0 } fft_window(); // window the data for better frequency response for (int i = 0 ; i < 512 ; i += 2) { fft_input[i] = (fft_input[i] >> 8); fft_input[i+1] = -(fft_input[i+1] >> 8); } fft_reorder(); // reorder the data before doing the fft fft_run(); // process the data in the fft //fft_mag_log(); // take the output of the fft sei(); Serial.print("start"); for (byte i = 0 ; i < FFT_N ; i+=2) { if (! ((i>=20 && i<=40) || (i>=FFT_N-40 && i<=FFT_N-20))) { fft_input[i] = 0; fft_input[i+1] = 0; } Serial.println(fft_input[i]); // send out the data } } }
matlab串口通信代码
clear all
clc
arduino=serial('COM22','BaudRate',115200 );
fopen(arduino);
data = fread(arduino, 256);
ifft(data , 'symmetric');
fclose(arduino);
delete(instrfindall);
这个代码是一个实验。但它没有恢复。
在 Arduino 上执行 fft_run (),我想要 matlab 中的逆 fft。
有很多问题。
我想以某种方式问什么。
更新
我已根据SleuthEye's answer 进行了更改。但有一个问题。
-arduino 代码-
/*
fft_adc_serial.pde
guest openmusiclabs.com 7.7.14
example sketch for testing the fft library.
it takes in data on ADC0 (Analog0) and processes them
with the fft. the data is sent out over the serial
port at 115.2kb.
*/
//#define LOG_OUT 1 // use the log output function
#define FFT_N 256 // set to 256 point fft
#include <FFT.h> // include the library
void setup() {
Serial.begin(115200); // use the serial port
TIMSK0 = 0; // turn off timer0 for lower jitter
ADCSRA = 0xe5; // set the adc to free running mode
ADMUX = 0x40; // use adc0
DIDR0 = 0x01; // turn off the digital input for adc0
}
void loop() {
while(1) { // reduces jitter
cli(); // UDRE interrupt slows this way down on arduino1.0
for (int i = 0 ; i < 512 ; i += 2) { // save 256 samples
while(!(ADCSRA & 0x10)); // wait for adc to be ready
ADCSRA = 0xf5; // restart adc
byte m = ADCL; // fetch adc data
byte j = ADCH;
int k = (j << 8) | m; // form into an int
k -= 0x0200; // form into a signed int
k <<= 6; // form into a 16b signed int
fft_input[i] = k; // put real data into even bins
fft_input[i+1] = 0; // set odd bins to 0
}
fft_window(); // window the data for better frequency response
for (int i = 0 ; i < 512 ; i += 2) {
fft_input[i] = (fft_input[i] >> 8);
fft_input[i+1] = -(fft_input[i+1] >> 8);
}
fft_reorder(); // reorder the data before doing the fft
fft_run(); // process the data in the fft
// fft_mag_log(); // take the output of the fft
sei();
Serial.println("start");
for (byte i = 0 ; i < FFT_N ; i+=2) {
Serial.write(fft_input[i]); // send out the real part
Serial.write(fft_input[i+1]); // send out the imaginary part
}
}
}
-matlab 端-
clear all
clc
arduino=serial('COM22','BaudRate',115200 );
fopen(arduino);
header = fread(arduino, 5); % skip "start" header
data = fread(arduino, 512); % read actual data
% now rearrange the data
rearranged = data(1:2:end) + 1i * data(2:2:end);
recoverd = ifft(rearranged, 'symmetric');
fclose(arduino);
delete(instrfindall);
我的问题是:它删除了过滤器部分。
Arduino 将数据发送到 MATLAB。来自 Arduino 的 512 个数据。 (FFT_N- 实数 256 和虚数 256。)
不是完全恢复。在 matlab 中执行 ifft,而不是原始数据。
数据表单有问题。
这种形式的数据在交流中似乎有问题。(arduino to matlab)
data = fread(arduino, 512); % read actual data.
但我的猜测。没有找到确切的原因。
更新
感谢您的回复。
for (int i = 0 ; i < 512 ; i += 2) {
fft_input[i] = (fft_input[i] >> 8);
fft_input[i+1] = -(fft_input[i+1] >> 8);
}
这个代码已经发现不需要了。
for (byte i = 0 ; i < FFT_N ; i+=2) {
Serial.write(fft_input[i]); // send out the real part
Serial.write(fft_input[i+1]); // send out the imaginary part
}
我的困难是, 当您执行此代码时,OUTPUT 的部分是 256 REAL 和 256 IMAGINARY。
但是,
header = fread(arduino, 5); % skip "start" header
data = fread(arduino, 1024); % read actual data sent in binary form
% now rearrange the data
rearranged = (data(1:4:end) + 256*data(2:4:end)) + 1i *(data(3:4:end) + 256*data(4:4:end));
recovered = ifft(rearranged, 'symmetric');
"SIZE * PRECISION 必须小于或等于 InputBufferSize.."
缓冲区大小问题...
所以再试一次。 我不得不按照你说的修改代码。
/*
fft_adc_serial.pde
guest openmusiclabs.com 7.7.14
example sketch for testing the fft library.
it takes in data on ADC0 (Analog0) and processes them
with the fft. the data is sent out over the serial
port at 115.2kb.
*/
//#define LOG_OUT 1 // use the log output function
#define FFT_N 256 // set to 256 point fft
#include <FFT.h> // include the library
void setup() {
Serial.begin(115200); // use the serial port
TIMSK0 = 0; // turn off timer0 for lower jitter
ADCSRA = 0xe5; // set the adc to free running mode
ADMUX = 0x40; // use adc0
DIDR0 = 0x01; // turn off the digital input for adc0
}
void loop() {
while(1) { // reduces jitter
cli(); // UDRE interrupt slows this way down on arduino1.0
for (int i = 0 ; i < 512 ; i += 2) { // save 256 samples
while(!(ADCSRA & 0x10)); // wait for adc to be ready
ADCSRA = 0xf5; // restart adc
byte m = ADCL; // fetch adc data
byte j = ADCH;
int k = (j << 8) | m; // form into an int
k -= 0x0200; // form into a signed int
k <<= 6; // form into a 16b signed int
fft_input[i] = k; // put real data into even bins
fft_input[i+1] = 0; // set odd bins to 0
}
fft_window(); // window the data for better frequency respons
fft_reorder(); // reorder the data before doing the fft
fft_run(); // process the data in the fft
// fft_mag_log(); // take the output of the fft
sei();
Serial.println("start"); // header send
for (byte i = 0 ; i < FFT_N ; i+=2) {
Serial.write(fft_input[i]); // send out the real part
Serial.write(fft_input[i+1]); // send out the imaginary part
}
}
}
你的回答让我很忙。使活动。好答案。
【问题讨论】:
-
有什么问题?什么没有恢复?您必须更具体地了解您所面临的错误。我们不是千里眼,也不是读心术。
-
@rayryeng 虽然我很想拥有读心术的能力:D
-
@GameOfThrows 你和我都是我的朋友 ;)
-
更新版本使用
Serial.println("start")而不是Serial.print("start")作为标题(其中包括更多的行尾字节,您必须相应调整)。此外,循环滤除频率仓20-40是不可恢复的操作。您将无法获得完全相同的原始时间序列。我的回答确实存在一些问题,请参阅更新。 -
这是一个很好的答案。但是,也存在一些问题。我已经更新了我的问题。请查看