Hi & thanks in advance for your patience. I am trying to get arm_rfft running on a Pi Pico. My basic problem is that I have a working sketch, but when I paste the code into my larger application - it fails. First observation is that this FFT is wicked fast, outputting results in 800 uS for a 512 sample size at 500,000 samples/sec (1mS of real time). Which means that the FFT is faster than the Pico can acquire data, potentially opens the opportunity to process ultrasonic (20kHz-100kHz) in real time. I am limited to troubleshooting using Serial.print statements. Also limited coding abilities.
Below is a comparison of the results of the two sketches, the first one shows proper operation, the second illustrates the characteristics of the failure:
Index Bin pResult Freq Mag Time
0 51 7935 49806.6 7935.0 1024 (all remaining are identical)
Index Bin pResult Freq Mag Time
0 0 4678 0.0 4678.0 148
1 0 1974 0.0 1974.0 144
2 0 8247 0.0 8247.0 143
3 0 12939 0.0 12939.0 147
4 0 15130 0.0 15130.0 147
5 0 14412 0.0 14412.0 143
6 0 10918 0.0 10918.0 158
7 0 5323 0.0 5323.0 146
8 0 1292 0.0 1292.0 143
9 0 7663 0.0 7663.0 150
10 0 12556 0.0 12556.0 146
11 0 15032 0.0 15032.0 143
12 0 14611 0.0 14611.0 149
13 0 11371 0.0 11371.0 147
14 0 5943 0.0 5943.0 142
15 0 627 0.0 627.0 158
Max Mag 627
I see hints; first, all bin number are zero, which seems to hint that only noise is being detected, second, the time is much quicker indicating that the input data array includes a lot of “0” data. I have printed the input buffer before arm_rfft is executed and the data in both sketches is identical. Lastly; not all bins are identical, which indicates to me that there is data in the input buffer, just invalid data.
My theory is that something is stomping on the input buffer - but how can I isolate the culprit?
Working sketch appears below.
Preferences:https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json
Compiler:”“Standard” and “Fast” (20% faster)
Board: Pi Pico 2040, Pico 2 fails to execute in both cases
Code size working sketch: Sketch uses 139684 bytes (6%) of program storage space. Maximum is 2093056 bytes.
Global variables use 29712 bytes (11%) of dynamic memory, leaving 232432 bytes for local variables. Maximum is 262144 bytes.
Code size failed sketch: Sketch uses 81672 bytes (3%) of program storage space. Maximum is 2093056 bytes.
Global variables use 46912 bytes (17%) of dynamic memory, leaving 215232 bytes for local variables. Maximum is 262144 bytes.
Working sketch:
#include <arm_math.h> // Include the CMSIS-DSP library header
int16_t adcBuffer[8192]; // adc data
uint32_t fftStartTime;
uint32_t fftCalcTime;
arm_rfft_instance_q15 rfft;// RFFT instance
void setup() {
Serial.begin(115200); // arduino ide
delay(3000);
arm_status status = arm_rfft_init_q15(&rfft, 512, 0, 1);// 0=fft,1=no bit rev
}
void loop() {
for(int i=0; i<8192;i++) adcBuffer[i] = 2000*sin(float(i)*50/80.) + 2048; // 50kHz
generateSpectrogram();
delay(5000);
}
q15_t fftInput[512]; // q15, 1.15 format, convert <<4 q15 result
q15_t fftOutput[1024]; // q15, 9.7 format, convert >>17 int16 result
q15_t fftPower[256]; // Buffer for magnitude results
int16_t maxMag; // spectrogram->max mag among all slices
float fftSliceFreq[16]; //
float fftSliceMag[16]; //
char TAB = 9;
// ---------------------------- fft ----------------------------------------------
void generateFFT(int slicePtr) {
maxMag = 0;
q15_t pResult; // signal magnitude, does not matter if q15 or no "<<4"
uint32_t pIndex; // bin number, doc says "q15_t*" but behaves like uint32_t
float peakFreq;
fftStartTime = micros(); // 512 samples
for (int i=0; i<512; i++) {
fftInput[i]=((adcBuffer[i+slicePtr*512]-2048)<<4); // xform->q15, remove dc
}
arm_rfft_q15(&rfft, fftInput, fftOutput);
arm_cmplx_mag_q15(fftOutput, fftPower, 256); // output is real/imaginary pairs), calculate magnitude
arm_max_q15(fftPower, 256, &pResult, &pIndex); // Find the peak magnitude and its index (bin number)
fftSliceFreq[slicePtr] = float(pIndex*976.6); // save peak freq for this slice
fftSliceMag[slicePtr] = float(pResult); // save peak signal magnitude
if(pResult>maxMag) maxMag = pResult;
fftCalcTime = micros() - fftStartTime;
Serial.print(slicePtr); // index
Serial.print(TAB);
Serial.print(pIndex); // bin
Serial.print(TAB);
Serial.print(pResult); // mag
Serial.print(TAB);
Serial.print(fftSliceFreq[slicePtr],1); // freq
Serial.print(TAB);
Serial.print(fftSliceMag[slicePtr],1); // mag
Serial.print(TAB);
Serial.print(fftCalcTime); // time
Serial.println();
}
// ------------------------ Spectrogram ---------------------------------------
// slice adc buffer into 1ms/slice, fft each slice, output to array
void generateSpectrogram() {
Serial.println("Index Bin pResult Freq Mag Time");
for(int slicePtr=0; slicePtr<16; slicePtr++) { // perform fft on 512 samples window (1 mS) 16 times
generateFFT(slicePtr); // 512 slice * 16 slices = 8192 whole buffer
}
Serial.print("Max Mag ");
Serial.println(maxMag);
}