Using Fourier analysis signal on STM32 microcontroller

For the knowledge of Fourier transform, you can read my previous article: Fourier transform record , which records the meaning of some parameters and uses python and matlab for Fourier analysis and some processes of extracting signals. I hope it can help readers Generate a little help.

The following record uses stm32 to analyze the signal. This generally refers to some signals sampled by adc. On the one hand, the analysis of the signal is to obtain some components of the signal, and on the other hand, it is possible to contain many causes in the signal. Through analysis, we can analyze the signal. Noise is processed.

Note :This article uses the MCU as stm32f103RCT6, and may consider using the F4 platform for testing in the future. For the time being, only F1 is tested here. I believe that if there is no problem with F1, the effect of F4 should be better.

1. Import analysis tools

Before writing this article, I also referred to some articles. Here I will post the post of the boss first. For F1, I need to import some math libraries.

https://blog.csdn.net/weixin_43368814/article/details/103552114
https://shequ.stmicroelectronics.cn/thread-632949-1-1.html
https://blog.csdn.net/Simon223/article/details/105728567

There are currently two solutions here, but their test methods seem to be basically the same. Let’s learn from each other. It should be hhh. The first one is to directly import the required libraries, which are the following files, and import them into the path of keil. The following
insert image description here
is to import the .s file
insert image description here
and the following is to import the .h file
insert image description here

The following is the second solution, which is basically the same. I personally recommend the second solution

In the location where the hal library is installed. It is the location where the package of the library is downloaded, there is the following directory, just find this directory, find the following lib file, copy it out and
insert image description here
then enter the following directory, find the following 3 .h files and copy them out in the same
insert image description here
way Copy the two files together to our project directory,
insert image description here
add the lib file in the project directory,
insert image description here
and add it to our compilation macro parameters

,ARM_MATH_CM3,__CC_ARM,ARM_MATH_MATRIX_CHECK,ARM_MATH_ROUNDING

Add the compiled macro parameters and add the file path just copied to our directory.
insert image description here

2. Signal generation and viewing

First use the analysis tool we mentioned to see what the signal looks like. The function to generate the signal is as follows, which is still the superposition of three sine functions. Here, the sampling rate is set to 100khz, which is more realistic. The data is sent out through the serial port, and we use matlab to analyze the captured data.

#define Fs 100000

void InitBufInArray(void)
{
    
    
  unsigned short i;
  float fx;
  for(i = 0; i < FFT_LENGTH; i++)
  {
    
    
    fx = 15 * sin(PI * 2 * i * 13500.0 / Fs) +
         27 * sin(PI * 2 * i * 45000.0 / Fs) +
         40 * sin(PI * 2 * i * 8500.0 / Fs);
//    lBufInArray[i] = ((signed short)fx) << 16;
    printf("%f\n", fx);
  }
}

Use matlab to collect the data, you can see that the superimposed data is still very messy, here basically can not see the characteristics of the original data, it is a very messy signal, but directly use matlab to analyze it by three The group signal consists of three distinct spikes below.
insert image description here
Here, let’s zoom in on the intercepted just now. The standard value of this part should be 8500, 40, which is very close. This error will definitely exist, because the single-chip computer must perform approximation for the sin calculation, etc., and the calculation itself will exist. error.
insert image description here

3. Use STM32 to read data

1. Use the first library

The following uses stm32 for analysis. Here it needs to be explained that using stm32 for analysis must be discrete analysis, which is to analyze a segment of the signal, so if it corresponds to our actual sampling, it is actually sampling a segment of the signal to analyze a segment of the signal.

First of all, we need to build the array we need to analyze. The source code is as follows. Let’s introduce it below.

#define Fs 100000
#define FFT_LENGTH 1024
int32_t lBufInArray[FFT_LENGTH] = {
    
    0};
uint16_t ADC_Value[FFT_LENGTH] = {
    
    0};
int32_t lBufOutArray[FFT_LENGTH / 2] = {
    
    0};
int32_t lBufMagArray[FFT_LENGTH / 2] = {
    
    0};

void InitBufInArray(void)
{
    
    
  unsigned short i;
  float fx;
  for(i = 0; i < FFT_LENGTH; i++)
  {
    
    
    fx = 1024*sin(2*PI*i * 13500.0 / Fs)
		+512*sin(2*PI*i * 8500.0 / Fs)
		+512*sin(2*PI*i * 3500.0 / Fs);
		ADC_Value[i] = fx+2048;
    lBufInArray[i] = ((signed short)ADC_Value[i]) << 16;
//		printf("%d\n", ADC_Value[i]);
  }
}

Here, in order to adapt to the acquisition method of stm32, the generated sequence is converted into an integer format of 0-4096,This process will definitely cause a loss of precision, so the subsequent results should become inaccurate. Pay attention here, but there is no need to worry about the actual real sampling.
insert image description here
Here, according to the conversion function, the sampling data needs to be processed. For 32-bit shaping data, the upper 16 bits are placed in the real part, and the lower 16 bits are placed in the imaginary part. The imaginary part is generally 0, so it will not be processed.
insert image description here
In this way, the following function can be used to calculate, and the sequence of FFT can be generated

	InitBufInArray();
	cr4_fft_1024_stm32(lBufOutArray, lBufInArray, FFT_LENGTH);

But this result is not what we want in the end. The final result still needs to be optimized. Here is to extract its harmonic amplitude.

void GetPowerMag(void)
{
    
    
  signed short lX, lY;
  float X, Y, Mag;
  unsigned short i;
  for(i = 0; i < FFT_LENGTH / 2; i++)
  {
    
    
    lX  = (lBufOutArray[i] << 16) >> 16;
    lY  = (lBufOutArray[i] >> 16);
    X = FFT_LENGTH * ((float)lX) / 32768;
    Y = FFT_LENGTH * ((float)lY) / 32768;
    Mag = sqrt(X * X + Y * Y) / FFT_LENGTH;
    if(i == 0)
      lBufMagArray[i] = (unsigned long)(Mag * 32768);
    else
      lBufMagArray[i] = (unsigned long)(Mag * 65536);
  }
}

Finally, just add this function, and add the result printing function.
insert image description here
The source code is as follows

void FFT(void)
{
    
    
	InitBufInArray();
	cr4_fft_1024_stm32(lBufOutArray, lBufInArray, FFT_LENGTH);
	GetPowerMag();	                      
  for(int16_t i = 1; i < FFT_LENGTH/2; i++)
  {
    
    
    printf("%d\n",lBufMagArray[i]);
  }
}

Download the program to the development board, and the final result is as follows. Whether the result is accurate or not, it is better to use matlab to conduct a comparison test to find out.
insert image description here
Here we first put this data into matlab to check it,
insert image description here
and then import the data we generated into matlab for analysis. You can see the results as follows, which are relatively accurate. The error here is caused by the above forced conversion.
insert image description here

2. Use the second library

The second is the fft function that comes with arm, the function isarm_cfft_f32, the first thing to pay attention to here is the data position of one of its real and imaginary parts. There has been a change here. It is no longer the data stored in the upper 16 bits and lower 16 bits. Instead, it exists at intervals in the array buffer, as follows As shown in the figure:
insert image description here
The following is an introduction to the entire process. First, the required sampling data is generated.
insert image description here
The following is the part of Fourier analysis.
insert image description here

The end result looks like this:
insert image description here
Full code:

#include "fft_test.h"

#include "arm_math.h"
#include "arm_const_structs.h"
#include "stdio.h"


#define Fs 100000
#define FFT_LENGTH 1024

float32_t lBufInArray[FFT_LENGTH*2] = {
    
    0};
float32_t lBufOutArray[FFT_LENGTH / 2] = {
    
    0};
uint16_t ADC_Value[FFT_LENGTH] = {
    
    0};

void InitBufInArray(void)
{
    
    
  unsigned short i;
  float fx;
  for(i = 0; i < FFT_LENGTH; i++)
  {
    
    
    fx = 1024 * sin(2 * PI * i * 13500.0 / Fs)
         + 512 * sin(2 * PI * i * 8500.0 / Fs)
         + 512 * sin(2 * PI * i * 3500.0 / Fs);

    ADC_Value[i] = fx + 2048;
  }
}

void FFT(void)
{
    
    
  InitBufInArray();
  for (int i = 0; i < FFT_LENGTH; i++)
  {
    
    
    lBufInArray[i * 2] = ADC_Value[i]; //实部赋值
    lBufInArray[i * 2 + 1] = 0; //虚部赋值
  }
  arm_cfft_f32(&arm_cfft_sR_f32_len1024, lBufInArray, 0, 1);
  arm_cmplx_mag_f32(lBufInArray, lBufOutArray, FFT_LENGTH);

  for (int i = 1; i < FFT_LENGTH/2; i++)
  {
    
    
    lBufOutArray[i] /= 512;
  }

  for(int16_t i = 1; i < FFT_LENGTH/2; i++)
  {
    
    
    printf("%f\n", lBufOutArray[i]);
  }
}

Guess you like

Origin blog.csdn.net/m0_51220742/article/details/124869371