我假设额外的频谱转换是有意的,而不是你发现的问题。例如,你不应该期望在20到40(包括20到40)个箱中取回频谱值,因为你明确地将它们归零。此外,代码
for (int i = 0 ; i < 512 ; i += 2) {
fft_input[i] = (fft_input[i] >> 8);
fft_input[i+1] = -(fft_input[i+1] >> 8);
}
是一个技巧
obtain the inverse transform using Arduino's forward transform
由于您从时间样本开始,我假设您只需要前向变换(因此不需要这部分代码)。
现在,与
Arduino's FFT example
,有一些差异可能暗示了发生了什么。第一个显著的差异来自示例发送的信号,即频谱幅度的下半部分(128个值),不足以重建原始信号。在您的案例中,您正确地注释了
fft_mag_log
这将允许您发送频谱的复杂值。然而,当您在fft箱上循环时,您只发送每秒钟一次的值(因此丢失了所有的虚部)。
另一个需要注意的是数据的包装。更具体地说,您发送的是一个数据头(“start”字符串),您必须在Matlab的接收端读取,否则它将与实际数据混合。
二进制传输
您正在使用
Serial.println
它以ASCII格式发送你的号码,而你用Matlab的
fread
假设它们是二进制形式的,它会读取它们。为了保持一致,您应该以二进制形式发送数据
Serial.write
:
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
}
然后,由于您要发送256个复数值作为交织的实/虚部分(总共512个值),您需要读取这512个数值(通常每个2字节,按小字节顺序),并在Matlab一侧重新排列数据:
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');
ASCII传输
或者,您可以使用
系列.println
(即纯ASCII格式):
for (byte i = 0 ; i < FFT_N ; i+=2) {
Serial.println(fft_input[i]); // send out the real part
Serial.println(fft_input[i+1]); // send out the imaginary part
}
并在matlab中以ASCII格式读回
fscanf
:
fscanf(arduino, "start"); % skip "start" header
data = fscanf(arduino, "%d"); % read actual data sent in plain ASCII form
% now rearrange the data
rearranged = data(1:2:end) + 1i * data(2:2:end);
recovered = ifft(rearranged, 'symmetric');