2025-03-25 5:35 PM
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);
}