• AVR Freaks

Hot!IIR Filter implementation on dsPIC33

Author
NADAA
New Member
  • Total Posts : 3
  • Reward points : 0
  • Joined: 2019/08/29 08:34:33
  • Location: 0
  • Status: offline
2019/09/23 09:52:07 (permalink)
0

IIR Filter implementation on dsPIC33

Hello,
I am currently working on a project with dspic33ev on Mplab X IDE and xc16 compiler
I need to remove DC component from a SineWave so to do that I thought that it might be useful to work with DSP Library and IIR Transposed predefined functions 
 
The first step I did was to calculate the filter coefficients on Matlab by specifying the filter order and the cut off frequency (See the picture below)
 
NB : Filter Order = 2
       Cut off frequency = 5Hz
       Sampling frequency = 2 KHz
 
Then, on simulink, I specified a sine wave input with a constant offset and I supposed to get only the offset at the output scope (See attached the output signal)
 
The second step I did was to divide all the coefficients by 2 (so that they will be between -1 and 1) and then convert them to Q15
 
The problem is that the output in Mplab takes random values (Normally, I should get values near to 2045 ADC which is the value of the offset I applied using GBF : 2.5 V )
 
See the output values in a picture attached 
 
****************************************************************************************************
; File iir_filter.s
.equ iir_filterNumSections, 1
; Allocate and initialize filter coefficients
; These coefficients have been designed for use in the Transpose filter only
.section .xdata,data,xmemory
iir_filterCoefs:
.hword 0x0001 ; b( 1,0)/2
.hword 0x0002 ; b( 1,1)/2
.hword 0x3E98 ; a( 1,1)/2
.hword 0x0001 ; b( 1,2)/2
.hword 0x816C ; a( 1,2)/2
; ..............................................................................
; Allocate states buffers in (uninitialized) Y data space
.section .ybss, bss, ymemory
iir_filterStates1:
.space iir_filterNumSections*2
iir_filterStates2:
.space iir_filterNumSections*2
; ..............................................................................
; Allocate and intialize filter structure
.section .data
.global _Filter1
_Filter1:
.hword iir_filterNumSections-1
.hword iir_filterCoefs
.hword 0xFF00
.hword iir_filterStates1
.hword iir_filterStates2
.hword 0x0000
***********************************************************************************************
Main.c
***********************************************************************************************
/******************************************************************************/
/* Files to Include */
/******************************************************************************/
#include <xc.h>
#include <dsp.h>
#include "system.h" /* System funct/params, like osc/peripheral config */
#include "ADC.h"
#include "dsp.h"
#define SEUIL 1000 /*seuil de test : 1.22V environ*/
/******************************************************************************/
/* Global Variable Declaration */
/******************************************************************************/
extern IIRTransposedStruct Filter1;
/*buffer utilisé par la voie 0 du module DMA ==> mesures brutes*/
volatile unsigned int AcquistionsTab[DMA_BUFFER_SIZE] __attribute__((aligned(16)));
#define DATA_LENGTH 255
unsigned int data_in[DATA_LENGTH] __attribute__((space(xmemory)));
unsigned int data_out[DATA_LENGTH];
unsigned int OutVoltage = 0;
unsigned char counter = 0;

void Timer1_config(void)
{
T1CONbits.TON = 0;
T1CONbits.TSIDL = 0;
T1CONbits.TCKPS = 0;
T1CONbits.TCS = 0;
PR1 = 15000;
IPC0bits.T1IP = 2;
TMR1 = 0;
T1CONbits.TON = 1;
IFS0bits.T1IF = 0;
IEC0bits.T1IE = 1;
}
void __attribute__((__interrupt__,__no_auto_psv__)) _T1Interrupt(void)
{ //LATC6_bit =~ LATC6_bit;

OutVoltage = Read_ADC(TENSION_SORTIE);
data_in[counter] = OutVoltage;
counter++;
IFS0bits.T1IF = 0;
}
int main(void)
{
/* broches de test*/
/* Configure the oscillator for the device */
ConfigureOscillator();
Init_ADC();
// int cpt = 0;

T5CONbits.TCKPS = 0;
PR5 = 3000;
IEC1bits.T5IE = 1;
IFS1bits.T5IF = 0;
IPC7bits.T5IP = 7;
T5CONbits.TON = 1;
Timer1_config();
IIRTransposedInit(&Filter1);
aa =1;
while(1)
{
IIRTransposed(DATA_LENGTH, (fractional*)data_out, (fractional*)data_in, &Filter1);
}
}
****************************************************************************************************
 
Thank you in advance for your help !
 
Nada

Attached Image(s)

#1
du00000001
Just Some Member
  • Total Posts : 3075
  • Reward points : 0
  • Joined: 2016/05/03 13:52:42
  • Location: Germany
  • Status: online
Re: IIR Filter implementation on dsPIC33 2019/09/23 10:11:54 (permalink)
0
I have no Simulink to play with, nor do I have the time to maybe debug your fancy algorithm.
 
Why can't you do it like other kids - simply implementing a sliding signal average with a sufficiently low filter coefficient (Fc)?
 
According to the basic formula

Y[t] = Y[t-1]*(1-Fc) + X[t]*Fc

This one is simple, proven, free from oscillations under whatever conditions you could imagine, ...

PEBKAC / EBKAC / POBCAK / PICNIC (eventually see en.wikipedia.org)
#2
NADAA
New Member
  • Total Posts : 3
  • Reward points : 0
  • Joined: 2019/08/29 08:34:33
  • Location: 0
  • Status: offline
Re: IIR Filter implementation on dsPIC33 2019/09/24 01:20:51 (permalink)
0
Hi, 
 
Thank you for your "funny" answer LoL: LoL
 
Well, I am supposed to implement a second order IIR filter using at a first time the predefined functions in DSP Library :
IIRCanonic() IIRTransposed() IIRLattice()
 
I think that as long as it exists, it should work so any help in this would be very kind 
 
And concerning my "fancy" algorithm it is quite simple :
 
In the asm file there's the implementation of five coefficients/2 in Q15 that I got from Matlab (As long it is a 2nd order)
 
And In the main.c file, there's 2 predef functions call : 
 
IIRTransposedInit() : to initialize the filter 
IIRTransposed() : to apply IIR filter 
 
I don't know where I did it wrong sad: sad
 
Thank you in advance !
 
 
#3
du00000001
Just Some Member
  • Total Posts : 3075
  • Reward points : 0
  • Joined: 2016/05/03 13:52:42
  • Location: Germany
  • Status: online
Re: IIR Filter implementation on dsPIC33 2019/09/24 01:52:20 (permalink)
0
The description might not be complete:
  • Is the lower trace in capture.gif your filter's output ? That's looking reasonable.
  • Or is this from Matlab/Simulink?  In this case it would be nice if you could provide more than just some xx values for input and output values. Preferably in some graphic form.
  • Provided you've got an 'EV with enough pins, you could even use the DAC outputs (ok - only 7 bits of resolution available. But really useful to visualize e.g. input and output continuously.)

PEBKAC / EBKAC / POBCAK / PICNIC (eventually see en.wikipedia.org)
#4
atonyb
New Member
  • Total Posts : 15
  • Reward points : 0
  • Joined: 2014/05/08 07:11:07
  • Location: 0
  • Status: offline
Re: IIR Filter implementation on dsPIC33 2019/09/30 08:33:38 (permalink)
0
It's hard to get a clear idea of what's going on here, but I wanted to pick on the halving of coefficients you are doing. It's ok to halve your zeros (your a coefficients) as this simply has the result of halving the gain of your filter for any given frequency. Halving your pole/feedback coefficients on the other hand will totally change the response of your filter.
 
I'm not familiar with the library function you are calling or what it expects - so maybe it is expecting the format in Q14 to give a dynamic range of 2>x>=-2 as you often need for biquads. If I were to do a biquad myself I would probably code it myself which is why I am not familiar with the library... Maybe you could paste in either a picture or a link to the relevant docs for it?
 
The random values could also be a result of overflowing if saturation isn't enabled (but, frankly, you can get similar problems even if intermediate saturation is occurring). 
#5
Jump to:
© 2019 APG vNext Commercial Version 4.5