This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

STM32 real time FIR filter from ADC samples

Hello,

I have a Nucleo-L476RG board and I'm trying to make a lowpass filter with the FIR function (using cmsis libraries) to filter the samples I get from the ADC in realtime.
Then I'd like to get the processed signal out through the DAC.

Both ADC and DAC work at a sampling frequency of 20khz, triggered by two different timers. They use DMA.

FIR function is called every time the ADC ends a conversion.

I'm using arrays of 1 element as buffers, so the number of blocks of the FIR function is 1.

I can get a signal on the output, but it does not match what the input signal processed through the filter would be.

Thank you very much for your help. I hope my explanation is good enough.

Here is my code:

#include <math.h>
#include "arm_math.h"
uint32_t adcValue[1];
uint32_t adcValue1[1];
int i;
float32_t signal_in = 0;
float32_t signal_out = 0;

#define TEST_LENGTH_SAMPLES  1
#define BLOCK_SIZE            1
#define NUM_TAPS              29



arm_fir_instance_f32 S;

static float32_t firStateF32[BLOCK_SIZE + NUM_TAPS - 1];

static float32_t firCoeffs[NUM_TAPS] = {-0.0018225230f, -0.0015879294f, +0.0000000000f, +0.0036977508f, +0.0080754303f,
    +0.0085302217f, -0.0000000000f, -0.0173976984f, -0.0341458607f, -0.0333591565f,
    +0.0000000000f, +0.0676308395f, +0.1522061835f, +0.2229246956f, +0.2504960933f,
    +0.2229246956f, +0.1522061835f, +0.0676308395f, +0.0000000000f, -0.0333591565f,
    -0.0341458607f, -0.0173976984f, -0.0000000000f, +0.0085302217f, +0.0080754303f,
    +0.0036977508f, +0.0000000000f, -0.0015879294f, -0.0018225230f};


uint32_t blockSize = BLOCK_SIZE;
uint32_t numBlocks = TEST_LENGTH_SAMPLES/BLOCK_SIZE;


void SystemClock_Config(void);


int main(void)
{

  HAL_Init();

  /* Configure the system clock */
  SystemClock_Config();

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_DAC1_Init();
  MX_TIM6_Init();
  MX_ADC1_Init();
  MX_TIM7_Init();
  MX_ADC2_Init();

  //Timers
  HAL_TIM_Base_Start(&htim6);
  HAL_TIM_Base_Start(&htim7);

  //ADC Start
  HAL_ADC_Start_DMA(&hadc1, adcValue, 1 );
  
  //DAC Start
  HAL_DAC_Start(&hdac1,DAC_CHANNEL_1);    
  HAL_DAC_Start_DMA(&hdac1, DAC_CHANNEL_1, (uint32_t*)adcValue1, 1, DAC_ALIGN_12B_R);

  //FIR Init
  arm_fir_init_f32(&S, NUM_TAPS, (float32_t *)&firCoeffs[0], (float32_t *)&firStateF32[0], blockSize);
  

  /* Infinite loop */
 
   while (1)
   {
  
   }
  

}

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
	if(hadc->Instance == ADC1)
	{
		    signal_in = (float32_t)adcValue[0];

		    arm_fir_f32(&S, &signal_in, &signal_out, blockSize);

		    adcValue1[0] = (uint32_t)signal_out; //signal_out;

	}
}

  • Hello Ruggine, 

    Im doing the same right now, could you get any improvement on your results? i think the issue with the difference between expected results and the reached results is regarding that in the FIR example has floating point input format, and in your case the ADC give a int format data, so you need to convert that into voltage floating point data and then pass through the FIR, hope you can get your expected results and let me know...

    kind regards

    Msc Dmitri S.

  • NUM_TAPS should be even for Q15.

    F32 Helium version the array of coefficients must be a multiple of 16 even if less then 16 coefficients are used.

    arm-software.github.io/.../group__FIR.html