cancel
Showing results for 
Search instead for 
Did you mean: 

FFT on Array outputting incorrect value.

mattsparksy
Associate

Hi there, I'm attempting to run an FFT on a sine wave input with frequencies from 0.1-1Hz however i seem to be getting incorrect frequencies from my FFT. Any help would be appreciated. 

 

#include "main.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include <stdio.h> #include <string.h> #include "arm_math.h" /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ /* USER CODE BEGIN PTD */ /* USER CODE END PTD */ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ #define SAMPLE_RATE 200 // Adjust the sample rate (samples per second) #define DURATION 12 // Duration in seconds #define TOTAL_SAMPLES (SAMPLE_RATE * DURATION) #define FFT_SIZE 1024 // Define FFT size (must be a power of 2) /* USER CODE END PD */ /* Private macro -------------------------------------------------------------*/ /* USER CODE BEGIN PM */ /* USER CODE END PM */ /* Private variables ---------------------------------------------------------*/ ADC_HandleTypeDef hadc1; UART_HandleTypeDef huart2; /* USER CODE BEGIN PV */ uint16_t lux =0; char msg[20]; uint32_t lux_values[TOTAL_SAMPLES]; float32_t fft_input[FFT_SIZE * 2]; float32_t fft_output[FFT_SIZE]; /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_ADC1_Init(void); static void MX_USART2_UART_Init(void); /* USER CODE BEGIN PFP */ void PerformFFT(void); /* USER CODE END PFP */ /* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ /** * @brief The application entry point. * @retval int */ int main(void) { /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ /* MCU Configuration--------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* USER CODE BEGIN Init */ /* USER CODE END Init */ /* Configure the system clock */ SystemClock_Config(); /* USER CODE BEGIN SysInit */ /* USER CODE END SysInit */ /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_ADC1_Init(); MX_USART2_UART_Init(); /* USER CODE BEGIN 2 */ char buffer[64]; uint32_t start_time = HAL_GetTick(); uint32_t index = 0; /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while ((HAL_GetTick() - start_time) < (DURATION * 1000) && index < TOTAL_SAMPLES) { HAL_ADC_Start(&hadc1); HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY); lux_values[index] = HAL_ADC_GetValue(&hadc1); snprintf(buffer, sizeof(buffer), "Light Intensity: %lu\r\n", lux_values[index]); HAL_UART_Transmit(&huart2, (uint8_t*)buffer, strlen(buffer), HAL_MAX_DELAY); index++; HAL_Delay(1000 / SAMPLE_RATE); } snprintf(buffer, sizeof(buffer), "Data collection done. Performing FFT...\r\n"); HAL_UART_Transmit(&huart2, (uint8_t*)buffer, strlen(buffer), HAL_MAX_DELAY); PerformFFT(); while (1) {} } /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ void PerformFFT(void) { arm_rfft_fast_instance_f32 fft_instance; arm_rfft_fast_init_f32(&fft_instance, FFT_SIZE); for (uint32_t i = 0; i < FFT_SIZE; i++) { fft_input[i] = (i < TOTAL_SAMPLES) ? (float32_t)lux_values[i] : 0.0f; } arm_rfft_fast_f32(&fft_instance, fft_input, fft_output, 0); float32_t magnitudes[FFT_SIZE / 2]; for (uint32_t i = 0; i < FFT_SIZE / 2; i++) { float32_t real = fft_output[2 * i]; float32_t imag = fft_output[2 * i + 1]; magnitudes[i] = sqrtf(real * real + imag * imag); } float32_t max_value = 0; uint32_t max_index = 1; // Start from 1 to avoid DC component for (uint32_t i = 1; i < (FFT_SIZE / 2); i++) { if (magnitudes[i] > max_value) { max_value = magnitudes[i]; max_index = i; } } float32_t bin_resolution = (float32_t)SAMPLE_RATE / (float32_t)FFT_SIZE; float32_t dominant_frequency = max_index * bin_resolution; char buffer[64]; snprintf(buffer, sizeof(buffer), "Dominant Frequency: %.2f Hz\r\n", dominant_frequency); HAL_UART_Transmit(&huart2, (uint8_t*)buffer, strlen(buffer), HAL_MAX_DELAY); }
View more

 

2 REPLIES 2
Saket_Om
ST Employee

Hello @mattsparksy 

Did you try to use the CMSIS DSP library to perform FFT on the buffered data?

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.
Saket_Om

The posted code does two things:

  1. Gets data from ADC
  2. Does FFT on that

How are you sure that the first part is actually giving good data for input to your FFT?

EDIT: Or, to put it another another way, have you tested your FFT on other, known-good data?

Or tried putting your ADC data through a different, known-good FFT?

 


@mattsparksy wrote:

i seem to be getting incorrect frequencies from my FFT. Any help would be appreciated. 


So what results are you getting ?

Have you tried any other standard FFT implementations - eg, as @Saket_Om suggested?

 

A complex system that works is invariably found to have evolved from a simple system that worked.
A complex system designed from scratch never works and cannot be patched up to make it work.