目前,我正在尝试通过使用 STM32F411RE 板上的 CMSIS 包来实现一个程序来查找 3 个频率(xs = 30.1 kHz、ys = 28.3 kHz 和 zs = 25.9 kHz)。我无法让复数 FFT (CFFT) 和复数幅度正常工作。
根据频率箱,我生成一个包含这些频率的数组,以便我可以手动查找信号 xs、ys 和 zs 所在的索引箱。然后,我使用该索引查看 3 个 fft 结果(Xfft、Yfft、Zfft)以找到这些信号的结果,但它们不匹配。
我使用以下功能顺序:
DMA ADC 缓冲区: 将
ADC 输入更改为浮动 Xfft
CFFT_F32:
复数幅度HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef* hadc)
中的频率箱 :binfreqs
arm_cfft_f32(&arm_cfft_sR_f32_len1024, Xfft, 0, 0);
arm_cmplx_mag_f32(Xfft, Xdsp, fftLen);
// ADC Stuff done via DMA, working correctly
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_DMA_Init();
MX_ADC1_Init();
MX_USART2_UART_Init();
HAL_ADC_Start_DMA(&hadc1, adc_buffer, bufferLen); // adc_buffer needs to be an uint32_t
while (1)
{
/**
* Generate the frequencies
*/
for (int binfreqs = 0; binfreqs < fftLen; binfreqs++) // Generates the frequency bins to relate the amplitude to an actual value, rather than a bin frequency value
{
fftFreq[binfreqs] = binfreqs * binSize;
}
/*
* Find the amplitudes associated with the 3 emitter frequencies and store in an array for each axis. By default these arrays are generated with signal strength 0
* and with frequency index at 0: because of system limits these will indicate invalid values, as system range is from 10 - 60 kHz.
*/
volatile int32_t X_mag[3][4] = // x axis values: [index][frequency][signal_strength][phase]
{
{0, Xfreq, 0, 0}, // For x-freq index [0][0], frequency [0][1] associated with 1st biggest amplitude [0][2], phase [0][3]
{0, Yfreq, 0, 0}, // Ditto for y-freq
{0, Zfreq, 0, 0} // Ditto for z-freq
};
/*
* Finds the index in fftFreq corresponding to respectively X, Y and Z emitter frequencies
*/
for(int binSearch = 0; binSearch < fftLen; binSearch++)
{
if(fftFreq[binSearch] == Xfreq) // Find index for X emitter frequency
{
X_mag[0][0] = binSearch;
}
if(fftFreq[binSearch] == Yfreq) // Find index for Y emitter frequency
{
X_mag[1][0] = binSearch;
}
if(fftFreq[binSearch] == Zfreq) // Find index for Z emitter frequency
{
X_mag[2][0] = binSearch;
}
}
信号处理
/* Signal processing algorithms --------------------------------------------------
*
* Only to be run once with fresh data from the buffer, [do not run continuous] or position / orientation data will be repeated.
* So only run once when conversionPaused
*/
if(conversionPaused)
{
/*
* Convert signal to voltage (12-bit, 4096)
*/
for (int floatVals = 0; floatVals < fftLen; floatVals++)
{
Xfft[floatVals] = (float) Xin[floatVals]; * 3.6 / 4096
}
/*
* Fourier transform
*/
arm_cfft_f32(&arm_cfft_sR_f32_len1024, Xfft, 0, 0); // Calculate complex fourier transform of x time signal, processing occurs in place
for (int fix_fft = 0 ; fix_fft < half_fftLen ; fix_fft++)
{
Xfft[fix_fft] = 2 * Xfft[fix_fft] / fftLen;
Xfft[fix_fft + half_fftLen] = 0;
}
/*
* Amplitude calculation
*/
arm_cmplx_mag_f32(Xfft, Xdsp, fftLen); // Calculate the magnitude of the fourier transform for x axis
/*
* Finds all signal strengths for allocated frequency indexes
*/
for(int strength_index = 0; strength_index < 3; strength_index++) // Loops through xyz frequencies for all 3 magnetometer axis
{
int x_temp_index = X_mag[strength_index][0]; // temp int necessary to store the strength, otherwise infinite loop?
X_mag[strength_index][2] = Xfft[x_temp_index]; // = Xfft[2*x_temp_index];
}
conversionPaused = 0;
}
} // While() end
} // Main() end
我不知道如何计算 cfft 和复数幅度的这种组合的频率区间,因为我希望数组的偶数索引保存实际值,而数组的奇数索引保存虚相位值。我引用了一些1 2 3 个示例,但无法弄清楚我的代码做错了什么。
然而,根据图像,当应用 30.1 kHz 的输入信号时,301 bin 索引或 602 bin 索引都不会保持预期的相应输出?
编辑:
此后,我尝试实现此处给出的 arm_cfft_f32 示例。后一个示例完全被破坏了,因为默认情况下不再包含外部 10 kHz 数据集,并且尝试包含它是不可能的,因为程序的行为很差,并且一直在错误地返回甚至根本不存在的返回数据类型。因此我不能使用为此给出的示例程序:它似乎也已经过时了 4 年,所以这并不奇怪。
arm_max_f32() 函数也被证明没有成效,因为它通过使用模拟生成的信号不断追踪在 bin 0 处生成的噪声。手动将此 bin 0 设置为等于 0 会扰乱算法,该算法开始指向随机值,这些随机值甚至不是系统中存在的最大值。
即使手动查看 CFFT 数据和幅度,它们似乎也无法正常工作。整个频谱部分都有随机噪声值,而示波器确认大结果应该只出现在 0 Hz 和所选信号发生器频率(因此对应于频率仓)。
使用 CMSIS 对我来说非常令人沮丧,因为可用的文档和示例很少,然后由于其中大部分根本无法正常工作(没有重大修改)而进一步减少。