Filter Design by Pole-Zero Placement

by

H. Joel Trussell
Dept. of Electrical and Computer Engineering
North Carolina State University
Raleigh, NC  27695-7911

e-mail:  hjt@ecehjt.ncsu.edu

Initialization

zeros = {}; poles = {};

plotRoots[ roots_, text_ ] :=
	Graphics[ Map[ Text[text, #]&, roots ] ]

unitcircle = Graphics[ Circle[{0,0}, 1], AspectRatio -> 1 ];

complexRoots[ roots_] := Block[{newroots,k,theroot },
	newroots = {};
	For [k=1,k<=Length[roots],k++,
		If [Abs[roots[[k,2]]] < 0.05,
			newroots = Append[ newroots, roots[[k,1]] ],
			(* else *)
			theroot = roots[[k,1]]+I*roots[[k,2]];
			newroots = Append[ newroots, theroot ];
			newroots = Append[ newroots, Conjugate[theroot] ];
			]
	];
	Return[newroots]]

plotPoleZero[poles_,zeros_] := Block[{temp,PlotPZ },
	temp =Transpose[{Re[poles],Im[poles]}];
	polePlot = plotRoots[ temp, "X" ];
	temp =Transpose[{Re[zeros],Im[zeros]}];
	zeroPlot = plotRoots[ temp, "O" ];
	PlotPZ = Show[ unitcircle, polePlot, zeroPlot,
      AxesLabel -> { "Re", "Im" }, Axes -> True,
      PlotLabel -> "Poles/Zeros",DisplayFunction->Identity];
    Return[PlotPZ];
   ]
	
PlotPairs[x_,y_] := Transpose[{x,y}];
FreqAxis := Table[i*Pi/128,{i,0,128}];

Motivation and Guidelines

The purpose of this exercise  is to give the student insight into the relation between the physical location of poles and zeros in the Z-plane and the frequency response of the system represented by those poles and zeros.

Pole-Zero Plot

Recall that π on the unit circle corresponds to the Nyquist frequency for a sampled signal. For the cases considered in this notebook, we will describe frequencies in terms of their normalized values between -π and π.

Show[unitcircle, AxesLabel -> { "Re", "Im" }, Axes -> True]

Now, use the mouse to place poles on the graph. Click the left button once to bring up the frame around the graph. Hold down the command key, 
position the crosshairs and click the left mouse button for each pole. When you have entered all of the desired poles hit <Command>-c to copy the pole list; position the cursor on the line indicated below and hit <Command>-v to paste the list as an argument for the roundRoots function.  Execute the following command to produce a list of  conjugate poles and round small imaginary parts to zero. This assume that the  user wished to put the pole on the real axis but was a bit sloppy.

poles = complexRoots[
(* put pole list on the line below *)
{{0.838172, 0.456409}, {0.511204, 0.599458}, 
{0.398809, 0.885555}}
]
Show[plotPoleZero[poles, zeros],DisplayFunction :> $DisplayFunction]

Now, use the mouse to place zeros on the graph that contains the poles. You may want to use the poles as reference points for the placement of the zeros. Copy and paste the points from the graph as before.

zeros = complexRoots[
(* put zero list on the line below, delete any points left *)
(* from previous runs of this program *)
{{0.951154, 0.197886}, {0.227752, 0.937186}, 
{-0.559245, 0.627157}, {-0.885173, 0.142239}}]
Show[plotPoleZero[poles, zeros],DisplayFunction :> $DisplayFunction]

Now, to obtain the frequency response evaluate the following

Compute Frequency Response

The frequecy response of the filter is obtained by evaluating the rational polynomial at points around the unit circle. This is computed efficiently by using the Fast Fourier Transform. Expand the numerator and denominator by multiplying the terms (1 - pk z-1). The polynomials in z evaluated at 256 points on the unit circle can be computed efficiently by taking the FFT of a sequence of the polynomial coefficients which has been padded with zeros to a length of 256. Division of the FFTs yields the frequency response. We plot the magnitude response in dB and amplitude as well as the phase response.

numerator =  Expand[
	Product[1 - zeros[[k]]*z,{k,Length[zeros]}]];
ncoeff = Table[
	Re[Coefficient[numerator,z^k]],{k,0,Length[zeros]}];
fncoeff = Fourier[
	Join[ncoeff,Table[0,{k,256-Length[ncoeff]}]]];
denominator =  Expand[
	Product[1 - poles[[k]]*z,{k,Length[poles]}]];
dcoeff = Table[
	Re[Coefficient[denominator,z^k]],{k,0,Length[poles]}];
fdcoeff = Fourier[
	Join[dcoeff,Table[0,{k,256-Length[dcoeff]}]]];
freqResponse = 
	N[fncoeff/fdcoeff]; (* Compute Frequency Response *)
magResponse = 
	Abs[freqResponse];  (* Compute Magnitude Response *)
maxMag = 
	Max[magResponse]; (* Find Maximum of Magnitude Response *)
NmagResponse = 
	magResponse/maxMag; (* Normalize Magnitude Response *)
dbmagResponse = 
	10 Log[10,NmagResponse]; (* Magnitude Response in dB *)
phaseResponse = Arg[freqResponse];

Plot Frequency Response

Now Plot the magnitude response  in both absolute and decibels, the phase response along with the pole-zero plot. If you get a very small plot, you can enlarge it by clicking on the plot to bring up the frame, then positioning the cursor at the lower right hand corner and dragging the corner to a larger position.

Show[ GraphicsArray[{ {
  Plotmag = ListPlot[
  	PlotPairs[FreqAxis,Take[NmagResponse,129]],
    PlotJoined->True,
	PlotLabel -> "Magnitude Response (Absolute)",
	DisplayFunction->Identity,
	PlotRange->All],
  Plotdbmag = ListPlot[
  	PlotPairs[FreqAxis,Take[dbmagResponse,129]],
    PlotJoined->True,
	PlotLabel -> "Magnitude Response (dB)",
	AxesOrigin -> {0,Min[Take[dbmagResponse,129]]},
	DisplayFunction->Identity]},{
  Plotarg = ListPlot[
  	PlotPairs[FreqAxis,Take[phaseResponse,129]],
    PlotJoined->True,
	PlotLabel -> "Phase Response",
	DisplayFunction->Identity],
  PlotPZ = plotPoleZero[poles,zeros]}}],
  	DisplayFunction :> $DisplayFunction
]

Student Exercises

Now, return to the Pole-Zero plot and put in poles and zeros which will yield, lowpass, highpass, and bandstop filters. 

It is often desired to attenuate a single frequency in a signal, for example, eliminate 60 cycle hum. This type filter is called a notch filter. The desired filter response is flat except for a notch at the desired frequency. To eliminate the frequency, it is obvious that a zero should be placed at that frequency. To get the flat response a pole (or poles) is needed. Using your knowledge of the relation between the magnitude response and the geometry of the pole-zero positions to determine the placement of the pole(s) to get a flat response at all other frequencies except the one we wish to attenuate.