Saturday, 23 April 2016

IIR Implementation of Low Pass and High Pass Filters on a Microcontroller or DSP

This post describes the steps involved in designing a digital filter and writing its equivalent code to be executed on a Microcontroller or Digital Signal Processor. This post will contain the derivation of the discretization process of a First order Low Pass Filter and will also contain the experimental results of the First order Low Pass and High Pass Filters. 

1. The s-domain Transfer Function:
Any continuous-time filter can be represented by an equivalent s-domain transfer function, which signifies the relationship between the input and output of the filter (In terms of Magnitude and Phase) throughout the operating frequency spectrum. The s-domain transfer functions can be obtained by performing frequency domain analysis to an electrical equivalent of the filter and finding the relationship between the input and output.
The s-domain transfer function of a First order Low Pass filter is:



2. Various Discretization Methods:
To convert the s-domain transfer function to it's equivalent z-domain transfer function, some of the methods that can be used are Forward/Backward Euler or Tustin's Method. These methods are used to map the s-domain factors to their equivalent factors on the z-plane, so that the continuous-time domain transfer function is effectively converted to the discrete-time domain transfer function.

i. Forward Euler:
ii. Backward Euler:

iii. Trapezoidal (Tustin):

Ts = Sampling interval

3. The z-domain Transfer Function:
While designing the filters, I have considered using the Tustin's method because it provides a better dynamic response. But any of the other methods mentioned above can be used, provided you compromise on the dynamic response of the filter while reducing the execution time of the filter equation by using any of the other 2 methods.



By taking inverse z-transform,


4. Formation of difference equation from the z-domain Transfer Function:
The transfer function cannot be directly executed in code, and has to be formed in terms of an executable equation. By solving the transfer function in terms of Y(z) and by applying properties of z-transform, the final executable equation in terms of y(n) can be found out.
While solving below, two constants A and B are assumed to replace the coefficients in final z transfer function stated above.



Applying the properties of z-transform,
Final executable equation:


5. Code:
The key to implement a filter with a good dynamic response is to have a very small sampling interval, Ts which is dependent upon the bandwidth of your system and the number of samples that you need to record per Hz (samples/Hz). The sampling interval should be repetitive and should not vary with time. A varying sampling interval will cause the approximation to fail and thus result in misbehaviour of the filter or may reproduce poor dynamics. It is ideal to start a Timer interrupt at a sampling frequency (Fs), which gives us the sampling interval (Ts) to be used in the filter equation. Initializing an interrupt ensures that the sampling interval will be fixed and periodic. If the signal is going to be read on the ADC of the MCU/DSP, then the vector address of the Timer ISR should also contain the routines to read the required ADC channel along with the code to execute the filter response, and then the code to write the processed variable on a DAC (If required). The code written is not specific to any MCU/DSP and can be ported to a suitable target device.


/*
IIR Implementation of First Order Low Pass Filter
*/

float x_n, x_n1, y_n, y_n1;
float Fc, wc, Tc, P, Q;
float Ts = 0.0000250; // Example sampling interval = 25 usec

void main()
{
//Peripheral Initialization

//Filter Variables Initialization
x_n = 0.0;
x_n1 = 0.0;
y_n = 0.0;
y_n1 = 0.0;

// Filter Properties : Fc = 300Hz (Example Fc)
Fc = 300.0;
wc = 2.0*3.141592*Fc;
Tc = 1.0/wc;

// One time co-efficient calculation
P = Ts/(Ts + 2.0*Tc);
Q = (Ts - 2.0*Tc)/(Ts + 2.0*Tc);

//Start Timer Interrupt
}

interrupt TIMER_ISR()
{
//Read ADC, Assign value to x_n

y_n = (x_n + x_n1)*P - y_n1*Q;
//Reassign values for next iteration
x_n1 = x_n;
y_n1 = y_n;

// Write value of y_n to DAC
}

High Pass Filter:
By using the same approach as above, discretization of a First order High Pass Filter s-domain Transfer Function yields the following results.

s-domain Transfer Function:

z-domain Transfer Function:
Final executable equation:


/*
IIR Implementation of First Order High Pass Filter
#Initialization remains the same as Low Pass Filter
#Only coefficients and equation changed
*/

// Coefficients
P = (2.0*Tc)/(Ts + 2.0*Tc);
Q = (Ts - 2.0*Tc)/(Ts + 2.0*Tc);

// High Pass Fiter Code
y_n = (x_n - x_n1)*P - y_n1*Q;
x_n1 = x_n;
y_n1 = y_n;

6. Results:

The digital filters are implemented on the C2000 series TMS320F28027's LaunchPad. The filter variables are stored in a buffer and plotted on a graph in Code Composer Studio v6.0.1 instead of writing on a DAC.
A function x(t) = 0.80*sin(2*PI*f*t) + 0.20*sin(2*PI*3f*t), where f = 500 Hz is passed through the filters to observe following response:

1 comment:

  1. Can you please share the details how to implement IIR digital filter for notch and band pass filters.

    ReplyDelete