Hello,
i working with a TWR-K60F120M Evaluationboard.
I build a continuous single ended adc Measurement and all works fine. With the dma function i don't have to burden the µC with the measurement. My problem is that i can't find any components for digital filtering and i have problems to use the CMSIS Lib of ARM. I looking for a way to use a Moving average on my measured value without programm the code myself.
My ADC measurement saves 32768 values via dma in a array and all works fine and the change of my coeffs work also from float to int16_t.
Here my code for fir
//DEFINES
#define TEST_LENGTH_SAMPLES 16384
#define BLOCK_SIZE 32
#define NUM_TAPS 29
//COEFFICIENTS fir1(28,1/5) mathlab
float32_t Coeffs[NUM_TAPS]={
0.0011 , 0.0021 , 0.0032 , 0.0031 , -0.0000 , -0.0071 , -0.0165 , -0.0233 , -0.0200 , 0.0000 , 0.0386 , 0.0906 , 0.1441 ,
0.1845 , 0.1995 , 0.1845 , 0.1441 , 0.0906 , 0.0386 , 0.0000 , -0.0200 , -0.0233 , -0.0165 , -0.0071 , -0.0000 , 0.0031 ,
0.0032 , 0.0021 , 0.0011
};
//
uint16_t numblocks=TEST_LENGTH_SAMPLES/BLOCK_SIZE;
//NUMBER OF SAMPLES
uint32_t blocksize=BLOCK_SIZE;
//COEFFICIENTS int16_t
int16_t Coeffsq15[NUM_TAPS];
//FIR Output
int16_t output_fir[TEST_LENGTH_SAMPLES];
//STATE buffer
int16_t firstate[BLOCK_SIZE+NUM_TAPS];
....
int main(void)
/*lint -restore Enable MISRA rule (6.3) checking. */
{
....
arm_fir_instance_q15 S;
uint16_t i;
....
//FIR
arm_float_to_q15(Coeffs,Coeffsq15,29);
arm_fir_init_q15(&S,29,&Coeffsq15[0],&firstate[0],blocksize);
for (;;)
{
if(DMA_complete==TRUE)
{
for(i=0;i<numblocks;i++)
{
arm_fir_q15(&S,Messwertarray+(i*blocksize),output_fir+(i+blocksize),blocksize);
}
}
If i debug my system jumps in a hardfault. What am i doing wrong?
Hi, Philipp,
I suspect that the code is incorrect.
arm_fir_q15(&S,Messwertarray+(i*blocksize),output_fir+(i+blocksize),blocksize);
Pls check if the address of Messwertarray and output_fir is correct.
I suspect you should use this line.
arm_fir_q15(&S,Messwertarray+(i*blocksize*sizeof(int16_t)),output_fir+(i*blocksize*sizeof(int16_t)),blocksize);
Pls have a check.
BR
Xiangjun Rong
i can use the library , i found my problem with the implantation.
but i don't know how to use the q15 fir function probably
Hi, Philipp,
I am glad to hear you have fixed the library issue.
Regarding the q15 FIR digital filter, I suppose you have to acquire the coefficents array with matlab or the other tools based on the application requirements, if the coefficents array is float type, and the absolute maximum element is greater than 1, you can divide each element of the coefficents with the absolute maximum element, in this way all the coeffiecnts in the array ranges from -1 to +1.
You can use the macro to transform the coeeicents to Q15.
#define FRAC16(x) 32768*x
#define TAPNUMBER 20
#define BLOCKSIZE 1
#define TOTAL_POINTS 100
#define Q15_OFFSET 0x4000
int16_t lpFilterCoefficent[TAPNUMBER]=
{
FRAC16(4.45556640625000e-003),
FRAC16(1.44042968750000e-002),
FRAC16(2.54516601562500e-002),
FRAC16(3.69873046875000e-002),
FRAC16(4.84619140625000e-002),
FRAC16(5.92041015625000e-002),
FRAC16(6.86950683593750e-002),
FRAC16(7.63244628906250e-002),
FRAC16(8.16650390625000e-002),
FRAC16(8.44116210937500e-002),
FRAC16(8.44116210937500e-002),
FRAC16(8.16650390625000e-002),
FRAC16(7.63244628906250e-002),
FRAC16(6.86950683593750e-002),
FRAC16(5.92041015625000e-002),
FRAC16(4.84619140625000e-002),
FRAC16(3.69873046875000e-002),
FRAC16(2.54516601562500e-002),
FRAC16(1.44042968750000e-002),
FRAC16(4.45556640625000e-003)
};
const arm_fir_instance_q15 sFirStru;
int16_t FirState[TAPNUMBER+BLOCKSIZE];
int16_t temp,temp1;
void main()
{
.....................
arm_fir_init_q15(&sFirStru,TAPNUMBER,&lpFilterCoefficent[0],&FirState[0],BLOCKSIZE);
arm_fir_fast_q15(&sFirStru,&temp,&temp1,1);
}
In the code, the temp is the latest sample(Note if the sample is in 16 bits, you should logic right shift one bit, because the MSB is regarded as sign. In other words, the MSB should be zero), temp1 is the filtered result. Generally, the arm_fir_fast_q15() should be put in the ADC ISR.
Hope it can help you
BR
xiangJun Rong
Hi, Philipp,
I suggest you can use FIR digital filter, if you want to perform Moving average, it is okay to use digital filter by setting the digital coefficents as the same value.
I think you have to do digital filtering, currently, what is your problem? You can post you code, I can help you to fix the issue.
BR
Xiangjun Rong