How do I obtain the step response of this PID controller in Matlab? - matlab

I'm relatively new to Control systems. I'm trying to obtain a graph for the step response of a PID controller of the form
Is this possible to plot in mat lab because I get the error that the function cannot plot the step response of a system with more poles than zeros.
Is there any way to plot this system without the whole infinity issue so that I can observe the characteristics of its step response?
I'm sorry if I'm asking a dumb question that may seem obvious but any help or explanation would be greatly appreciated.
This is my mat lab code for my PID controller:
%3.PID Control,Td=0.001, 0.01, 0.05, 0.1
a=tf([0 0 -10],[0 1 10]);
b=tf([0 -1 -5],[1 3.5 6]);
kc=5;
Ti=1;
Td=0.001;
k1=tf([0 Td 0],[0 0 1]); %derivative control
k2=tf([0 1],[Ti 0]); %integral control
G=kc*(k1+k2+1); % the controller
G1=series(a,b);
y=feedback(G,G1,-1);
subplot(2,2,1),stepplot(y),title('kc=5,Ti=1,Td=0.001');

As thewaywewalk mentioned, MATLAB can only deal with proper systems, and a pure derivative isn't proper, so you need to use an approximate derivative in your transfer function. It's never a good practice to use pure derivatives as they tend to amplify noise.
Look at the documentation on the PID Controller block in Simulink to see how to implement a PID controller with approximate derivative. In short, you need to replace Kd*s by Kd*s/(1+a*s) where a is small compared to the dominant time constant of the system.
EDIT:
The best way to create your PID is to use the actual pid function from the Control System Toolbox. It implements a first-order derivative filter on the derivative term.

Related

How to use the FFT (Fast Fourier Transform) in Matlab

I'm just learning Matlab and the fast fourier transform algorithm.
As a first step I tried to duplicate this example: https://en.wikipedia.org/wiki/Fourier_transform#Example
I use the following code:
t = -6:0.01:6;
s = cos(2 * pi * 3 * t) .* exp(-pi * t.^2);
figure(1);
plot(t, s);
xlim([-2 2]);
r = fft(s);
figure(2);
plot(t, abs(r));
And I obtained the following picture:
Figure 2:
Figure 1 is OK, but Figure 2 is not. I see one of the problem is that in Figure 2 I should plot vector r against frequency, not against time. Another problem in Figure 2 is the scale in the Y-axis.
Thus, I have 2 questions in order to duplicate the example:
How can I obtain the frequency domain (X-axis in Figure 2)?
How should I scale vector r (Y-axis in Figure 2)?
Your issue is that you aren't actually creating a frequency vector to plot the fft against. The reason that the fft is plotted against time is because that is what you specified in your plot command.
Here is a working fft outline:
N=length(t);
index=0:N-1;
FrequencyResolution=SamplingRate/N;
Frequency=index.*FrequencyResolution;
data_fft=fft(detrend(data));
%the detrend isn't necessary but it does look nicer because it focuses the plot on changes around the mean of the data
data_FFTmagnitude=abs(data_fft);
plot(Frequency, data_FFTmagnitude)
I remember once for the first time that I wanted to use DFT and FFT for one of my study projects I used this webpage, it explains in detail with examples on how to do so. I suggest you go through it and try to replicate for your case, doing so will give you insight and better understanding of the way one can use FFt as you said you are new to Matlab. Do not hesitate to ask again if you need more detailed help.
And also keep in mind that for FFT it is better to have signal length of a power of 2, that way you will get the most exact results, and if you cannot control your signal length you can take the largest power of 2 close to that length, as everyone usually does.

how can i bode plot this low pass filter?

i am not an expert by any means in matlab but i am asked to plot this transfer function which reflects an active low pass filter but i can't seem to get it right ... can you point out where is the error in this command please? ( the error shows a graph with straight lines)
num=9.18;
den=[(10e3)*(5e-9)];
lowpass= tf(num,den)
bode (lowpass)
I think i have missed up with the brackets but can't tell unfortunately, and i know another command which is easier to generate the required graph , but i have been ask to do this one as it shows the correct form of the transform function.
This is not a MATLAB issue. You have defined the transfer function 9.18/(10e3*5e-9)=9.18/5.0000e-05. This results in a transfer function representing a static gain of 183600. So you defined only one numerator and one denominator coefficient.
You probably mean: den=[ 10e3, 5e-9 ]; giving you two denominator coefficients.
>> lowpass
lowpass =
9.18
---------------
10000 s + 5e-09
Continuous-time transfer function.
This results in lowpass characteristics:
bode(lowpass)

MATLAB using FFT to find steady state response to a periodic input force (mass spring damper system)

Lets say I have a mass-spring-damper system...
here is my code (matlab)...
% system parameters
m=4; k=256; c=1; wn=sqrt(k/m); z=c/2/sqrt(m*k); wd=wn*sqrt(1-z^2);
% initial conditions
x0=0; v0=0;
%% time
dt=.001; tMax=2*pi; t=0:dt:tMax;
% input
F=cos(t); Fw=fft(F);
% impulse response function
h=1/m/wd*exp(-z*wn*t).*sin(wd*t); H=fft(h);
% convolution
convolution=Fw.*H; sol=ifft(convolution);
% plot
plot(t,sol)
so I can successfully retrieve a plot, however I am getting strange responses I also programmed a RK4 method that solves the system of differential equations so I know how the plot SHOULD look like, and the plot I am getting from using FFT has an amplitude of a like 2 when it should have an amplitude of like .05.
So, how can I solve for the steady state response for this system using FFT. I want to use FFT because it is about 3 orders of magnitude faster than numerical integration methods.
Keep in mind I am defining my periodic input as cos(t) which has a period of 2*pi that is why I only used FFT over the time vector that spanned 0 to 2*pi (1 period). I also noticed if I changed the tMax time to a multiple of 2*pi, like 10*pi, I got a similar looking plot but the amplitude was 4 rather than 2, either way still not .05!. maybe there is some kind of factor I need to multiply by?
also I plotted : plot(t,Fw) expecting to see one peak at 1 since the forcing function is cos(t), yet I did not see any peaks (maybe I shouldn't be plotting Fw vs t)
I know it is possible to solve for the steady state response using fourier transform / fft, I am just missing something! I need help and understanding!!
The original results
Running the code you provided and comparing the result with the RK4 code posted in your other question, we get the following responses:
where the blue curve represents the FFT based implementation, and the red curve represents your alternate RK4 implementation. As you have pointed out, the curves are quite different.
Getting the correct response
The most obvious problem is of course the amplitude, and the main sources of the amplitude discrepancies of the code posted in this question are the same as the ones I indicated in my answer to your other question:
The RK4 implementation performs a numeric integration which correctly scales the summed values by the integration step dt. This scaling is lacking from the FFT based implementation.
The impulse response used in the FFT based implementation is consistent with the driving force being scaled by the mass m, a factor which was missing from the RK4 implementation.
Fixing those two issues results in responses which are a little closer, but still not identical. As you probably found out given the changes in the posted code of your other question, another thing that was lacking was zero padding of the input and of the impulse response, without which you were getting a circular convolution rather than a linear convolution:
f=[cos(t),zeros(1,length(t)-1)]; %force f
h=[1/m/wd*exp(-z*wn*t).*sin(wd*t),zeros(1,length(t)-1)]; %impulse response
Finally the last element to ensure the convolution yields good result is to use a good approximation to the infinite length impulse response. How long is long enough depends on the rate of decay of the impulse response. With the parameters you provided, the impulse response would have died down to 1% of its original values after approximately 11*pi. So extending the time span to tMax=14*pi (to include a full 2*pi cycle after the impulse response has died down), would probably be enough.
Obtaining the steady-state response
The simplest way to obtain the steady-state response is then to discard the initial transient. In this process we discard a integer number of cycles of the reference driving force (this of course requires knowledge of the driving force's fundamental frequency):
T0 = tMax-2*pi;
delay = min(find(t>T0));
sol = sol(delay:end);
plot([0:length(sol)-1]*dt, sol, 'b');
axis([0 2*pi]);
The resulting responses are then:
where again the blue curve represents the FFT based implementation, and the red curve represents your alternate RK4 implementation. Much better!
An alternate method
Computing the response for many cycles waiting for the transient response to die down and extracting the remaining samples corresponding
to the steady state might appear to be a little wasteful, despite the fact that the computation is still fairly fast thanks to the FFT.
So, let's go back a little and look at the problem domain. As you are probably aware,
the mass-spring-damper system is governed by the differential equation:
where f(t) is the driving force in this case.
Note that the general solution to the homogeneous equation has the form:
The key is then to realize that the general solution in the case where c>0 and m>0 vanishes in the steady state (t going to infinity).
The steady-state solution is thus only dependent on the particular solution to the non-homogenous equation.
This particular solution can be found by the method of undetermined coefficients, for a driving force of the form
by correspondingly assuming that the solution has the form
Substituting in the differential equation yields the equations:
thus, the solution can be implemented as:
EF0 = [wn*wn-w*w 2*z*wn*w; -2*z*wn*w wn*wn-w*w]\[1/m; 0];
sol = EF0(1)*cos(w*t)+EF0(2)*sin(w*t);
plot(t, sol);
where w=2*pi in your case.
Generalization
The above approach can be generalized for more arbitrary periodic driving forces by expressing the driving force as a
Fourier Series (assuming the driving force function satisfies the Dirichlet conditions):
The particular solution can correspondingly be assumed to have the form
Solving for the particular solution can be done in a way very similar to the earlier case. This result in the following implementation:
% normalize
y = F/m;
% compute coefficients proportional to the Fourier series coefficients
Yw = fft(y);
% setup the equations to solve the particular solution of the differential equation
% by the method of undetermined coefficients
k = [0:N/2];
w = 2*pi*k/T;
A = wn*wn-w.*w;
B = 2*z*wn*w;
% solve the equation [A B;-B A][real(Xw); imag(Xw)] = [real(Yw); imag(Yw)] equation
% Note that solution can be obtained by writing [A B;-B A] as a scaling + rotation
% of a 2D vector, which we solve using complex number algebra
C = sqrt(A.*A+B.*B);
theta = acos(A./C);
Ywp = exp(j*theta)./C.*Yw([1:N/2+1]);
% build a hermitian-symmetric spectrum
Xw = [Ywp conj(fliplr(Ywp(2:end-1)))];
% bring back to time-domain (function synthesis from Fourier Series coefficients)
x = ifft(Xw);
A final note
I purposely avoided the undamped c=0 case in the above derivation. In this case, the oscillation never die down and the general solution to the homogeneous equation does not have to be the trivial one.
The final "steady-state" in this case may or may not have the same period as the driving force. As a matter of fact, it may not be periodic at all if the period oscillations from the general solution is not related to the period of the driving force through a rational number (ratio of integers).

Basic 2-body interaction using Matlab's ode45

I'm trying to model basic gravitation for an object of negligible mass around a massive body. I've followed the examples provided in the ODE suite documentation, but the results I'm getting are plainly ridiculous.
Here's the function I'm calling with ode45:
function dy = rigid(t,y)
dy = zeros(4,1);
%Position
xx=y(1);
yy=y(2);
%Radius
r=(xx.^2+yy.^2).^0.5;
%Constants
M=10^30;
G=6.67*10^-11;
%dX/dt
dy(1)=y(3); %vx
dy(3)=-M.*G.*xx.*r.^-3; %ax
%dY/dt
dy(2)=y(4); %vy
dy(4)=-M.*G.*yy.*r.^-3; %ay
And here are the solver lines:
%Init
x_0=1;
y_0=1;
vx_0=0;
vy_0=5;
%ODEs
[T,Y] = ode45(#rigid,[0 1000],[x_0 y_0 vx_0 vy_0]);
%Vectors
x=Y(:,1);
y=Y(:,2);
%Plot
plot(x,y)
xlabel('x');
ylabel('y');
title('y=f(x)');
I get a linear plot at the end. Even with initial speed, the position doesn't change over a period of several steps. The only thing I can think of is that I've misunderstood the way to set up my system of ODEs.
I've been pondering this for a while now, and I'm really short on ideas having had done a few searches on the web.
Summary: There are problems in integrating Hamiltonian systems with normal numerical integrators, and your special initial conditions aggravate this to the point where the numerical solution has no resemblance with the correct one.
There's nothing wrong with your implementation per se. However, the initial conditions you use are not the best. The constants G and M you use are in SI units, which means the coordinates are in m, the speeds are in m/s, and time is in s. These lines
x_0=1;
y_0=1;
vx_0=0;
vy_0=5;
[T,Y] = ode45(#rigid,[0 1000],[x_0 y_0 vx_0 vy_0]);
therefore mean that you are asking for an orbit with a radius of about 1.4 meters and an orbital speed of 5 m/s, and you want this orbit over a period of 17 minutes. Imagine there actually was an object just meters away from a mass of 10^30 kilograms!
So let's try to ask for something more realistic, similar to Earths' orbit, and look at it over 1 year:
x_0=149.513e9;
y_0=0;
vx_0=0;
vy_0=29.78e3;
[T,Y] = ode45(#rigid,[0 31.536e6],[x_0 y_0 vx_0 vy_0]);
And the result is
which looks as expected.
But there is a second problem here. Let's look at this orbit over a period of 10 years ([0 315.36e6]):
Now we no longer get a closed orbit, but a spiral! That's because the numerical integration proceeds with limited precision, and for this set of equations this leads (physically speaking) to a loss of energy. The precision can be increased using parameters to ode45, but ultimately the problem will persist.
Now let's go back to your original parameters and have a look at the result:
This "orbit" is a straight line towards the origin (the sun). Which could be ok, since a straight oscillation is a possible special case of an elliptic orbit. But looking at the coordinates over time:
We see that there is no oscillation. The "planet" falls into the sun and stays there. What's happening here is the same effect as with the larger orbit: Imprecise integration leads to a loss of energy. Moreover, the numerical integration gets stuck: We asked for a period of 1000 s, but the integration does not proceed beyond 1.6e-10 seconds.
As far as I can tell, neither ode45 nor any of the other standard Matlab integrators are adequate to deal with this problem. There are special numerical integration algorithms designed to do so, specifically for Hamiltonian systems, called symplectic integrators. There is a file exchange entry that provides different implementations. Also see this question and answers for more pointers.

Time of Arrival estimation of a signal in Matlab

I want to estimate the time of arrival of GPR echo signals using Music algorithm in matlab, I am using the duality property of Fourier transform.
I am first applying FFT on the obtained signal and then passing these as parameters to pmusic function, i am still getting the result in frequency domain.?
Short Answer: You're using the wrong function here.
As far as I can tell Matlab's pmusic function returns the pseudospectrum of an input signal.
If you click on the pseudospectrum link, you'll see that the pseudospectrum of a signal lives in the frequency domain. In particular, look at the plot:
(from Matlab's documentation: Plotting Pseudospectrum Data)
Notice that the result is in the frequency domain.
Assuming that by GPR you mean Ground Penetrating Radar, then try radar or sonar echo detection approach to estimate the two way transit time.
This can be done and the theory has been published in several papers. See, for example, here:
STAR Channel Estimation in DS-CDMA Systems
That paper describes spatiotemporal estimation (i.e. estimation of both time and direction of arrival), but you can ignore the spatial part and just do temporal estimation if you have a single-antenna receiver.
You probably won't want to use Matlab's pmusic function directly. It's always quicker and easier to write these sorts of functions for yourself, so you know what is actually going on. In the case of MUSIC:
% Get noise subspace (where M is number of signals)
[E, D] = eig(Rxx);
[lambda, idx] = sort(diag(D), 'descend');
E = E(:, idx);
En = E(:,M+1:end);
% [Construct matrix S, whose columns are the vectors to search]
% Calculate MUSIC null spectrum and convert to dB
Z = 10*log10(sum(abs(S'*En).^2, 2));
You can use the Phased array system toolbox of MATLAB if you want to estimate the DOA using different algorithms using a single command. Such as for Root MUSIC it is phased.RootMUSICEstimator phased.ESPRITEstimator.
However as Harry mentioned its easy to write your own function, once you define the signal subspace and receive vector, you can directly apply it in the MUSIC function to find its peaks.
This is another good reference.
http://ieeexplore.ieee.org/stamp/stamp.jsp?arnumber=1143830