2025-01-27 04:12 PM - last edited on 2025-01-27 11:15 PM by Peter BENSCH
I don't know if libopencm3 code is allowed to post here but really isn't that different at all...
I am getting wrong frequencies trying to measure a sine wave of 1.5v amplitude through adc of stm32f411, when 82hz I am getting 7.81, 110hz = 23.44... but when I simulate an 82hz sine wave with the code below, I am getting satisfactory results:
for (int i = 0; i < BUFFER_SIZE; i++) {
adc_buffer[i] = (uint16_t)(2048 + 2047 * sinf(2 * PI * 82.41 * i / SAMPLE_RATE));
}
, I am really FFT noob and probably doing something very ***, anyway here is some important parts of my code:
#include "arm_math.h"
#include "arm_const_structs.h"
#include <stdint.h>
#include <stdlib.h>
#include <math.h>
#include <stdio.h>
#define SAMPLE_RATE 8000
#define BUFFER_SIZE 1024
uint16_t adc_buffer[BUFFER_SIZE];
float fft_input[BUFFER_SIZE * 2]; // Interleaved real and imaginary parts
float fft_output[BUFFER_SIZE];
void compute_fft(float *input, float *output, int buffer_size) {
arm_cfft_instance_f32 fft_instance;
if (arm_cfft_init_f32(&fft_instance, buffer_size) != ARM_MATH_SUCCESS) {
return;
}
arm_cfft_f32(&fft_instance, input, 0, 1);
arm_cmplx_mag_f32(input, output, buffer_size);
}
float find_fundamental_frequency(float *fft_output, int buffer_size) {
float max_value = 0.0f;
int max_index = 0;
for (int i = 1; i < buffer_size / 2; i++) {
if (fft_output[i] > max_value) {
max_value = fft_output[i];
max_index = i;
}
}
return (float)max_index * SAMPLE_RATE / buffer_size;
}
void capture_adc_data(uint16_t *buffer, int size) {
for (int i = 0; i < size; i++) {
adc_start_conversion_regular(ADC1);
while (!adc_eoc(ADC1));
buffer[i] = adc_read_regular(ADC1);
}
}
int main(void) {
rcc_clock_setup_pll(&rcc_hse_25mhz_3v3[RCC_CLOCK_3V3_84MHZ]);
adc_setup();
usart_setup();
char output_buffer[50];
while (1) {
capture_adc_data(adc_buffer, BUFFER_SIZE);
for (int i = 0; i < BUFFER_SIZE; i++) {
float sample = (float)adc_buffer[i] / 4096.0f - 0.5f;
fft_input[2 * i] = (float)adc_buffer[i] / 4096.0f - 0.5f;
fft_input[2 * i + 1] = 0.0f;
}
compute_fft(fft_input, fft_output, BUFFER_SIZE);
float fundamental_frequency = find_fundamental_frequency(fft_output, BUFFER_SIZE);
snprintf(output_buffer, sizeof(output_buffer), "Freq: %.2f Hz\r\n", fundamental_frequency);
usart_send_string(output_buffer);
}
return 0;
}
my raw adc values seem to be right what can could be happening?