Lab 2 Filters

Download as pdf or txt
Download as pdf or txt
You are on page 1of 14

Lab

 2:  Designing  a  Low  Pass  Filter  


In  this  lab  we  will  be  using  a  low  pass  filter  to  filter  the  signal  from  an  Infra  Red  (IR)  sensor.  The  IR  sensor  
will  be  connected  to  the  Arduino  and  Matlab  will  be  used  to  view  and  filter  the  signal.  We  use  Matlab  
because  it  allows  us  to  graph  the  data.  This  is  very  useful  for  optimizing  the  filter  coefficients  and  for  
determining  whether  the  filter  is  working  properly.  For  your  final  project,  you  will  likely  not  be  using  
Matlab.  However,  using  Matlab  filters  to  optimize  your  Arduino  filters  during  the  design  stage  could  be  
very  helpful  as  you  can  see  and  compare  the  output  easily.    

The  purpose  of  a  filter  is  to  remove  some  unwanted  component  from  a  signal.  In  this  lab,  it  will  be  used  
to  remove  high  frequency  noise  from  the  IR  signal  we  wish  to  analyze.  The  cut-­‐off  frequency  is  the  
boundary  in  a  filter's  response.  Any  frequencies  outside  the  cut-­‐off  frequency  range  will  be  attenuated.    
Ideally  the  filter  would  completely  eliminate  any  frequencies  outside  the  cut-­‐off  frequency  range.  
However,  in  reality,  the  attenuation  depends  on  the  order  of  the  filter.  Higher  order  filters  attenuate  the  
unwanted  frequencies  more  effectively,  but  increase  the  lag  (phase  delay)  between  the  input  and  
output.  The  figure  below  shows  various  orders  of  low  pass  filters  (order  1  to  5).  Notice  that  the  steepest  
attenuation  is  associated  with  the  highest  order  filter.    

 
Figure  1-­‐  Low  Pass  Filters  of  various  Orders  

You  can  either  have  an  analog  filter  or  a  digital  filter.  As  you  might  expect,  analog  filters  are  used  for  
analog  signals  (continuous  waveforms)  and  digital  filters  are  used  for  digital  (discrete)  signals.      
Analog  filters  are  created  from  hardware  components  such  as  resistors,  capacitors  and  inductors  
whereas  digital  filters  are  software  based.  You  are  likely  more  familiar  with  analog  filters  because  of  
your  Controls  class.  The  steps  for  designing  a  digital  filter  are  very  similar  to  those  for  an  analog  filter.  
First,  the  desired  filter  response  must  be  characterised  and  then  the  parameters  calculated.    For  analog  
filters  the  parameters  calculated  are  the  resistor,  capacitor  and  inductor  values  required  to  build  the  
filter.  For  digital  filters  the  parameters  calculated  are  the  coefficients  used  in  the  software  
implementation  of  the  filter.        

Classes  of  Digital  Filters  


 

Digital  filters  can  be  classified  as  follows:  

(a)  Linear  filters  versus  nonlinear  filters.    

(b)  Time-­‐invariant  filters  versus  time-­‐varying  filters.    

(c)  Adaptive  filters  versus  non-­‐adaptive  filters.    

(d)  Recursive  versus  non-­‐recursive  filters.    

(e)  Direct-­‐form,  cascade-­‐form,  parallel-­‐form  and  lattice  structures  

In  this  lab  we  will  be  using  a  recursive,  linear  time  invariant  (LTI)  filter.  This  is  a  filter  whose  output  is  a  
linear  combination  of  the  input  signals  and  the  previous  output  signals.  The  filter  coefficients  do  not  vary  
with  time.  The  formula  below  describes  the  most  basic  time  domain  input-­‐output  relationship  for  a  first  
order,  LTI,  recursive  filter.    

y(i)=α*  y(i  −1)  +  x(i)  

Where  x(i)  is  the  filter  input  (raw  data),  y(i)  is  the  filter  output(filtered  signal),  α  is  the  filter  coefficient,  i  
is  the  current  time  step  and  y(i-­‐1)  is  the  previous  filter  output.    

Characterising  the  Filter  


 

There  are  many  methods  used  for  characterizing  a  filter,  but  the  most  commonly  used    is  the  transfer  
function.  Transfer  functions  are  usually  used  to  describe  single-­‐input  single-­‐output  filters.  The  input  
signal  goes  through  the  transfer  function  and  is  converted  into  the  desired  output  signal.  See  below.  

 
Input  x(t),  X(z)   H(z)   Output  y(t),  Y(z)  
 

x(t)  and  y(t),  usually  denoted  with  lowercase  x  and  y,  are  the  time  domain  signals  and  X(z)  and  Y(z),  
usually  denoted  with  uppercase  X  and  Y,  are  the  frequency  domain  signals.  To  define  the  transfer  
function,  you  must  first  convert  the  time  domain  signals  into  frequency  domain  using  the  Z-­‐transform.  
The  Z-­‐transform  is  the  equivalent  of  the  Laplace  Transform,  but  for  digital  instead  of  analog  signals.  
Once  the  relationship  between  the  input  and  output  signals  is  defined  in  frequency  domain,  the  transfer  
function,  H(z),  is  simply  the  output,  Y(z),  over  the  input,  X(z).    

The  transfer  function  for  a  linear,  time  invariant,  digital  filter  is  defined  as  follows.    

𝑌 𝐵(𝑧) 𝑏+ + 𝑏- 𝑧 .- +  𝑏0 𝑧 .0 +  . . . 𝑏2 𝑧 .2
𝐻 𝑧 = = =  
𝑋 𝐴(𝑧) 1 + 𝑎- 𝑧 .- +  𝑎0 𝑧 .0 +  . . . 𝑎5 𝑧 .5

Where  H(z)  is  the  transfer    function  in  frequency  domain  (z)  and  the  parameters    to  be  determined  are  
B(z)  and  A(z).  B  is  a  1xN  matrix  of  the  numerator  coefficients  and  A  is  a  1xM  matrix  of  the  denominator  
coefficients.  So  B  =  [b0  b1  b2  ...  bN]  and  A  =  [  1  a1  a2  ....  aM  ].    

For  the  1st  order  filter  above  the  transfer  function  is  as  follows.  This  was  derived  using  the  Z-­‐transform.    

1
𝐻(𝑧)   =  
1 + 𝛼𝑧 .-

Low  Pass  Filter  


 

The  type  of  filter  you  require  depends  on  which  frequencies  you  want  to  attenuate.  For  example,  a  low  
pass  filter  passes  low  frequencies  and  attenuates  the  high  frequencies  (frequencies  higher  than  the  
cutoff  frequency).    The  time  domain  representation  of  a  low  pass,  LTI,  first  order,  recursive  filter  can  be  
seen  below:  

𝑦8 = 𝛼𝑥8 +   (1 − 𝛼)𝑦8.-  

Where  x  is  the  unfiltered  data,  y  is  the  filtered  data  and  α  is  the  filter  (smoothing)  coefficient.  The  
smoothing  coefficient  can  be  modified  depending  on  the  desired  system  response.  For  an  in-­‐depth  
explanation  of  low  pass  filters  and  the  derivation  of  this  equation,  visit  the  low  pass  filter  Wikipedia  
page:  http://en.wikipedia.org/wiki/Low-­‐pass_filter  

Once  the  time  domain  equation  is  known,  the  Z-­‐transform  is  used  to  get  the  equation  in  frequency  
domain  so  the  transfer  function  can  be  determined.  The  Z-­‐transformation  is  shown  below.  

 
𝑦8 = 𝛼𝑥8 +   1 − 𝛼 𝑦8.-  

𝑦8 − 1 − 𝛼 𝑦8.- = 𝛼𝑥8      

𝑌 − 1 − 𝛼 𝑌(𝑧)𝑧 .- = 𝛼𝑋  

𝑌 ∗ 1 − 𝑧 .- + 𝛼𝑧 .- = 𝛼𝑋  

𝑌 𝛼
=  
𝑋 1 − 𝑧 + 𝛼𝑧 .-
.-

The  Transfer  function  can  be  written  as:  

𝐵 𝑧 𝛼
𝐻 𝑧 = =  
𝐴 𝑧 1 + (𝛼 − 1)𝑧 .-

Therefore,    the  B  and  A  matrices  are:  

B  =  α  

A  =  [  1  (α-­‐1)]  

Just  a  few  notes  on  how  to  do  the  Z-­‐transformation  (in  case  you  were  interested):  

constants  stay  the  same  


yi  =  y(z)  
xi  =  x(z)  
yi-­‐1  =  y(z)*z-­‐1  
yi-­‐2  =  y(z)*z-­‐2....    
 

Since  digital  filters  are  implemented  in  code,  there  are  various  ways  you  can  program  them.    One  is  to  
use  the  filter  functions  built  into  Matlab.  These  functions  require  inputs  of  either  the  sampling  
frequency  or  the  coefficients,  A  and  B.  Although  you  will  likely  not  be  using  Matlab  for  your  final  project,  
it  may  be  useful  to  use  the  Matlab  filters  to  compare  and  optimize  your  Arduino  filtering.  This  is  why  we  
will  go  over  using  the  filter  functions  in  Matlab  

Another  way  to  implement  the  filter  in  code,  is  simply  to  use  the  time  domain  formula.  This  is  the  
simplest  way  and  is  good  for  programming  languages  where  there  are  no  filter  functions  built  in,  like  the  
Arduino.    

Time  Domain  Formula  in  Software    


 

In  order  to  implement  the  low  pass,  LTI,  first  order  filter  in  the  code,  you  simply  use  the  time  domain  
function  for  the  low  pass  filter  from  above.  The  formula  below  is  the  implementation  of  this  filter  in  
Matlab  code.  

y(i) = a*x(i)+(1-a)*y(i-1);
Where  y  is  an  array  of  the  filtered  values  and  x  is  an  array  of  the  raw  data.  y(i)  is  the  filtered  data  output  
and  y(i-­‐1)  is  the  previous  filtered  data  output  value.    

We  will  now  use  this  formula  to  filter  the  input  from  an  IR  sensor.  The  Arduino  code  in  Appendix  A  will  
read  the  IR  sensor  values  and  output  the  raw  values  to  Matlab.  Once  we  have  the  raw  values  we  will  
filter  and  plot  them  in  Matlab.  The  sample  code  to  do  this  filtering  is  shown  in  Appendix  B.  This  function  
reads  the  IR  output  from  the  Arduino  and  plots  the  raw  and  filtered  data  with  respect  to  time.  The  time  
array  is  created  using  the  'tic'  and  'toc'  functions  in  Matlab.  If  a  more  precise  counter  is  required,  it  
should  be  done  on  the  Arduino.    

The  plots  below  show  the  un-­‐filtered  and  filtered  IR  data  for  α  =0.1  and  α=0.01.  Note  that  the  smaller  
the  α  value,  the  smoother  the  data,  but  the  larger  the  phase  delay.    

 
Figure  2-­‐  Filtered  Voltage(red)  and  Unfiltered  voltage(blue)  from  IR  sensor  with  alpha  =  0.1  
 
Figure  3-­‐  Filtered  Voltage(red)  and  Unfiltered  Voltage(blue)  from  IR  sensor  with  alpha  =  0.01  

Notice  that  a  value  of  α  =  0.01,  causes  too  much  filtering  and  the  output  curve  is  excessively  smoothed.  
You  will  need  to  find  the  optimal  combination  between  eliminating  noise,  but  still  having  a  function  that  
responds  quickly  to  changes.  This  is  done  by  trial  and  error.    

This  is  the  most  basic  implementation  of  the  low  pass  filter  and  is  very  useful  if  you  do  not  have  any  built  
in  filtering  functions.  However,  Matlab  does  have  built  in  filter  functions.  These  functions  require  the  
coefficients  (A  and  B),  that  were  calculated  above,  as  inputs  to  define  the  type  of  filter.    We  will  only  
look  at  the  filtfilt  function  in  this  lab,  but  there  are  lots  of  other  types  you  can  use.    

Matlab  FiltFilt  function  


 

If  you  notice,  the  filtered  voltage  above  is  shifted  from  the  original  voltage  in  both  of  the  above  graphs.  
This  is  due  to  the  time  required  to  process  the  filtering  equation  on  the  fly.  In  order  to  avoid  this  shift  we  
can  use  the  filtfilt  function  in  matlab.  The  filtfilt  function  performs  zero-­‐phase  shift  digital  filtering  by  
processing  the  data  in  both  the  forward  and  reverse  direction.  However,  since  filtfilt  needs  to  process  
the  data  both  backwards  and  forwards,  it  needs  to  know  all  the  data,  meaning  it  cannot  be  used  on  the  
fly.  You  must  first  create  an  array  of  all  the  collected  data,  raw  values,  and  then  filter  that  array  instead  
of  using  the  function  on  every  data  point  individually  as  we  did  in  the  previous  example.  To  learn  more  
about  the  filtfilt  function,  type  "help  filtfilt"  into  the  Matlab  command  line.  The  following  line  shows  
how  to  properly  call  the  filtfilt  function.    

Y  =  filtfilt(B,A,X);  

Where  X  and  Y  are  the  unfiltered  and  filtered  data  arrays  respectively  and  B  and  A  are  the  transfer  
function  coefficients  calculated  above.    The  Matlab  code  below  uses  the  filtfilt  function  to  filter  the  IR  
data  from  above.    

%This function using filtfilt to low pass filter data(an array of values from
the IR sensor). It then plots the filtered and unfiltered data.
function IR_SENSOR_FILTFILT(obj)
tic;
i= 1;
while toc < 10
time(i) = toc;
voltage(i) = (obj.ard.analogRead(2))*(5/1024);
i = i+1;
end
a = 0.1; %sets the value of alpha
filtered_data = filtfilt(a,[1 a-1],voltage);
%uses filtfilt to filter the voltage data
figure;
plot(time,voltage,'b');
hold on;
plot(time,filtered_data,'r');
xlabel('Time');
ylabel('Voltage');
end

See  the  plot  below  for  the  output  of  the  unfiltered  (blue)  and  filtered  data  (red),  found  using  the  filtfilt  
function.    
 
Figure  4-­‐  FiltFilt  Filtered  and  Unfiltered  voltage  plot  with  alpha  of  0.1  

Note  that  in  the  plot,  the  filtered  voltage  is  not  offset  from  the  original.  Sometimes,  depending  on  the  
type  of  filter,  the  offset  will  be  linear  so  a  formula  can  be  used  to  shift  all  the  data  backwards.  
Unfortunatley,  this  is  not  the  case  for  the  simple  low  pass  filter  formula  we  used.  This  is  why  the  zero  
phase  shift    of  the  filtfilt  function  is  so  useful  however,  since  it  can  only  be  used  after  all  the  signal  data  
has  been  read,  it  would  not  be  useful  for  a  balancing  robot  application.  In  order  to  balance,  the  signal  
needs  to  be  read  and  filtered  in  real  time.    

   
Butterworth  
 

The  Butterworth  filter    is  another  type  of  linear,  time  invariant  filter.  However,  it  will  have  different  B  
and  A  transform  function  coefficients  than  the  basic  LTI,  low  pass  filter.  There  is  a  Butterworth  filter  
function  builder  in  Matlab  so  it  is  very  easy  to  use.  If  you  want  to  implement  a  Butterworth  filter  in  the  
Arduino  you  should  first  use  Matlab  to  determine  the  A  and  B  coefficients.  In  order  to  determine  these  
coefficients  we  use  the  'butter'  function  in  Matlab.    

Using  butter  Function  to  Find  the  Coefficients:  


 

The  butter  function  will  create  a  butterworth  filter  and  give  us  the  coefficients  (B  and  A).  The  syntax  to  
call  the  function  is  shown  below.    

[B,  A]  =  butter(N,Wn,'low')  

Where  B  and  A  are  transfer  function  coefficients,  N  is  the  order  of  Butterworth  filter  you  wish  to  design  
(remember  the  higher  the  order  the  more  accurate,  but  the  more  lag)and  Wn  is  the  normalized  cut-­‐off  
frequency.  By  default,  the  Butterworth  filter  is  a  low  pass  filter  i.e.  butter(N,Wn)  will  design  a  low  pass  
filter,  but  you  can  design  all  types  of  filters  (see  help  butter  in  Matlab  for  more  details).  

The  cut-­‐off  frequency  for  a  digital  filter  can  be  given  by  the  following  formula:  

1
𝑓= =  
1−𝛼
2𝜋∆𝑇
𝛼

This  formula  comes  from  substituting  the  RC  formula  for  digital  filters  into  the  cut-­‐off  frequency  formula  
for  analog  filters(see  Wikipedia  low  pass  filter  page).  ∆T  is  the  sampling  period.  For  operations  in  Matlab,    
you  can  calculate  an  approximate  value  of  ∆T  by  creating  a  time  array  using  the  'tic'  and  'toc'  functions.  
The  sampling  period  is  then  the  maximum  value  in  the  time  array  and  divided  by  the  number  of  entries.  
This  is  not  the  most  accurate  method  since  'tic'  and  'toc'  are  just  counters,  but  provided  you  don't  do  
too  many  time  intensive  processes  (graphing,  printing,  complex  math  etc)  in  between  the  counting  you  
should  get  a  good  result.  The  use  of  tic  and  toc  are  shown  in  in  the  IR_SENSOR_FILTFILT  function  above.      

The  normalized  cut-­‐off  frequency  is  then:  

𝑓=
𝑊C   =    
2𝑓D

Where  fs  is  the  sampling  frequency  (1/sampling  period).  If  you  are  using  the  Arduino,  you  could  set  a  
timer  interrupt  and  sample  everytime  the  interrrupt  goes  off.  That  way  you  know  your  exact  sampling  
frequency.      
Once  we  have  the  coefficients,  we  can  implement  the  filter.  We  will  go  over  how  to  implement  it  in  both  
Matlab  and  Arduino.    

Matlab  Butterworth  Filter  Implementation  


 

To  implement  the  filter  in  Matlab,  we  will  use  the  filtfilt  function  due  to  the  zero  phase  shift,  but  you  
could  also  use  Y  =  filter(B,A,X).  The  following  function  outlines  how  to  create  and  use  a  butterworth  
filter  in  Matlab  to  filter  the  raw  IR  data.    

function [B,A] = BUTTERWORTH(obj,N)


T = max(time)/length(time); %Calculates Sampling Period
fc = 1/(2*pi()*T*(1-a)/a); %Calculates the cutoff frequency
Wn = fc/(2*1/T); %Normalized Cutoff frequency(0 < Wn < 1)
[B,A] = butter(N,Wn,'low');
%Generates coefficients of lowpass Butterworth filter, order N
Butterworth = filtfilt(B,A,IR); %IR is the array of raw data
figure; %Creates a new figure
plot(time,IR,'r');
hold on
plot(time,Butterworth,'b')%Butterworth = array of filtered values
end

The  plot  below  shows  the  filtered  and  unfiltered  data  when  'butter'  is  used  to  determine  the  B  and  A  
matrices.  
 
Figure  5-­‐  Filtered  and  Unfiltered  Voltage  plots  using  Butterworth  filter  design  and  alpha  of  0.1  

Arduino  Butterworth  Filter  Implementation  


 

To  implement  this  filter  on  the  Arduino  you  will  need  to  manually  write  out  the  equation  using  the  
coefficients.    Recall  from  above  that  the  transfer  function  in  frequency  domain  can  be  defined  as  
follows:  

𝑌 𝑏+ + 𝑏- 𝑧 .- +  𝑏0 𝑧 .0 +  . . . 𝑏2 𝑧 .2
=  
𝑋 1 + 𝑎- 𝑧 .- +  𝑎0 𝑧 .0 +  . . . 𝑎5 𝑧 .5

Assume  that  the  B  and  A  matrices  for  the  low  pass,  LTI,  first  order,  recursive  filter,  defined  above,    are  as  
follows:  

B    =  [  b0  b1  ]  and  A  =  [  1  a1]  

The  Butterworth  filter  can  be  determined  using  the  following  relation.    
𝐴𝑦 = 𝐵𝑥  

Plugging  in  the  matrices  and  solving  for  Y  gives  the  following.  Remember  this  example  is  for  a  1st  order  
Butterworth.    

 𝑦8   =   𝑏+ 𝑥8 + 𝑏- 𝑥8.- − 𝑎- 𝑦8.-  

If  you  want  a  higher  order,  you  will  get  larger  matrices.  A  second  order  Butterworth  filter  would  yield  
1x3  matrices  and  would  give  you  the  following  equation:  

   𝑦8   =   𝑏+ 𝑥8 + 𝑏- 𝑥8.- + 𝑏0 𝑥8.0 − 𝑎- 𝑦8.- − 𝑎0 𝑦8.0  

Note:    y*a1  yields  yi-­‐1  and  y*a2  would  yield  yi-­‐2  etc.    

Since  we  used  the  butter()  function  in  Matlab  to  determine  the  A  and  B  coefficients,  we  are  
implementing  a  Butterworth  filter.  If  you  would  like  to  use  another  type  of  filter,  you  can  use  a  different  
function  in  Matlab  to  determine  the  coefficients.  For  example,  to  obtain  the  A  and  B  coefficients  for  a  
Chebyshev  filter  you  could  use  the  chebyl  function  in  Matlab.    

Lab  Requirements  
 

This  lab  showed  a  few  different  ways  to  do  filtering.  For  this  lab  you  will  need  to  do  the  following:  

•   Connect  an  IR  sensor  to  the  Arduino  


•   Read  the  raw  IR  data  and  output  it  to  Matlab  
•   Choose  three  filtering  methods  from  above  and  use  them  on  the  IR  data  
•   Create  one  graph  per  filtering  method  showing  the  raw  and  filtered  data  as  well  as  what  filtering  
coefficient  was  used  

You  do  not  need  to  implement  the  butter  filter  on  the  Arduino  for  this  lab,  but  it  may  be  useful  for  your  
final  project  so  you  may  want  to  try  it.  If  you  choose  to  use  it  as  one  of  your  three  filtering  methods,  you  
will  need  to  import  the  filtered  data  and  graph  it  in  Matlab.    

Remember  the  filtfilt  function  is  not  defined  on  the  Arduino  so  it  can  only  be  used  in  Matlab.  Also  for  
your  project  you  will  want  to  measure  and  evaluate  the  data  in  real  time  so  the  filtfilt  function  wouldn't  
really  be  useful  anyway.    

A  write-­‐up  is  not  required  for  this  lab.    

   
 

Appendix  A  
 

 
 

Appendix  B  
clc;
clear all;
numSec=10;
IR=[];
IR_filt = [];
a = 0.5; %smoothing coefficient (to be optimized)

s1 = serial('COM8'); % define serial port


s1.BaudRate=9600; % define baud rate
set(s1, 'terminator', 'LF'); % define the terminator for println
fopen(s1);

try % use try catch to ensure fclose


% signal the arduino to start collection
w=fscanf(s1,'%s'); % must define the input % d or %s, etc.
if (w=='A')
display(['Collecting data']);
fprintf(s1,'%s\n','A'); % establishContact just wants
% something in the buffer
end

i=0;
t0=tic;
while (toc(t0)<=numSec)
i=i+1;
t(i) = toc(t0);
t(i) = t(i)-t(1);
IR(i)=fscanf(s1,'%f'); % must define the input % d, %f, %s, etc.
if(i==1)
IR_filt(i) = IR(i);
else
IR_filt(i) = a*IR(i)+(1-a)*IR_filt(i-1);
end
plot(t,IR); %plots the raw IR output
hold on;
plot(t,IR_filt,'r'); %plots the filtered IR output
drawnow;
end

fclose(s1);

catch exception
fclose(s1); % always, always want to close s1
throw (exception);
end
 

You might also like