cancel
Showing results for 
Search instead for 
Did you mean: 

FFT problem on stm32f4 discovery.

ameer
Associate II
Posted on August 29, 2015 at 19:08

Hi. I am facing strange problem implementing FFT on stm32f4 kit. i am using Virtual Com Port to transmit serial data which is plotted on QT (C++) platform.

The problem i am facing is that some time output is correct but most of the times wrong data is being plotted. Even when correct data is plotted still some wrong samples are

there to ruin theplot. Here is my code. Any help would be appreciated. Thanks in advance.

===== CODE =====

&sharpdefine FFT_SAMPLES 2048

&sharpdefine FFT_SIZE FFT_SAMPLES/2

&sharpdefine FFT_TIM_PRESCALE 420-1// 100 KH-z Clock

&sharpdefine FFT_TIM_PERIOD 10-1//100 KHz down to 10 Khz

&sharpdefine FFT_SAMPLE_FRQ ADC_SampleTime_15Cycles

&sharpdefine FFT_SAMPLE_DELAY ADC_TwoSamplingDelay_5Cycles

uint16_t fftAdc[FFT_SAMPLES/2];

float32_t fftInput[FFT_SAMPLES];

float32_t fftOutput[FFT_SIZE];

uint16_t fftInc=0;

uint16_t fftI=0;

double fftAdcValue;//after conversion -1 to +1

uint32_t fftMaxIndex;

float32_t fftMaxValue;

uint8_t fftFlag=0;

int main(void){

arm_cfft_radix4_instance_f32 FFT_InitStruc;

FFT_NVIC_ADC();

FFT_GPIO();

FFT_TIM2();

FFT_ADC();

status = arm_cfft_radix4_init_f32(&FFT_InitStruc,FFT_SIZE,0,1);

while(1){

if(fftFlag == 1){

fftFlag = 0;

arm_cfft_radix4_f32(&FFT_InitStruc,fftInput);

arm_cmplx_mag_f32(fftInput,fftOutput,FFT_SIZE);

arm_max_f32(fftOutput,FFT_SIZE,&fftMaxValue,&fftMaxIndex);

if(fftMaxIndex >= FFT_SIZE/2){

fftMaxIndex = FFT_SIZE - fftMaxIndex;

}

for(frInc=0;frInc<FFT_SIZE/2;frInc+=16){

sprintf(strPut,''♯%d+%.0f+%.0f+%.0f+%.0f+%.0f+%.0f+%.0f+%.0f+%.0f+%.0f+%.0f+%.0f+%.0f+%.0f+%.0f+%.0f+%d+%.0f+~'',frInc,fftOutput[frInc],fftOutput[frInc+1],

fftOutput[frInc+2],fftOutput[frInc+3],fftOutput[frInc+4],fftOutput[frInc+5],fftOutput[frInc+6],fftOutput[frInc+7],fftOutput[frInc+8],fftOutput[frInc+9],fftOutput[frInc+10],fftOutput[frInc+11],

fftOutput[frInc+12],fftOutput[frInc+13],fftOutput[frInc+14],fftOutput[frInc+15],fftMaxIndex,fftMaxValue);

TM_USB_VCP_Puts(strPut);

Delay(7000);

}

}

}

}

void FFT_GPIO(void){

GPIO_InitStruc.GPIO_Pin = GPIO_Pin_0;

GPIO_InitStruc.GPIO_Mode = GPIO_Mode_AN;

GPIO_InitStruc.GPIO_Speed = GPIO_Speed_100MHz;

GPIO_InitStruc.GPIO_PuPd = GPIO_PuPd_NOPULL;

GPIO_Init(GPIOA,&GPIO_InitStruc);

}

void FFT_NVIC_ADC(void){

NVIC_InitStruc.NVIC_IRQChannel = ADC_IRQn;

NVIC_InitStruc.NVIC_IRQChannelCmd = ENABLE;

NVIC_InitStruc.NVIC_IRQChannelPreemptionPriority = 0;

NVIC_InitStruc.NVIC_IRQChannelSubPriority = 0;

NVIC_Init(&NVIC_InitStruc);

}

void FFT_TIM2(void){

TIM_DeInit(TIM2);

TIM_TimeBaseStructInit(&TIM_TimeBaseInitStruc);

TIM_TimeBaseInitStruc.TIM_Period = FFT_TIM_PERIOD;

TIM_TimeBaseInitStruc.TIM_Prescaler = FFT_TIM_PRESCALE;

TIM_TimeBaseInitStruc.TIM_ClockDivision = 0;

TIM_TimeBaseInitStruc.TIM_CounterMode = TIM_CounterMode_Up;

TIM_TimeBaseInitStruc.TIM_RepetitionCounter = 0;

TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStruc);

TIM_SelectOutputTrigger(TIM2,TIM_TRGOSource_Update);

TIM_Cmd(TIM2,ENABLE);

}

void FFT_ADC(void){

DMA_DeInit(DMA2_Stream0);

DMA_InitStruc.DMA_Channel = DMA_Channel_0;

DMA_InitStruc.DMA_PeripheralBaseAddr = (uint32_t) &ADC1->DR;

DMA_InitStruc.DMA_Memory0BaseAddr = (uint32_t) &fftAdc[0];

DMA_InitStruc.DMA_DIR = DMA_DIR_PeripheralToMemory;

DMA_InitStruc.DMA_BufferSize = FFT_SIZE;

DMA_InitStruc.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

DMA_InitStruc.DMA_MemoryInc = DMA_MemoryInc_Enable;

DMA_InitStruc.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;

DMA_InitStruc.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;

DMA_InitStruc.DMA_Mode = DMA_Mode_Circular;

DMA_InitStruc.DMA_Priority = DMA_Priority_High;

DMA_InitStruc.DMA_FIFOMode = DMA_FIFOMode_Disable;

DMA_InitStruc.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;

DMA_InitStruc.DMA_MemoryBurst = DMA_MemoryBurst_Single;

DMA_InitStruc.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;

DMA_Init(DMA2_Stream0,&DMA_InitStruc);

DMA_Cmd(DMA2_Stream0,ENABLE);

ADC_DeInit();

ADC_CommonInitStruc.ADC_Mode = ADC_Mode_Independent;

ADC_CommonInitStruc.ADC_Prescaler = ADC_Prescaler_Div2;

ADC_CommonInitStruc.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;

ADC_CommonInitStruc.ADC_TwoSamplingDelay = FFT_SAMPLE_DELAY;

ADC_CommonInit(&ADC_CommonInitStruc);

ADC_InitStruc.ADC_Resolution = ADC_Resolution_12b;

ADC_InitStruc.ADC_ScanConvMode = DISABLE;

ADC_InitStruc.ADC_ContinuousConvMode = DISABLE;

ADC_InitStruc.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T2_TRGO;

ADC_InitStruc.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_Rising;

ADC_InitStruc.ADC_DataAlign = ADC_DataAlign_Right;

ADC_InitStruc.ADC_NbrOfConversion = 1;

ADC_Init(ADC1,&ADC_InitStruc);

ADC_RegularChannelConfig(ADC1,ADC_Channel_0,1,FFT_SAMPLE_FRQ);

ADC_DMARequestAfterLastTransferCmd(ADC1,ENABLE);

ADC_ITConfig(ADC1,ADC_IT_EOC,ENABLE);

ADC_DMACmd(ADC1,ENABLE);

ADC_Cmd(ADC1,ENABLE);

ADC_SoftwareStartConv(ADC1);

}

void ADC_IRQHandler(void){

float32_t *pData;

uint16_t *pConvertedValues;

ADC_ClearITPendingBit(ADC1,ADC_IT_EOC);{

if(fftFlag ==0){

fftFlag = 1;

pData = &(fftInput[0]);

pConvertedValues = & (fftAdc[0]);

for(fftI =0;fftI<FFT_SIZE;fftI++){

*pData = (float32_t) ((float32_t)*pConvertedValues - (float32_t) 2048) / (float32_t) 2048;

pData ++;

*pData = 0;

pData ++;

pConvertedValues ++;

}

}

}

}

#discovery #fft #stm32f4
6 REPLIES 6
Posted on August 29, 2015 at 21:30

Not sure the EOC method is going to work, are you trying to do an FFT at each sample?

Realistically if you're going to use DMA, and perform an FFT on the buffer you are going to need to double the buffer size, and interrupt on the HT (Half Transfer) and TC (Transfer Complete) and process the half of the buffer that's NOT be actively loaded behind the scenes. 

The FFT portion you might want to test by providing known data sets and confirming all is well there.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
ameer
Associate II
Posted on August 30, 2015 at 06:45

As u said, I performed the fft on test array (which was working on Matlab) but

the output bins are keep increasing. Could u plz point out mistake in my code.

From: clive1

Posted: Saturday, August 29, 2015 9:30 PM

Subject: FFT problem on stm32f4 discovery.

Not sure the EOC method is going to work, are you trying to do an FFT at each sample?

Realistically if you're going to use DMA, and perform an FFT on the buffer you are going to need to double the buffer size, and interrupt on the HT (Half Transfer) and TC (Transfer Complete) and process the half of the buffer that's NOT be actively loaded behind the scenes. 

The FFT portion you might want to test by providing known data sets and confirming all is well there.

ameer
Associate II
Posted on August 30, 2015 at 06:45

As u said, I performed the fft on test array (which was working on Matlab) but

the output bins are keep increasing. Could u plz point out mistake in my code.

From: clive1

Posted: Saturday, August 29, 2015 9:30 PM

Subject: FFT problem on stm32f4 discovery.

Not sure the EOC method is going to work, are you trying to do an FFT at each sample?

Realistically if you're going to use DMA, and perform an FFT on the buffer you are going to need to double the buffer size, and interrupt on the HT (Half Transfer) and TC (Transfer Complete) and process the half of the buffer that's NOT be actively loaded behind the scenes. 

The FFT portion you might want to test by providing known data sets and confirming all is well there.

ameer
Associate II
Posted on August 30, 2015 at 06:45

As u said, I performed the fft on test array (which was working on Matlab) but

the output bins are keep increasing. Could u plz point out mistake in my code.

From: clive1

Posted: Saturday, August 29, 2015 9:30 PM

Subject: FFT problem on stm32f4 discovery.

Not sure the EOC method is going to work, are you trying to do an FFT at each sample?

Realistically if you're going to use DMA, and perform an FFT on the buffer you are going to need to double the buffer size, and interrupt on the HT (Half Transfer) and TC (Transfer Complete) and process the half of the buffer that's NOT be actively loaded behind the scenes. 

The FFT portion you might want to test by providing known data sets and confirming all is well there.

ameer
Associate II
Posted on August 30, 2015 at 06:49

I have checked adc function separately its giving me the right conversions. But when i

performed fft on test array(tested on matlab) the output bins are keep increasing. Could 

u plz point out mistake in my code. Tanks

spochamreddy
Associate
Posted on February 09, 2016 at 16:33

Hi,

I am trying to Implement real time FFT Using STM32F4.

Regarding to DSP libraries  I am facing some Problems.

If you Solved your Issue; Can you help me in that.