AnsweredAssumed Answered

STM32 real time FIR filter from ADC samples

Question asked by Ruggero Still on Mar 10, 2018
Latest reply on Apr 17, 2018 by David Pekin

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 (tim6 and tim7) 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;
    }
}

Outcomes