2018-03-10 12:40 PM
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 29arm_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; }}2018-03-13 02:17 AM
Problem solved! The code is 100% right. I figured out that I swapped some pins in STM32CubeMX and so I was not putting my probe on the DAC output!
2018-03-13 02:32 AM
static float32_t firCoeffs[NUM_TAPS] = {-0.0018225230f, -0.0015879294f, +0.0000000000f ...
Just for the books - I think your floating point number precision is a bit excessive.
Single precision does not carry that much digits.
2018-03-13 08:43 AM
Yes, you are totally right. In fact I got the filter computed by a website that outputs the coefficients as 'double' type. I just forgot that, many thanks!
2018-04-17 01:42 PM
Hello, I just started looking at the CubeMX FIR filters. I too need to filter an ADC reading but I need a notch type filter.
I'm updating a PID loop at approximately 4Khz. Some system resonances are present in the ADC reading that I need to filter out. These resonances are around 80hz. I figured I could use a LP and HP filter to achieve a 80 hz notch filter. But I've got a number of questions.
I see you set the block size to 1 so you filter each sample as it's taken. That's what I need to do as well Apparently the filter state structure keeps track of the prior N samples and is able to filter using that past data, right?
For a notch filter can I just feed the output of the LP filter into the HP filter? That doesn't sound right since the output from the LP would not have the high frequency component. Or should I take the original ADC reading and feed that into both a LP and a HP filters and then add the 2 outputs? I'm uncertain on the correct approach.
The FIR example shows how to build a LP filter by getting MATLAB to generate the coefficients by calling the fir1() MATLAB function. How do I configure a HP filter?
Thanks for any pointers on this!