System Controlling: DC Motor
Showing posts with label DC Motor. Show all posts
Showing posts with label DC Motor. Show all posts

Sunday, November 18, 2012

Model predictive control of brushed DC motor

Motor model

The state space model of a brushed DC motor as follow:
$$A =\left[ {\begin{array}{cc} -\frac{R_{a}}{L_{a}} & -\frac{K_{e}}{L_{a}} &  0 \\ \frac{K_{m}}{J} & -\frac{b}{J} & 0 \\ 0 & 1 & 0 \end{array} } \right] B=\left[ {\begin{array}{cc} \frac{1}{L_{a}} \\ 0 \\ 0 \end{array} } \right] C=\left[ {\begin{array}{cc} 0 \\ 1 \\ 0 \end{array} } \right] D=\left[ {\begin{array}{cc} 0 \end{array} } \right]\tag{1}$$
As you can see, I assumed that the torque is zero. 
Where the states are:
$$\dot{x(t)} =\left[ {\begin{array}{cc} \frac{di}{dt} \\ \frac{d\omega}{dt} \\ \frac{d\theta}{dt} \end{array} } \right]\tag{2}$$

Controller design


I already introduced the MPC controller, please read that first before you continue to read this blog. 
The first step is to determine the Toeplitz matrix:
$$\begin{bmatrix}x_{k+1|k} \\ \vdots \\ x_{k+N_c|k} \\ x_{k+N_c+1|k} \\ \vdots \\ x_{k+N|k} \end{bmatrix}=\begin{bmatrix}\Phi \\ \vdots \\ \Phi^{N_c} \\ \Phi^{N_c+1} \\ \vdots \\ \Phi^N \end{bmatrix}x_k + \begin{bmatrix}\Gamma \\ \vdots \\ \sum_{i=0}^{N_c-1} \Phi^{i} \Gamma\\ \sum_{i=0}^{N_c}\Phi^{i} \Gamma\\ \vdots \\ \sum_{i=0}^{N}\Phi^i \Gamma \end{bmatrix}u_{k-1}\\+ \begin{bmatrix}\Gamma & \cdots & 0 \\ \vdots & \ddots & \vdots \\ \sum_{i=0}^{N_c}\Phi^{i} \Gamma & \cdots & \Phi \Gamma+\Gamma \\ \vdots & \ddots & \vdots \\ \sum_{i=0}^{N-1}\Phi^i \Gamma & \cdots & \sum_{i=0}^{N-N_c}\Phi^i \Gamma \end{bmatrix} \begin{bmatrix}\Delta u_{k+1|k} \\ \vdots \\ \Delta u_{k+N_c-1|k} \end{bmatrix}\tag{1}$$ 
I wrote the following Matlab function to build up the  $\Phi^*$, $\Gamma^*$, $G_y$:
function [FiFi,FiGam,Gy] = getFiFi_FiGa(Fi,Ga,C,N,Nc,n)
    
    FiFi=[]; %ennek a merete N*n x n kell legyen
    
    for i=1:N,    
        FiFi=[FiFi; C*Fi^i]; 
    end
    % FiGam szamitasa
    FiGam=[];
    for i=1:N,
        S=0;
        for j=0:i-1,       
            S=S+C*Fi^j*Ga;    
        end
        FiGam=[FiGam; S];
    end
    
    ng=size(FiGam,1);
    mg=size(FiGam,2);
    % Gy szamitasa
    Gy=zeros(ng,mg*Nc);
    % Gy szamitasa
    for j=1:mg:Nc*mg   % oszlopok         
        Gy(j:end, j:j+mg-1)=FiGam(1:end-j+1,:);
    end

end
To find the optimal control signal we have to solve the following optimization problem $J_k(u,x_k)=\frac{1}{2}\Delta u_k^TH\Delta u_k+f^T\Delta u_k+const$. I already presented the solution of this problem (see Model predictive control). I am going to  implement the calculation of the $\Delta u_k$ optimal control signal in the following example:
for v=1:n-N
    %Error vector
    E=Yref(v:v+N-1)-FiFi*x0-FiGam*u;
    
     deltau=inv(Gy'*Q*Gy+R)*Gy'*Q*E;
     u=u+deltau(1:2);
     for k=1:length(u)
         if(abs(u(k))>lim)
             u(k) = sign(u(k))*lim;
         end
     end
   
    x0 = Fi*x0+Ga*u;
    yt = C*x0;
    
    
    um=[um u];
    ym=[ym;yt];
end;

In the example above I also tried to constrain the control signal by choosing the $lim$ variable to 38. After choosing the values of the noise matrices as follows
  • $Q=eye(N*Nro)*1e4$ where $N$ is the number of the horizon and $Nro$ is the number of the outputs.
  • $R=eye(Nc*Nrin)*1e-5$ where $Nc$ is the number of the control horizon and $Nrin$ is the number of the inputs.
I got these results:
Figure 1. Rotor speed
Figure 2. Control signal
Figure 3. Error between the reference and measured rotor speed
We can reduce the error by increasing or eliminating the constrain of control signal as you can see in $Figure 4$
Figure 4. Error between the reference and measured rotor speed without limiting the control signal
The other solution  of the optimal control signal calculation in Matlab is the built in $quadprog$ function. You can find a simple example below, also you can read the description of this function on the Matlab help page:
H=2*(Gy'*Q*Gy+R);
for v=1:n-N
    %Hiba vektor    
    E=Yref(v:v+N-1)-FiFi*x0-FiGam*u;
    
    f=-2*E'*Q*Gy;        
    
    b = [abs(lim-u(1));
        abs(lim+u(1))];
    A = [1 0 0 0 0 0 0 0;
        -1 0 0 0 0 0 0 0;
        ];
     
    Aeq=[];beq=[];
    
    [deltau,FVAL,EXITFLAG]=quadprog(H,f,A,b,Aeq,beq);
    u=u+deltau(1:2);
    
   
    x0 = Fi*x0+Ga*u;
    yt = C*x0;    
    
    um=[um u0];
    ym=[ym;yt];
    Em = [Em;E];
end;

Appendix

Motor parameters:
    Rm = 0.35;
    Km=0.0296;
    Ke = 0.0296;
    b = 6.7*10e-5;
    J = 2.9*10e-6;
    Fc = 0.02;
    L = 25 *10e-6;
    Ts = 1e-4;

Monday, October 22, 2012

LQ speed regulation of a brushed DC motor

In the following post I will present a speed controller of the brushed DC motor using LQR. I will also introduce the Kalman filter to estimate the motor speed and torque. 
System diagram
I already introduced the state space model of the brushed DC machine, in this post I will introduce only the controller. 

Discrete state tracking linear quadratic regulator

Have the following linear discrete system
$$x_{k+1}=A_kx_k+B_ku_k\\
y_k=H_kx_k\tag{1}$$

Let us presume that $z_k$ is the trajectory what we would like to follow, in this case we have to determine the optimal control signal which optimize the quadratic criterion:
$$
J(u) = min\left[e_N^TFe_N+\sum_k{e_k^TQ_ke_k+\delta u_k^TR_k\delta u_k}\right]\tag{2}
$$
Where  $e=z_k-y_k$ and $\delta u_k=u_k-up_k$.
Bellman's equation of the corresponding control problem is:
$$
J_{min_k}(u) = min\left[e_k^TQ_ke_k+\delta u_k^TR_k\delta u_k+J_{min_{k+1}}(u)\right]\tag{3}
$$
Expressing the cost of termination point as:
$$
J_{min_N}(u)=\left[z_N-H_Nx_N\right]^TF\left[z_N-H_Nx_N\right]\tag{4}
$$Introduce the following expressions:
$$P_N=H_N^TF_NH_N\\ p_{N_0}=z_N^TFz_N\\ g_N^T=-2z_N^TFH_N\tag{5}$$
Where $N$ is the number of the horizon and $k$ is the iteration.
The cost function will be the following:
$$
J_{min_k}(u)=p_{k_0}+g_k^Tx_k+x_k^TP_kx_k\tag{6}
$$
where the Belman's equation is:
$$
J_{min_k}(u)=min\left[e_k^TQ_ke_k+\delta u_k^TR_k\delta u_k+p_{(k+1)_0}+g_{k+1}^Tx_{k+1}+x_{k+1}^TP_kx_{k+1}\right]\tag{7}
$$
Considering that in the $k$ iteration the $u_k$ optimal control minimizes the criterion $J(u)_k$, we can write the following relation
$$u_k=\left[R_k+B_k^TP_{k+1}B_k\right]^{-1}\left[R_kup_k+\frac{1}{2}B_kg_{k+1}-B_k^TP_{k+1}A_kx_k\right]\tag{8} $$
The recursive discrete Ricatti equation is the following:$$P_k=H_k^TQ_kH_k-A_k^TP_{k+1}B_k\left[R_k+B_k^TP_{k+1}B_k\right]^{-1}\\B_k^TP_{k+1}A_k+A_k^TP_{k+1}A_k\tag{9}$$respecting the final condition:
$$P_N=H_N^TF_NH_N\tag{10}$$
We can express the optimal control signal in the following form:
$$u_k=K_kx_k+f_k\tag{11}$$
where
$$K_k=-\left[R_k+B_k^TP_{k+1}B_k\right]^{-1}B_k^TP_{k+1}A_k\tag{12}$$
$$f_k=-\frac{1}{2}\left[R_k+B_k^TP_{k+1}B_k\right]^{-1}\left[B_k^Tg_{k+1}\right]\tag{13}$$
After performing some algebraic calculations, we will end up with the following equation:$$g_k^T=-2z_k^TQ_kH_k+g_{k+1}\left[A_k+B_kK_k\right]^T\tag{14}$$
with boundary condition:
$$g_N^T=-2z_N^TFH_k\tag{15}$$

Results 

The steady state error depends on the number of the horizon ($N$), the accuracy of the system model and the state estimation. Choosing the number of the horizon to five the rotor speed is the following:
 The controller signal is depending of the accuracy of the state estimator

Choosing the number of the horizon more than 15, the steady state error was 0. The number of the horizon, and the limitation of the control signal are influences the overshoot. One of the disadvantages of the LQR is that the optimal signal calculation doesn't include the signal limitation, thus a bigger control signal can be calculated than you can physically achieve.

Python implementation

The Python implementation of the state tracking LQR is under the following link. Feel free to fork. It was harder to implement into Python than Matlab, but finally I succeeded. In the T_DCMotor.py you can find two controller, one is a PID controller
pid  =  PID( KP = 0.2, KI = 100, KD = 0.00001 
for i in range( len( pw ) ):
    #Calculate the error
    error = pw[i] - sw;
    #Calculating the control signal
    u = pid.run( error, Ts = Ts )
    if( abs( u ) > 220 ):
        u = sign( u ) * 220; 

    #Simulating
    ( sw, x ) = dc2.dlsim( u , torque[0, i ] );
    y_out[i, :] = sw
    u_out[i, :] = u 

The other is the LQR state tracker controller with Kalman filter
dlqr = DSTLQR( Ak, Bk, Ck, N )
kf = dKF( x_est, Ak, Bk, H )

for i in range( len( pw ) - N ): 
   #Calculation the optimal control signal
   U = dlqr.calcU( x_est, array( [pw[i:i + N]] ) ) 
   if( abs( U ) > 220 ):
     U = sign( U ) * 220;

   #Simulating
   ( sw, x ) = dc2.dlsim( U, torque[0, i ], Ts = Ts );
   y_out[i, :] = sw
   u_out[i, :] = U

   #Estimating the states
   ( x_est, P, error ) = kf.update( x[0, 0] , U )

   y_est[i, :] = x_est[1]; 

Matlab source code

I used a discrete Kalman filter to estimate the torque and the rotor speed, here is the code of the Kalman filter:
% Created by Róbert Ungurán
% GPLv2
%******************************************************
% Dc motor discrete model
%******************************************************
% Input 
%   I_in - Measured current
%   U_in - Measured voltage
%******************************************************
% Output
%   x_out - Estimated state variables
function x_out = kf(I_in,U_in)

    global Ts  Rm L Ke Kd J Km;
    
    persistent x
    persistent P
    if isempty(x)
        x = [0;0; 0];        
        P = zeros(3);
    end
    % Armature current, rotor speed, Torque
    Ak  =   [1-Ts*(Rm/L)  -Ts*(Ke/L)        0;
            Ts*(Km/J)    1-Ts*(Kd/J)    -Ts/J;
            0               0               1;];

    Bk  =   [Ts*1/L; 0; 0];

    H   =   [1 0 0];
    
    
    R   =   1e-3;
    Q   =   diag([1e-6 1e-2 1e-2]);
    
    
    x   =   Ak*x + Bk*U_in;
   
    P   =   Ak * P * Ak' + Q;
    
   
    % Compute Kalman gain factor:
    S   =   H*P*H'+R;
    K   =   P*H'*inv(S);

    % Correction based on observation:
    error = I_in-H*x;
    x   =   x + K*error;
    P   =   P - K*H*P;
    
    x_out   =   x;
end
The source of the discrete linear quadratic regulator
% Created by Róbert Ungurán
% GPLv2
%******************************************************
% LQR controller of a DC motor
%******************************************************
% Input 
%   I       - Measured current
%   w       - Measured rotor speed
%   w_ref   - Reference rotor speed 
%******************************************************
% Output
%   U - Control signal
function U = mydlqr(I,w,Tl,w_ref)   
  
    global Ts  Rm L Ke Kd J Km N;
    
    x = [I;w;Tl];

    Ak  =   [1-Ts*(Rm/L)  -Ts*(Ke/L)        0;
            Ts*(Km/J)    1-Ts*(Kd/J)    -Ts/J;
            0               0               1;];

    Bk = [Ts*1/L; 0; 0];

    Ck = [0 1 0];

    Dk = [0];   
   
    
    [n,m] = size(Bk);
    [p,n] = size(Ck);
    
    R=eye(m)*0.001;
    Q=eye(p)*10;
    F=Q;
    
    PN = Ck'*F*Ck; 
    gN =  (-2*w_ref(1)'*F*Ck)';    
    
    
    for j=N:-1:1        
        K = (-inv(R+Bk'*PN*Bk)*Bk'*PN*Ak);
        fk = (-1/2)*inv(R+Bk'*PN*Bk)*Bk'*gN;       
        gN = (-2*w_ref(:,N-1)'*Q*Ck+gN'*(Ak+Bk*K))';
        PN = Ck'*Q*Ck-Ak'*PN*Bk*inv(R+Bk'*PN*Bk)*Bk'*PN*Ak+Ak'*PN*Ak;            
    end
     
    U = K*x+fk;
    
end
The main source code
clear all
close all
clc

%% Initialization
global Ts  Rm L Ke Kd J Km N Fc;

Rm  =   0.35;
Km  =   0.0296;
Ke  =   0.0296;
Kd  =   6.7*10e-5;
J   =   2.9*10e-6;
Fc  =   0.02;
L   =   25 *10e-6;
Ts  =   1e-5;
N   =   5;

x       =   [0;0;0];
w_ref   =   [ones(1,1000)*200 ones(1,1000)*400];
torque  =   [ones(1,1500)*2.0 ones(1,500)*1.0];
[n,m]   =   size(w_ref);
u   =   [];
w   =   [];
x_est = [0; 0; 0];
x_est_o = [0; 0; 0];


for i=1:m-N
    %% Calculation the optimal control signal
    %Input Current, Rotation speed, Rotation speed references
    U   =   mydlqr(x_est(1),x_est(2),x_est(3), w_ref(i:i+N));
    if(abs(U) > 380)
        U = sign(U)*380;
    end
    u   =   [u U];
    
    %% Simulation the model
    %Current, Rotation speed, Rotation position    
    [x(1), x(2), x(3)]  =   dc_motor(U, torque(i));
    w   =   [w x(2)];
    %% Estimating the states
    x_est   =   kf(x(1), U);
    
    x_est_o =   [x_est_o x_est];    
    
end

%% Visualization
plot(u);
figure;
plot(x_est_o(3,:));
figure;
hold on;
plot(w_ref, 'b-');
plot(w, 'r-');
plot(x_est_o(2,:), 'g-');
legend('Reference','Simulated', 'Estimated');

Monday, April 16, 2012

Brushed DC motor

Introduction

If you have never heard about Brushed DC motor, then the Wikipedia is a really good start.

A short description about the direct current motor: when a rectangular coil carrying current is placed in a magnetic field, a torque acts on the coil which rotates it continuously. When the coil rotates, the shaft attached to it also rotates and thus it is able to do mechanical work.

When the coil is powered, a magnetic field is generated around the armature. The left side of the armature is pushed away from the left magnet and drawn towards the right, causing rotation.


When the coil turns through 90°, the brushes lose contact with the commutator and the current stops flowing through the coil. However the coil keeps turning because of its own momentum. Now when the coil turns through 180°, the sides get interchanged 

 Motor Model

The following model is a equivalent-circuit representation of the brushed DC motor.


 In the equivalent-circuit above the electrical system equation is the following - using Kirchhoff's voltage and current law:
$$V_{a}=iR_{a}+L_{a}\frac{di}{dt}+e$$ $$e=K_{e}\omega_{m}$$  Mechanical system equation:
$$T_{l} = -J\frac{d\omega_{m}}{dt}-b\omega_{m}+K_{m}i_{a}$$ From the equation above we can write the following equations:
$$\frac{di}{dt} = - \frac{R_{a}}{L_{a}}i_{a} - \frac{K_{e}}{L_{a}}\omega_{m} + \frac{1}{L_{a}}V_{a}$$ $$\frac{d\omega_{m}}{dt} = \frac{K_{m}}{J}i_{a} - \frac{b}{J}\omega_{m} - \frac{1}{J}T_{l}$$ 
Where:
\(J\): Motor and load Inertia
\(b\) : Viscous damping coefficient
\(K_{e}\): Speed constant
\(K_{m}\): Torque constant
\(L_{a}\): Motor armature coil inductance
\(R_{a}\): Motor armature coil resistance

State Space Method

The state space method takes from the
$$\dot{x(t)} = Ax(t) + B u(t)$$$$y(t) = Cx(t) + Du(t)$$
Where the state-space matrices are the following:
$$\dot{x(t)} =\left[ {\begin{array}{cc} \frac{di}{dt} \\ \frac{d\omega}{dt} \\ \frac{d\theta}{dt} \end{array} } \right] A =\left[ {\begin{array}{cc} -\frac{R_{a}}{L_{a}} & -\frac{K_{e}}{L_{a}} &  0 \\ \frac{K_{m}}{J} & -\frac{b}{J} & 0 \\ 0 & 1 & 0 \end{array} } \right] B=\left[ {\begin{array}{cc} \frac{1}{L_{a}} \\ 0 \\ 0 \end{array} } \right] C=\left[ {\begin{array}{cc} 0 \\ 1 \\ 0 \end{array} } \right] D=\left[ {\begin{array}{cc} 0 \end{array} } \right]$$