Your SlideShare is downloading. ×
Control Systems Using Matlab
Control Systems Using Matlab
Control Systems Using Matlab
Control Systems Using Matlab
Control Systems Using Matlab
Control Systems Using Matlab
Control Systems Using Matlab
Control Systems Using Matlab
Control Systems Using Matlab
Control Systems Using Matlab
Control Systems Using Matlab
Control Systems Using Matlab
Control Systems Using Matlab
Control Systems Using Matlab
Control Systems Using Matlab
Control Systems Using Matlab
Control Systems Using Matlab
Control Systems Using Matlab
Control Systems Using Matlab
Control Systems Using Matlab
Control Systems Using Matlab
Control Systems Using Matlab
Control Systems Using Matlab
Control Systems Using Matlab
Control Systems Using Matlab
Control Systems Using Matlab
Control Systems Using Matlab
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Control Systems Using Matlab

247

Published on

Published in: Education, Technology, Business
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
247
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
20
Comments
0
Likes
0
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. CONTROL SYSTEM USING MATLAB Our online Tutors are available 24*7 to provide Help with Control System Homework/Assignment or a long term Graduate/Undergraduate Control System Project. Our Tutors being experienced and proficient in Control System ensure to provide high quality Control System Homework Help. Upload your Control System Assignment at ‘Submit Your Assignment’ button or email it to info@assignmentpedia.com. You can use our ‘Live Chat’ option to schedule an Online Tutoring session with our Control System Tutors. GUI FOR ASYMPTOTIC BODE PLOTS A tool for generating piecewise linear asymptotic Bode diagrams. BodePlotGui(varargin) function varargout = BodePlotGui(varargin) % BODEPLOTGUI Application M-file for BodePlotGui.fig % FIG = BODEPLOTGUI launch BodePlotGui GUI. % BODEPLOTGUI('callback_name', ...) invoke the named callback. % Last Modified by GUIDE v2.5 18-Oct-2011 14:11:08 %Written by Erik Cheever (Copyright 2002) %Contact: erik_cheever@swarthmore.edu % Erik Cheever % Dept. of Engineering % Swarthmore College % 500 College Avenue % Swarthmore, PA 19081 USA %This function acts as a switchyard for several callbacks. It also intializes %the variables used by the GUI. Note that all variables are initialized here to %default values. A brief description of each variable is included. if (nargin == 0) || (isa(varargin{1},'tf')) %If no arguments, or first fig = openfig(mfilename,'new'); handles = guihandles(fig); %Get handles structure. initBodePlotGui(handles); handles=guidata(handles.AsymBodePlot); %Reload handles after function call. if nargout > 0 %If output argument is used, set it to figure. varargout{1} = fig; end if ((nargin~=0) && (isa(varargin{1},'tf'))), %Transfer function chosen. handles.Sys=varargin{1}; %The variable Sys is the transfer function. doBodeGUI(handles);
  • 2. end elseif ischar(varargin{1}) % INVOKE NAMED SUBFUNCTION OR CALLBACK try [varargout{1:nargout}] = feval(varargin{:}); % FEVAL switchyard catch disp(lasterr); end end end % ------------------End of function BodePlotGui ---------------------- function initBodePlotGui(handles) handles.IncludeString=[]; %An array of strings representing terms to include in the plot. handles.ExcludeString=[]; %An array of strings representing terms to exclude from plot. handles.IncElem=[]; %An array of indices of terms corresponding to their % location in the IncludeString array. handles.ExcElem=[]; %An array of indices of terms corresponding to their % location in the ExcludeString array. handles.FirstPlot=1; %This term is 1 the first time a plot is made. This lets % Matlab do the original autoscaling. The scales are then % saved and reused. handles.MagLims=[]; %The limits on the magnitude plot determined by MatLab autoscaling. handles.PhaseLims=[]; %The limits on the phase plot determined by MatLab autoscaling. handles.LnWdth=2; set(handles.LineWidth,'String',num2str(handles.LnWdth)); %Set the color of lines used in gray scale. The plotting functions %cycle through these colors (and then cycle through the linestyles). handles.Gray=[0.75 0.75 0.75; 0.5 0.5 0.5; 0.25 0.25 0.25]; handles.GrayZero=[0.9 0.9 0.9]; %This is the color used for the zero reference. %Set the color of lines used in color plots. The plotting functions %cycle through these colors (and then cycle through the linestyles). handles.Color=[0 1 1; 0 0 1; 0 1 0; 1 0 0; 1 0 1;1 0.52 0.40]; handles.ColorZero=[1 1 0]; %Yellow, this is the color used for the zero reference. %Sets order of linestyles used. handles.linestyle={':','--','-.'}; %This sets the default scheme to color (GUI can set them to gray scale). handles.colors=handles.Color; handles.zrefColor=handles.ColorZero; handles.exactColor=[0 0 0]; %Black handles.Sys=[]; handles.SysInc=[];
  • 3. handles.Terms=[]; %The structure "Term" has three elements. % type: this can be any of the 7 types listed below. % 1) The multiplicative constant. % 2) Real poles % 3) Real zeros % 4) Complex poles % 5) Complex zeros % 6) Poles at the origin % 7) Zeros at the origin % value: this is the location of the pole or zero (or in the case % of the multiplicative constant, its value). % multiplicity: this gives the multiplicity of the pole or zero. It has % no meaning in the case of the multiplicative constant. %The variable "Acc" is a relative accuracy used to determine whether or not %two poles (or zeros) are the same. Because Matlab uses an approximate %technique to find roots of an equation, it is likely to give slightly %different locations to identical roots. handles.Acc=1E-3; set(handles.TransferFunctionText,'String',... {' ','No transfer function chosen',' '}); guidata(handles.AsymBodePlot, handles); %save changes to handles. loadSystems(handles); handles=guidata(handles.AsymBodePlot); %Reload handles after function call. guidata(handles.AsymBodePlot, handles); %save changes to handles. end function simpleTF = makeSimple(origTF) simpleTF=minreal(origTF); %Get minimum realization. % Get numerator and denominator of two realizations. If their % lengths are unequal, it means that there were poles and zeros that % cancelled. [n1,d1]=tfdata(simpleTF,'v'); [n2,d2]=tfdata(origTF,'v'); if (length(n1)~=length(n2)), disp(' '); disp(' '); disp(' '); disp('************Warning******************'); disp('Original transfer function was:'); origTF disp('Some poles and zeros were equal. After cancellation:'); simpleTF disp('The simplified transfer function is the one that will be used.'); disp('*************************************'); disp(' ');
  • 4. beep; waitfor(warndlg('System has poles and zeros that cancel. See Command Window for caveats.')); end end function doBodeGUI(handles) handles.Sys=makeSimple(handles.Sys); handles.SysInc=handles.Sys; %The variable sysInc is that part of the transfer % function that will be plotted (with no poles or zeros excluded). Start with % it equal to Sys. This variable is modified in BodePlotSys %The function BodePlotTerms separates the transfer function into its consituent parts. % The variable DoQuit will come back as non-zero if there was a problem. DoQuit=BodePlotTerms(handles); handles=guidata(handles.AsymBodePlot); %Reload handles after function call. %if DoQuit is zero, there were no problems and we may continue. if ~DoQuit, BodePlotter(handles); %Make plot handles=guidata(handles.AsymBodePlot); %Reload handles after function call. %DoQuit was non-zero, so there was a problem. Quit program. else CloseButton_Callback(fig,'',handles,''); end end %| ABOUT CALLBACKS: %| GUIDE automatically appends subfunction prototypes to this file, and %| sets objects' callback properties to call them through the FEVAL %| switchyard above. This comment describes that mechanism. %| %| Each callback subfunction declaration has the following form: %| <SUBFUNCTION_NAME>(H, EVENTDATA, HANDLES, VARARGIN) %| %| The subfunction name is composed using the object's Tag and the %| callback type separated by '_', e.g. 'slider2_Callback', %| 'figure1_CloseRequestFcn', 'axis1_ButtondownFcn'. %| %| H is the callback object's handle (obtained using GCBO). %| %| EVENTDATA is empty, but reserved for future use. %| %| HANDLES is a structure containing handles of components in GUI using %| tags as fieldnames, e.g. handles.figure1, handles.slider2. This %| structure is created at GUI startup using GUIHANDLES and stored in %| the figure's application data using GUIDATA. A copy of the structure %| is passed to each callback. You can store additional information in %| this structure at GUI startup, and you can change the structure %| during callbacks. Call guidata(h, handles) after changing your
  • 5. %| copy to replace the stored original so that subsequent callbacks see %| the updates. Type "help guihandles" and "help guidata" for more %| information. %| %| VARARGIN contains any extra arguments you have passed to the %| callback. Specify the extra arguments by editing the callback %| property in the inspector. By default, GUIDE sets the property to: %| <MFILENAME>('<SUBFUNCTION_NAME>', gcbo, [], guidata(gcbo)) %| Add any extra arguments after the last argument, before the final %| closing parenthesis. % -------------------------------------------------------------------- function varargout = IncludedElements_Callback(~, ~, handles, varargin) % Stub for Callback of the uicontrol handles.IncludedElements. % If a term in the "Included Elements" box is clicked, this callback is invoked. %Get index of element in box that is chosen.%If the index corresponds to one of the terms of the transfer function, deal with it. i=get(handles.IncludedElements,'Value'); % The alternative is that it corresponds to another string in the box (there is a blank % line, a line with dashes "----" and a line instructing the user to click on an element % to include it). if i<=length(handles.IncElem) TermsInd=handles.IncElem(i); %Get the index of the included element. handles.Terms(TermsInd).display=0; %Set display to 0 (to exclude it) guidata(handles.AsymBodePlot, handles); %save changes to handles. BodePlotter(handles); %Plot the Transfer function. handles=guidata(handles.AsymBodePlot); %Reload handles after function call. end end % ------------------End of function IncludedElements_Callback -------- % -------------------------------------------------------------------- function varargout = ExcludedElements_Callback(~, ~, handles, varargin) % Callback of the uicontrol handles.ExcludedElements. % If a term in the "Excluded Elements" box is clicked, this callback is invoked. i=get(handles.ExcludedElements,'Value'); %Get index of element in box that is chosen. %If the index corresponds to one of the terms of the transfer function, deal with it. % The alternative is that it corresponds to another string in the box (there is a blank % line, a line with dashes "----" and a line instructing the user to click on an element % to exclude it). if i<=length(handles.ExcElem) TermsInd=handles.ExcElem(i); %Get the index of the excluded element. handles.Terms(TermsInd).display=1; %Set display to 1 (to include it) guidata(handles.AsymBodePlot, handles); %save changes to handles. BodePlotter(handles); %Plot the Transfer function. handles=guidata(handles.AsymBodePlot); %Reload handles after function call. end
  • 6. end % ------------------End of function ExcludedElements_Callback -------- % -------------------------------------------------------------------- function varargout = CloseButton_Callback(~, ~, handles, varargin) % Callback for the uicontrol handles.CloseButton. %This function closes the window, and displays a message. disp(' '); disp('Asymptotic Bode Plotter closed.'); disp(' '); disp(' '); delete(handles.AsymBodePlot); end % ------------------End of function CloseButton_Callback ------------- % -------------------------------------------------------------------- function DoQuit=BodePlotTerms(handles) %This function takes a system and splits it up into terms that are plotted %individually when making a Bode plot by hand (it finds %1) The multiplicative constant. %2) All real poles %3) All real zeros %4) All complex poles %5) All complex zeros %6) All poles at the origin %7) All zeros at the origin % %In addition to finding the poles and zeros, it determines their multiplicity. %If two poles or zeros are very close they are determined to be the same pole %or zero. sys=handles.Sys; Acc=handles.Acc; %Relative accuracy. [z,p,k]=zpkdata(sys,'v'); %Get pole and zero data. %Find gain term. [n,d]=tfdata(sys,'v'); k=n(max(find(n~=0)))/d(max(find(d~=0))); term(1).type='Constant'; term(1).value=k; term(1).multiplicity=1; %Get all poles. j=length(term); for i=1:length(p), term(j+i).value=p(i); term(j+i).multiplicity=1; term(j+i).type='Pole'; end
  • 7. %Get all zeros. j=length(term); for i=1:length(z), term(j+i).value=z(i); term(j+i).multiplicity=1; term(j+i).type='Zero'; end %Check for multiplicity for i=2:length(term), for k=(i+1):length(term), %Handle pole or zero at origin as special case. if (term(i).value==0), %Multiple pole or zero at origin. if (term(k).value==0), term(i).multiplicity=term(i).multiplicity+term(k).multiplicity; %Set multiplicity of kth term to 0 to signify that it has been % subsumed by term(i) (by increasing the ith term's multiplicity). term(k).multiplicity=0; end %We know term is not at origin, so check for (approximate) equality % Since we know this term is not at origin, we can divide by value. elseif (abs((term(i).value-term(k).value)/term(i).value) < Acc), term(i).multiplicity=term(i).multiplicity+term(k).multiplicity; %Set multiplicity of kth term to 0 to signify that it has been % subsumed by term(i) (by increasing the ith term's multiplicity). term(k).multiplicity=0; end end end %Check for location of poles and zeros (and remove complex conjugates). i=2; while (i<=length(term)), %If root is at origin, handle it separately if (term(i).value==0), term(i).type=['Origin' term(i).type]; %If imaginary part is sufficiently small... elseif (abs(imag(term(i).value)/term(i).value)<Acc), term(i).type=['Real' term(i).type]; %...Add "Real" to type term(i).value=real(term(i).value); %...And set imaginary part=0 %If imaginary part is *not* small... else term(i).type=['Complex' term(i).type]; %...Add "Complex" to type term(i+1).multiplicity=0; %...Remove complex conjugate i=i+1; %...And skip conjugate. end i=i+1; %Go to next root. end
  • 8. %Remove all terms with multiplicity 0. j=0; for i=1:length(term), if (term(i).multiplicity~=0) j=j+1; term(j)=term(i); term(j).display=1; end end term=term(1:j); DoQuit=0; %Check for poles or zeros in right half plane, % or on imaginary axis. Poles and zeros at origin are OK. if any(real(p)>0), %Poles in RHP. beep; waitfor(errordlg('System has poles with positive real part, cannot make plot.')); DoQuit=1; return; end if any(real(z)>0), %Zeros in RHP. disp(' '); disp(' '); disp(' '); disp('************Warning******************'); handles.Sys disp('is a nonminimum phase system (zeros in right half plane).'); disp('The standard rules for phase do not apply.'); disp(' '); disp('Also - The plots produced may be different than the Matlab Bode plot'); disp(' by a factor of 360 degrees. So though the graphs don''t look'); disp(' the same, they are equivalent'); disp(' '); disp('Location(s) of zero(s):'); disp(z); disp('*************************************'); disp(' '); beep; waitfor(warndlg('System has zeros with positive real part. See Command Window for caveats.')); end %Check for terms near imaginary axis, or multiple poles or zeros at origin. for i=2:length(term), if (term(i).value~=0), if (abs(real(term(i).value)/term(i).value)<Acc), disp(' '); disp(' '); disp(' ');
  • 9. disp('************Warning******************'); handles.Sys disp('has a pole or zero near, or on, the imaginary axis.'); disp('The plots may be inaccurate near that frequency.') disp(' '); disp('--------'); disp('Pole(s):'); disp(p) disp('--------'); disp('Zero(s):'); disp(z); disp('*************************************'); disp(' '); disp(' '); disp(' '); beep; waitfor(warndlg('System has poles or zeros with real part near zero. See Command Window.')); end elseif (term(i).multiplicity>1), disp(' '); disp(' '); disp(' '); disp('************Warning******************'); handles.Sys disp('has multiple poles or zeros at the origin.'); disp('Components of the phase plot may appear to disagree.'); disp('This is because the phase of a complex number is'); disp('not unique; the phase of -1 could be +180 degrees'); disp('or -180 or +/-540... Likewise the phase of 1/s^2'); disp('could be +180 degrees, or -180 degrees (or +/-540'); disp('Keep this in mind when looking at the phase plots.'); disp('*************************************'); disp(' '); beep; waitfor(warndlg('System has multiple poles or zeros at origin. See Command Window.')); end end handles.Terms=term; guidata(handles.AsymBodePlot, handles); %save changes to handles. end % ------------------End of function BodePlotTerms -------------------- % -------------------------------------------------------------------- function BodePlotter(handles) %Get the constituent terms and the system itself.
  • 10. Terms=handles.Terms; sys=handles.Sys; %Call function to get a system with only included poles and zeros. BodePlotSys(handles); handles=guidata(handles.AsymBodePlot); %Reload handles after function call. %Get systems with included poles and zeros. sysInc=handles.SysInc; %Find min and max freq. MinF=realmax; MaxF=-realmax; for i=2:length(Terms), if Terms(i).value~=0, MinF=min(MinF,abs(Terms(i).value)); MaxF=max(MaxF,abs(Terms(i).value)); end end %If there is exclusively a pole or zero at origin, MinF and MaxF will % not have changed. So set them arbitrarily to be near unity. if MaxF==-realmax, MinF=0.9; MaxF=1.1; end %MinFreq is a bit more than an order of magnitude below lowest break. MinFreq=10^(floor(log10(MinF)-1.01)); %MaxFreq is a bit more than an order of magnitude above highest break. MaxFreq=10^(ceil(log10(MaxF)+1.01)); %Calculate 500 frequency points for plotting. w=logspace(log10(MinFreq),log10(MaxFreq),1000); %%%%%%%%%%%%%%%%%%%% Start Magnitude Plot %%%%%%%%%% axes(handles.MagPlot); cla; %Plot line at 0 dB for reference. semilogx([MinFreq MaxFreq],[0 0],... 'Color',handles.zrefColor,... 'LineWidth',1.5); hold on; %For each term, plot the magnitude accordingly. %The variable mag_a has the combined asymptotic magnitude. mag_a=zeros(size(w)); %The variable peakinds holds the indices at which peaks in underdamped
  • 11. %responses occur. peakinds=[]; for i=1:length(Terms), if Terms(i).display, switch Terms(i).type, case 'Constant', %A constant term is unchanging from beginning to end. f=[MinFreq MaxFreq]; m=20*log10(abs([Terms(i).value Terms(i).value])); semilogx(f,m,... 'LineWidth',handles.LnWdth,... 'LineStyle',GetLineStyle(i,handles),... 'Color',GetLineColor(i,handles)); mag_a=mag_a+interp1(log(f),m,log(w)); %Build up asymptotic approx. case 'RealPole', %A real pole has a single break frequency and then %decreases at 20 dB per decade (Or more if pole is multiple). wo=-Terms(i).value; f=[MinFreq wo MaxFreq]; m=-20*log10([1 1 MaxFreq/wo])*Terms(i).multiplicity; semilogx(f,m,... 'LineWidth',handles.LnWdth,... 'LineStyle',GetLineStyle(i,handles),... 'Color',GetLineColor(i,handles)); mag_a=mag_a+interp1(log(f),m,log(w)); %Build up asymptotic approx. case 'RealZero', %Similar to real pole, but increases instead of decreasing. wo=abs(Terms(i).value); f=[MinFreq wo MaxFreq]; m=20*log10([1 1 MaxFreq/wo])*Terms(i).multiplicity; semilogx(f,m,... 'LineWidth',handles.LnWdth,... 'LineStyle',GetLineStyle(i,handles),... 'Color',GetLineColor(i,handles)); mag_a=mag_a+interp1(log(f),m,log(w)); %Build up asymptotic approx. case 'ComplexPole', %A complex pole has a single break frequency and then %decreases at 40 dB per decade (Or more if pole is multiple). %There is also a peak value whose height and location are %determined by the natural frequency and damping coefficient. %We will plot a circle ('o') at the location of the peak. wn=abs(Terms(i).value); theta=atan(abs(imag(Terms(i).value)/real(Terms(i).value))); zeta=cos(theta); if (zeta < 0.5), %Show peaking if zeta<0.5 peak=2*zeta; f=[MinFreq wn wn wn MaxFreq]; m=-20*log10([1 1 peak 1 (MaxFreq/wn)^2])*Terms(i).multiplicity; semilogx(f,m,...
  • 12. 'LineWidth',handles.LnWdth,... 'LineStyle',GetLineStyle(i,handles),... 'Color',GetLineColor(i,handles)); semilogx(wn,-20*log10(peak),'o','Color',GetLineColor(i,handles)); % Set up for interpolation (w/o peak) f=[MinFreq wn MaxFreq]; m=-20*log10([1 1 (MaxFreq/wn)^2])*Terms(i).multiplicity; mag_a=mag_a+interp1(log(f),m,log(w)); %Build up asymptotic approx. %Find location closest to peak, and adjust its amplitude. index=find(w>=wn,1,'first'); mag_a(index)=mag_a(index)-20*log10(peak); peakinds=[peakinds index]; %Save this index. else f=[MinFreq wn MaxFreq]; m=-20*log10([1 1 (MaxFreq/wn)^2])*Terms(i).multiplicity; semilogx(f,m,... 'LineWidth',handles.LnWdth,... 'LineStyle',GetLineStyle(i,handles),... 'Color',GetLineColor(i,handles)); % Set up for interpolation (w/o peak) mag_a=mag_a+interp1(log(f),m,log(w)); %Build up asymptotic approx. end case 'ComplexZero', %Similar to complex pole, but increases instead of decreasing. wn=abs(Terms(i).value); theta=atan(abs(imag(Terms(i).value)/real(Terms(i).value))); zeta=cos(theta); if (zeta < 0.5), %Show peaking if zeta<0.5 peak=2*zeta; f=[MinFreq wn wn wn MaxFreq]; m=20*log10([1 1 peak 1 (MaxFreq/wn)^2])*Terms(i).multiplicity; semilogx(f,m,... 'LineWidth',handles.LnWdth,... 'LineStyle',GetLineStyle(i,handles),... 'Color',GetLineColor(i,handles)); semilogx(wn,20*log10(peak),'o','Color',GetLineColor(i,handles)); % Set up for interpolation (w/o peak) f=[MinFreq wn MaxFreq]; m=20*log10([1 1 (MaxFreq/wn)^2])*Terms(i).multiplicity; mag_a=mag_a+interp1(log(f),m,log(w)); %Build up asymptotic approx. %Find location closest to peak, and adjust its amplitude. index=find(w>=wn,1,'first'); mag_a(index)=mag_a(index)+20*log10(peak); peakinds=[peakinds index]; %Save this index. else f=[MinFreq wn MaxFreq]; m=20*log10([1 1 (MaxFreq/wn)^2])*Terms(i).multiplicity; semilogx(f,m,... 'LineWidth',handles.LnWdth,...
  • 13. 'LineStyle',GetLineStyle(i,handles),... 'Color',GetLineColor(i,handles)); % Set up for interpolation (w/o peak) mag_a=mag_a+interp1(log(f),m,log(w)); %Build up asymptotic approx. end case 'OriginPole', %A pole at the origin is a monotonically decreasing straigh line. f=[MinFreq MaxFreq]; m=-20*log10([MinFreq MaxFreq])*Terms(i).multiplicity; semilogx(f,m,... 'LineWidth',handles.LnWdth,... 'LineStyle',GetLineStyle(i,handles),... 'Color',GetLineColor(i,handles)); mag_a=mag_a+interp1(log(f),m,log(w)); %Build up asymptotic approx. case 'OriginZero', %Similar to pole at origin, but increases instead of decreasing. f=[MinFreq MaxFreq]; m=20*log10([MinFreq MaxFreq])*Terms(i).multiplicity; semilogx(f,m,... 'LineWidth',handles.LnWdth,... 'LineStyle',GetLineStyle(i,handles),... 'Color',GetLineColor(i,handles)); mag_a=mag_a+interp1(log(f),m,log(w)); %Build up asymptotic approx. end end end %Set the x-axis limits to the minimum and maximum frequency. set(gca,'XLim',[MinFreq MaxFreq]); [mg,ph,w]=bode(sysInc,w); %Calculate the exact bode plot. semilogx(w,20*log10(mg(:)),... 'Color',handles.exactColor,... 'LineWidth',handles.LnWdth/2); %Plot it. if (get(handles.ShowAsymptoticCheckBox,'Value')~=0), semilogx(w,mag_a,... 'Color',handles.exactColor,... 'LineStyle',':',... 'LineWidth',handles.LnWdth); %Plot asymptotic approx. semilogx(w(peakinds),mag_a(peakinds),'o','Color',handles.exactColor); end if handles.FirstPlot, %If this is the first time, let Matlab do autoscaling, but save %the y-axis limits so that they will be unchanged as the plot changes. ylims=get(gca,'YLim')/20; ylims(1)=min(-20,ceil(ylims(1))*20); ylims(2)=max(20,floor(ylims(2))*20); handles.MagLims=ylims;
  • 14. else %If this is not the first time, retrieve the old y-axis limits. ylims=handles.MagLims; end set(gca,'YLim',ylims); set(gca,'YTick',ylims(1):20:ylims(2)); %Make ticks every 20 dB. ylabel('Magnitude - dB'); xlabel('Frequency - omega, rad-sec^{-1}') title('Magnitude Plot','color','b','FontWeight','bold'); if get(handles.GridCheckBox,'Value')==1, grid on end hold off; %%%%%%%%%%%%%%%%%%%% End Magnitude Plot %%%%%%%%%% %%%%%%%%%%%%%%%%%%%% Start Phase Plot %%%%%%%%%% %Much of this section mirrors the previous section and is not commented. %One difference is that phase is calculated explicitly, rather than use %Matlab's "bode" command. Since phase is not unique (you can add or %subtract multiples of 360 degrees) There were sometimes discrepancies %between Matlab's phase calculations and mine axes(handles.PhasePlot); cla; %Plot line at 0 degrees for reference. semilogx([MinFreq MaxFreq],[0 0],... 'Color',handles.zrefColor,... 'LineWidth',1.5); hold on; %The variable phs_a has the combined asymptotic phase. phs_a=zeros(size(w)); for i=1:length(Terms), if Terms(i).display, switch Terms(i).type, case 'Constant', f=[MinFreq MaxFreq]; if Terms(i).value>0, p=[0 0]; else p=[180 180]; end if get(handles.RadianCheckBox,'Value')==1, p=p/180; end semilogx(f,p,... 'LineWidth',handles.LnWdth,...
  • 15. 'LineStyle',GetLineStyle(i,handles),... 'Color',GetLineColor(i,handles)); case 'RealPole', wo=-Terms(i).value; f=[MinFreq wo/10 wo*10 MaxFreq]; p=[0 0 -90 -90]*Terms(i).multiplicity; if get(handles.RadianCheckBox,'Value')==1, p=p/180; end semilogx(f,p,... 'LineWidth',handles.LnWdth,... 'LineStyle',GetLineStyle(i,handles),... 'Color',GetLineColor(i,handles)); case 'RealZero', if Terms(i).value>0, %Non-minimum phase wo=Terms(i).value; %Uncomment the next section to get agreement with Matlab plots. %if Terms(1).value>0, %Choose 0 or 360 to agree with MatLab plots % p=[0 0 0 0]; % (based on sign of constant term). % else % p=[360 360 360 360]; %end p=[0 0 -90 -90]*Terms(i).multiplicity; else %Minimum phase wo=-Terms(i).value; p=[0 0 90 90]*Terms(i).multiplicity; end f=[MinFreq wo/10 wo*10 MaxFreq]; if get(handles.RadianCheckBox,'Value')==1, p=p/180; end semilogx(f,p,... 'LineWidth',handles.LnWdth,... 'LineStyle',GetLineStyle(i,handles),... 'Color',GetLineColor(i,handles)); case 'ComplexPole', wo=abs(Terms(i).value); bf=0.2^zeta; f=[MinFreq wo*bf wo/bf MaxFreq]; p=[0 0 -180 -180]*Terms(i).multiplicity; if get(handles.RadianCheckBox,'Value')==1, p=p/180; end semilogx(f,p,... 'LineWidth',handles.LnWdth,... 'LineStyle',GetLineStyle(i,handles),... 'Color',GetLineColor(i,handles)); case 'ComplexZero',
  • 16. wo=abs(Terms(i).value); bf=0.2^zeta; f=[MinFreq wo*bf wo/bf MaxFreq]; if real(Terms(i).value)>0, %Non-minimum phase p=[0 0 -180 -180]*Terms(i).multiplicity; else p=[0 0 180 180]*Terms(i).multiplicity; end if get(handles.RadianCheckBox,'Value')==1, p=p/180; end semilogx(f,p,... 'LineWidth',handles.LnWdth,... 'LineStyle',GetLineStyle(i,handles),... 'Color',GetLineColor(i,handles)); case 'OriginPole', f=[MinFreq MaxFreq]; p=[-90 -90]*Terms(i).multiplicity; if get(handles.RadianCheckBox,'Value')==1, p=p/180; end semilogx(f,p,... 'LineWidth',handles.LnWdth,... 'LineStyle',GetLineStyle(i,handles),... 'Color',GetLineColor(i,handles)); case 'OriginZero', f=[MinFreq MaxFreq]; p=[90 90]*Terms(i).multiplicity; if get(handles.RadianCheckBox,'Value')==1, p=p/180; end semilogx(f,p,... 'LineWidth',handles.LnWdth,... 'LineStyle',GetLineStyle(i,handles),... 'Color',GetLineColor(i,handles)); end phs_a=phs_a+interp1(log(f),p,log(w)); %Build up asymptotic approx. end end if get(handles.RadianCheckBox,'Value')==1, ph=ph/180; end semilogx(w,ph(:),... 'Color',handles.exactColor,... 'LineWidth',handles.LnWdth/2); %Plot it. if (get(handles.ShowAsymptoticCheckBox,'Value')~=0),
  • 17. % There can be discrepancies between Matlabs calculation of phase and % the quantity "phs_a." This is because phase is not unique (you can % add or subtract multiples of 360 degrees). The next line shifts the % value of phs_a so that phs_a(1)=ph(1). Ensuring they are the same % at the beginning of the plot ensures that they align elsewhere. Note % that if the plots are already aligned (ph(1)=phs_a(1)), that the next % line does nothing. phs_a=phs_a+(ph(1)-phs_a(1)); semilogx(w,phs_a,... 'Color',handles.exactColor,... 'LineStyle',':',... 'LineWidth',handles.LnWdth); %Plot asymptotic approx. end set(gca,'XLim',[MinFreq MaxFreq]); if handles.FirstPlot, ylims=get(gca,'YLim')/45; ylims(1)=ceil(ylims(1)-1)*45; ylims(2)=floor(ylims(2)+1)*45; handles.DPhaseLims=ylims; %Find phase limits in degrees handles.RPhaseLims=ylims/180; %Find phase limits in radians/pi else if get(handles.RadianCheckBox,'Value')==1, ylims=handles.RPhaseLims; else ylims=handles.DPhaseLims; end end if get(handles.RadianCheckBox,'Value')==1, set(gca,'YLim',ylims); set(gca,'YTick',ylims(1):0.25:ylims(2)) ylabel('Phase - radians/pi'); else set(gca,'YLim',ylims); set(gca,'YTick',ylims(1):45:ylims(2)) ylabel('Phase - degrees'); end xlabel('Frequency - omega, rad-sec^{-1}'); title('Phase Plot','color','b','FontWeight','bold'); if get(handles.GridCheckBox,'Value')==1, grid on end hold off; %%%%%%%%%%%%%%%%%%%% End Phase Plot %%%%%%%%%% BodePlotDispTF(handles); %Display the transfer function BodePlotLegend(handles); %Display the legend.
  • 18. handles=guidata(handles.AsymBodePlot); %Reload handles after function call. %Set first plot to zero (so Matlab won't autoscale on subsequent calls). handles.FirstPlot=0; guidata(handles.AsymBodePlot, handles); %save changes to handles. end % ----------------- End of function BodePlotter ---------------------- % -------------------------------------------------------------------- function BodePlotSys(handles) %This function makes up a transfer function of all the terms that are not in %the "Excluded Elements" box in the GUI. Terms=handles.Terms; %Get all terms from original transfer function. p=[]; %Start with no poles, or zeros, and a constant of 1 z=[]; k=1; for i=1:length(Terms), %For each term. %If the term is not in "Excluded Elements". then we want to display it. if Terms(i).display, switch Terms(i).type, case 'Constant', k=Terms(i).value; %This is the constant. case 'RealPole', for j=1:Terms(i).multiplicity, p=[p Terms(i).value]; %Add poles. end case 'RealZero', for j=1:Terms(i).multiplicity, z=[z Terms(i).value]; %Add zeros. end case 'ComplexPole', for j=1:Terms(i).multiplicity, p=[p Terms(i).value]; %Add poles. p=[p conj(Terms(i).value)]; end case 'ComplexZero', for j=1:Terms(i).multiplicity, z=[z Terms(i).value]; %Add zeros. z=[z conj(Terms(i).value)]; end case 'OriginPole', for j=1:Terms(i).multiplicity, p=[p 0]; %Add poles. end case 'OriginZero',
  • 19. for j=1:Terms(i).multiplicity, z=[z 0]; %Add zeros. end end end end %Determine multiplicative constant in standard Bode Plot form. for i=1:length(p), if p(i)~=0 k=-k*p(i); end end for i=1:length(z), if z(i)~=0 k=-k/z(i); end end %If poles and/or zeros were complex conjugate pairs, there may be %some residual imaginary part due to finite precision. Remove it. k=real(k); handles.SysInc=zpk(z,p,k); guidata(handles.AsymBodePlot, handles); %save changes to handles. end % ------------------End of function BodePlotSys ---------------------- % -------------------------------------------------------------------- function BodePlotDispTF(handles) % This function displays a tranfer function that is a helper function for the % BodePlotGui routine. It takes the transfer function of the numerator and % splits it into three lines so that it can be displayed nicely. For example: % " s + 1" % "H(s) = ---------------" % " s^2 + 2 s + 1" % % The numerator string is in the variable nStr, % the second line is in divStr, % and the denominator string is in dStr. % Get numerator and denominator. [n,d]=tfdata(handles.SysInc,'v'); % Get string representations of numerator and denominator nStr=poly2str(n,'s'); dStr=poly2str(d,'s'); % Find length of strings.
  • 20. LnStr=length(nStr); LdStr=length(dStr); if LnStr>LdStr, %the numerator is longer than denominator string, so pad denominator. n=LnStr; %n is the length of the longer string. nStr=[' ' nStr]; %add spaces for characters at beginning of divStr. dStr=[' ' blanks(floor((LnStr-LdStr)/2)) dStr]; %pad denominator. else %the demoninator is longer than numerator, pad numerator. n=LdStr; nStr=[' ' blanks(floor((LdStr-LnStr)/2)) nStr]; dStr=[' ' dStr]; end divStr=[]; for i=1:n, divStr=[divStr '-']; end divStr=['H(s) = ' divStr]; set(handles.TransferFunctionText,'String',strvcat(nStr,divStr,dStr)); %Change type font and size. set(handles.TransferFunctionText,'FontName','Courier New') %set(handles.TransferFunctionText,'FontSize',10) guidata(handles.AsymBodePlot, handles); %save changes to handles. end % ------------------End of function BodePlotDispTF ------------------- % -------------------------------------------------------------------- function BodePlotLegend(handles) %This function creates the legends for the Bode plot being displayed. %It also makes four changes to the "handles" structure. % 1) It updates the array "IncElem" that holds the indices that determine % which elements are included in the Bode plot. % 2) It updates the sring array "IncStr" that hold the description of % each included elements. % 3) Updates ExcElem that holds indices of excluded elements. % 4) Updates ExcStr that hold descriptions of excluded elements. %Load the terms and the plotting strings into local variables for convenience. Terms=handles.Terms; axes(handles.LegendPlot); %Set axes to the legend widow, cla; % and clear it. Xleg=[0 0.1]; %Xleg holds start and end of line segment for legend.
  • 21. XlegText=0.125; %XlegText is location of text. FntSz=8; %Font Size of text. y=1-1/(length(Terms)+6); %Vertical location of first text item plot(Xleg,[y y],... 'Color',handles.exactColor,... 'LineWidth',handles.LnWdth/2); %Plot line for legend. text(XlegText,y,'Exact Bode Plot','FontSize',FntSz); %Place text hold on; if (get(handles.ShowAsymptoticCheckBox,'Value')~=0), y=1-2/(length(Terms)+6); %Vertical location of second item plot(Xleg,[y y],... 'Color',handles.exactColor,... 'LineStyle',':',... 'LineWidth',handles.LnWdth); %Plot line for legend. text(XlegText,y,'Asymptotic Plot','FontSize',FntSz); %Place text end y=1-3/(length(Terms)+6); %Vertical location of third item. plot(Xleg,[y y],... %Line. 'Color',handles.zrefColor,... 'LineWidth',2); text(XlegText,y,'Zero Value (for reference only)','FontSize',FntSz); %Text. IncElem=[]; %The indices of elements to be included in plot. ExcElem=[]; %The indices of elements to be excluded from plot. IncStr=''; %An array of strings describing included elements. ExcStr=''; %An array of strings describing excluded elements. %These variables are used as local counters later. Here they are initialized. i1=1; i2=1; for i=1:length(Terms), %For each term, %Tv is a local variable representing the pole location. It is used solely % for convenience. Tv=Terms(i).value; %Tm is a local variable representing the pole multiplicity. It is used solely % for convenience. Tm=Terms(i).multiplicity; %S2 is a blank string to be added to later in the loop. S2=''; %The next section of code ("switch" statement) plus a few lines, creates %a string that describes the pole or zero, its location, muliplicity... %The variable "DescStr" hold a Descriptive String for the pole or zero. The %string "S2" is a Second String that holds additional information (if needed)
  • 22. switch Terms(i).type, case 'Constant', %If the term is a consant, print its value in a string. DescStr=sprintf('Constant = %0.2g (%0.2g dB)',Tv,20*log10(abs(Tv))); if Tv>=0, DescStr=[DescStr ' phi=0']; else DescStr=[DescStr ' phi=180 (pi/2)']; end; case 'RealPole', %If the term is a real pole, print its value in string. DescStr=sprintf('Real Pole at %0.2g',Tv); case 'RealZero', %If the term is a real zero, print its value in string. DescStr=sprintf('Real Zero at %0.2g',Tv); if real(Tv)>0, DescStr=[DescStr ' RHP (Non-min phase)']; end; case 'ComplexPole', %If the term is a complex pole, print its value in string. %However, do this in terms of natural frequency and damping, as %well as the actual location of the pole (in S2). wn=abs(Tv); theta=atan(abs(imag(Tv)/real(Tv))); zeta=cos(theta); DescStr=sprintf('Complex Pole at wn=%0.2g, zeta=%0.2g',wn,zeta); if (zeta < 0.5), %peaking only if zeta<0.5 S2=sprintf('(%0.2g +/- %0.2gj) Circle shows peak height.',real(Tv),imag(Tv)); else S2=sprintf('(%0.2g +/- %0.2gj) (no peaking shown, zeta>0.5)',real(Tv),imag(Tv)); end case 'ComplexZero', %If the term is a complex zero, print its value in string. %However, do this in terms of natural frequency and damping, as %well as the actual location of the zero (in S2). %Also note if it is a non-minimum phase zero. wn=abs(Tv); theta=atan(abs(imag(Tv)/real(Tv))); zeta=cos(theta); DescStr=sprintf('Complex Zero at wn=%0.2g, zeta=%0.2g',wn,zeta); if real(Tv)>0, DescStr=[DescStr ' (RHP, Non-min phase)']; end; if (zeta < 0.5), %peaking only if zeta<0.5 S2=sprintf('(%0.2g +/- %0.2gj) Circle shows peak height.',real(Tv),imag(Tv)); else S2=sprintf('(%0.2g +/- %0.2gj) (no peaking shown, zeta>0.5)',real(Tv),imag(Tv)); end case 'OriginPole',
  • 23. %If pole is at origin, not this. DescStr=sprintf('Pole at origin'); case 'OriginZero', %If zero is at origin, not this. DescStr=sprintf('Zero at origin'); end %If multiplicity is greater than one, not this as well. if Tm>1, DescStr=[DescStr sprintf(', mult=%d',Tm)]; end %At this point we have a string (in "DescStr" and "S2"). if Terms(i).display, %If the term is to be included in plot.... IncStr=strvcat(IncStr,DescStr); %Add the Desriptive String to IncStr IncElem(i1)=i; %Add the appropriate index to the Included Elements list. i1=i1+1; %Increment the index counter y=1-(i1+2)/(length(Terms)+6); %Calculate the vertical position. plot(Xleg,[y y],... %Plot the line. 'LineWidth',handles.LnWdth,... 'LineStyle',GetLineStyle(i,handles),... 'Color',GetLineColor(i,handles)); text(XlegText,y,strvcat(DescStr,S2),'FontSize',FntSz); %Add the text. else %The term is *not* to be included in plot, so... ExcStr=strvcat(ExcStr,DescStr); %Add its Desriptive String to ExcStr ExcElem(i2)=i; %Add the appropriate index to the Excluded Elements list. i2=i2+1; %Increment the index counter. end end hold off; %Get rid of ticks around plot. axis([0 1 0 1]); set(gca,'Xtick',[]); set(gca,'Ytick',[]); %At this point the legend is completed. Next we will make up the strings %for the boxes that separately list included and excluded elements. IncStr=strvcat(IncStr,' '); %Add a blank line to IncStr. IncStr=strvcat(IncStr,'-------'); %Add a series of dashes. %If there are any included elements, we can click on box to exclude it. if i1~=1 IncStr=strvcat(IncStr,'Select element to exclude from plot'); end ExcStr=strvcat(ExcStr,' '); %Add a blank line to ExcStr ExcStr=strvcat(ExcStr,'-------'); %Add a series of dashes. %If there are any excluded elements, we can click on box to include it. if i2~=1 ExcStr=strvcat(ExcStr,'Select element to include in plot');
  • 24. end %Set the strings for included and excluded elements. set(handles.IncludedElements,'String',IncStr); set(handles.ExcludedElements,'String',ExcStr); %Change the arrays holding included and excluded elements in the handles array. handles.IncElem=IncElem; handles.ExcElem=ExcElem; guidata(handles.AsymBodePlot, handles); %save changes to handles. end % ------------------End of function BodePlotLegend -------- % -------------------------------------------------------------------- % --- Executes during object creation, after setting all properties. function LineWidth_CreateFcn(hObject, ~, ~) % hObject handle to LineWidth (see GCBO) % eventdata reserved - to be defined in a future version of MATLAB % handles empty - handles not created until after all CreateFcns called if ispc set(hObject,'BackgroundColor','white'); else set(hObject,'BackgroundColor',get(0,'defaultUicontrolBackgroundColor')); end end % ------------------End of function BodePlotLegend -------- % -------------------------------------------------------------------- % Set the width of the lines used in plots. function LineWidth_Callback(~, ~, handles) % hObject handle to LineWidth (see GCBO) % eventdata reserved - to be defined in a future version of MATLAB % handles structure with handles and user data (see GUIDATA) handles.LnWdth=str2num(get(handles.LineWidth,'String')); guidata(handles.AsymBodePlot, handles); %save changes to handles. BodePlotter(handles); %Plot the Transfer function. handles=guidata(handles.AsymBodePlot); %Reload handles after function call. end % ------------------End of function BodePlotLegend -------- % -------------------------------------------------------------------- % Determines the line color of the ith plot. function linecolor=GetLineColor(i,handles) numColors=size(handles.colors,1); %Cycle through colors by using mod operator.
  • 25. linecolor=handles.colors(mod(i-1,numColors)+1,:); end % ------------------End of function GetLineColor -------- % -------------------------------------------------------------------- % Determines the line style of the ith plot. function linestyle=GetLineStyle(i,handles) numColors=size(handles.colors,1); numLnStl=size(handles.linestyle,2); %Cycle through line styles, incrementing after all colors are used. linestyle=handles.linestyle{mod(ceil(i/numColors)-1,numLnStl)+1}; end % ------------------End of function GetLineStyle -------- % -------------------------------------------------------------------- % --- Executes on button press in GrayCheckBox. % This function sets the sequence of colors used in plotting to gray scales. function GrayCheckBox_Callback(~, ~, handles) if get(handles.GrayCheckBox,'Value')==1, %If button is not set, handles.colors=handles.Gray; %and set colors to gray scale handles.zrefColor=handles.GrayZero; else handles.colors=handles.Color; %and set colors to RGB handles.zrefColor=handles.ColorZero; end guidata(handles.AsymBodePlot, handles); %save changes to handles. BodePlotter(handles); %Plot the Transfer function. handles=guidata(handles.AsymBodePlot); %Reload handles after function call. end % ------------------End of function BodePlotLegend -------- % --- Executes on button press in GridCheckBox. function GridCheckBox_Callback(~, ~, handles) BodePlotter(handles); %Plot the Transfer function. end % --- Executes on button press in RadianCheckBox. function RadianCheckBox_Callback(~, ~, handles) BodePlotter(handles); %Plot the Transfer function. end % --- Executes on button press in WebButton. function WebButton_Callback(~, ~, ~) web('http://lpsa.swarthmore.edu/Bode/Bode.html','-browser') end
  • 26. % --- Executes on button press in ShowAsymptoticCheckBox. function ShowAsymptoticCheckBox_Callback(~, ~, handles) BodePlotter(handles); %Plot the Transfer function. end % --- Executes on button press in limitButton. function limitButton_Callback(~, ~, ~) s{1}='Restrictions on systems:'; s{2}=' 1) SISO (Single Input Single Output);'; s{3}=' 2) Proper systems (order of num <= order of den);'; s{4}=' 4) System must be a transfer function (i.e., not state space...)'; s{5}=' 5) Time delays are ignored.'; helpdlg(s,'Valid Systems'); end % --- Executes on selection change in popupSystems. function popupSystems_Callback(hObject, ~, handles) i=get(hObject,'Value'); if i ~= 1, %If this is not the "User Systems" choice if i==2, %This is the refresh choice loadSystems(handles); handles=guidata(handles.AsymBodePlot); %Reload handles after function call. else %THis is a valid choice, pick transfer function. initBodePlotGui(handles); handles=guidata(handles.AsymBodePlot); %Reload handles after function call. handles.Sys=handles.WorkSpaceTFs{i}; doBodeGUI(handles); handles=guidata(handles.AsymBodePlot); %Reload handles after function call. end end guidata(hObject, handles); end % --- Executes during object creation, after setting all properties. function popupSystems_CreateFcn(hObject, ~, ~) % hObject handle to popupSystems (see GCBO) % eventdata reserved - to be defined in a future version of MATLAB % handles empty - handles not created until after all CreateFcns called % Hint: popupmenu controls usually have a white background on Windows. % See ISPC and COMPUTER. if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) set(hObject,'BackgroundColor','white'); end end function loadSystems(handles) [v_name, v_tf]=getBaseTFs;
  • 27. set(handles.popupSystems,'String',v_name); handles.WorkSpaceTFs=v_tf; guidata(handles.AsymBodePlot, handles); %save changes to handles. end function [varName, varTF]=getBaseTFs % Find all valid transfer functions in workspace s=evalin('base','whos(''*'')'); tfs=strvcat(s.class); %x=class of all variable tfs=strcmp(cellstr(tfs),'tf'); %Convert to cell array and find tf's s=s(tfs); %Get just tf's vname=strvcat(s.name); varName{1}='User Systems'; varTF{1}=[]; varName{2}='Refresh Systems'; varTF{2}=[]; j=2; for i=1:length(s) myTF=evalin('base',vname(i,:)); if (size(myTF.num)==[1 1]), %Check for siso j=j+1; varName{j}=vname(i,:); varTF{j}=myTF; end end end visit us at www.assignmentpedia.com or email us at info@assignmentpedia.com or call us at +1 520 8371215

×