Я пытаюсь получить частоты аудиосигнала, используя библиотеку FFT, доступную для PIC32MZ2064DAB176.
Я использую для настройки MPLAB Harmony.
Для тестирования,используются две синусоидальные волны с частотами 1002 Гц и 750 Гц.Это делается с помощью онлайн-генератора тона.У меня 1002 Гц в одном окне браузера и 750 Гц в другом окне браузера.Выход с аудиоразъема O / P подается на АЦП микроконтроллера после смещения постоянного тока.
После выполнения смещения постоянного тока 1,6 В сигнал отправляется на 12-разрядный АЦП.Максимальное напряжение, которое я ожидаю, составляет 3 В PP, поэтому я предполагаю, что смещения постоянного тока будет 1,6 В.
Сигналы дискретизируются с частотой 48 кГц, поскольку мне нужно будет считывать частоты до 20 кГц.
БПФ - это БПФ с 1024 точками.
Я могу получить значение постоянного тока в 0-м индексе частотного бина.
Формула, используемая для получения значения частоты из ячейки: Frequency = index * Частота выборки / Количество точек FFT
Однако я получаю высокую величину всегда в 1-й и2-ые ячейки частоты для любого значения входной частоты.Насколько я понимаю, для 1002 Гц амплитуда должна быть высокой около 21-го индекса частотного бина, а для сигнала 750 Гц амплитуда должна быть высокой около 16-го индекса.
Я прилагаю свой код, снимок экрана конфигурации ADC Harmony, снимок экрана результата и снимок входного сигнала.
В коде массив, используемый для частотного бина, - это "singleSidedFFT"
Любая помощь в получении правильной частотызначение высоко ценится.
/* FFT */
#define N 1024// Also change the log2N variable below!!
#define SAMPLE_FREQ 48000
#define PI 3.14
// Section: Global Data Definitions
APP_DATA appData;
/* ADC */
long count = 0;
/* FFT */
int16c fftCoefs[N];
int16c *fftc;
int log2N = 10;
extern const int16c twiddleFactors[];
long int freqVector[N];
int16c sampleBuffer[N]; //initialize buffer to collect samples
long int singleSidedFFT[N];
void APP_Tasks ( void )
{
/* Check the application's current state. */
switch ( appData.state )
{
/* Application's initial state. */
case APP_STATE_INIT:
{
bool appInitialized = true;
if (appInitialized)
{
int i;
fftc = &fftCoefs; /* Stores the twiddle factors */
// zero the freqVector and singleSidedFFT
for (i=0; i<N; i++)
{
freqVector = 0;
singleSidedFFT = 0;
sampleBuffer.re = 0;
}
// generate frequency vector this is the x-axis of your single sided fft
for (i=0; i<N; i++)
{
freqVector = i*(SAMPLE_FREQ/2)/((N/2) - 1);
}
/* Calculate the twiddle factors */
DSP_TransformFFT16_setup(fftc, log2N);
appData.state = APP_STATE_SERVICE_TASKS;
}
break;
}
case APP_STATE_SERVICE_TASKS:
{
/* Trigger a conversion */
ADCCON3bits.GSWTRG = 1;
/* Wait the conversions to complete */
while (ADCDSTAT1bits.ARDY2 == 0);
if (count < N)
{
sampleBuffer[count].re = ADCDATA2; /* fetch the result */
sampleBuffer[count].im = 0;
count++;
}
else
{
appData.state = APP_STATE_COMPUTE_FREQ;
count = 0;
}
break;
}
case APP_STATE_COMPUTE_FREQ:
{
APP_ComputeFreq();
appData.state = APP_STATE_SERVICE_TASKS;
break;
}
}
}
void APP_ComputeFreq(void)
{
int i;
int16c dout[N]; //holds computed FFT
int16c scratch[N];
// load complex input data into din
DSP_TransformFFT16(dout, sampleBuffer, fftc, scratch, log2N);
// compute single sided fft
for(i = 0; i < N/2; i++)
{
singleSidedFFT = sqrt((dout.re*dout.re) + (dout.im*dout.im));
}
LATAbits.LATA6 = ~LATAbits.LATA6;
}
Я также попытался написать отдельную функцию FFT ,.Результат тот же.Вот оно ..
void APP_ComputeFreq_2(void)
{
int16_t k, t;
for (k = 0; k < N; k++)
{
// For each output element
int16_t sumreal = 0;
int16_t sumimag = 0;
for (t = 0; t < N; t++)
{
// For each input element
double angle = 2 * M_PI * t * k / N;
sumreal += sampleBuffer[t].re * cos(angle) + sampleBuffer[t].im * sin(angle);
sumimag += -sampleBuffer[t].re * sin(angle) + sampleBuffer[t].im * cos(angle);
}
singleSidedFFT[k] = sqrt((sumreal * sumreal) + (sumimag * sumimag));
}
}
Конфигурация АЦП MPLAB Harmony
Корзина частоты АЦП
Входной сигнал
Большое спасибо.