Skip to main content
Visitor II
March 26, 2025
Question

FFT on Array outputting incorrect value.

  • March 26, 2025
  • 2 replies
  • 371 views

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);
}

 

    This topic has been closed for replies.

    2 replies

    Technical Moderator
    May 15, 2025

    Hello @mattsparksy 

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

    Super User
    May 15, 2025

    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?