DC Motor Simulation


This Matlab/Octave file demonstrates a simulation of a simple DC motor model simulation.

simulate_dc_motor.m

This is a basic simulation of the first order ordinary differential equations of a DC motor with a specified voltage. In class, we wrote each of the three functions as separate files, but you can include them all in one file as shown below. To run this file, download it, set your Octave/Matlab path to the directory where the file is and type simulate_dc_motor in the Octave/Matlab terminal window.

Download simulate_dc_motor.m

%% This file demonstrates how to do basic simulation of the first order
%% differential % equations of a simple DC motor model.

% This file contains three functions. The first function in the file will be
% the primary function that calls the other two functions defined below.

function simulate_dc_motor()
    % The system has four state variables and here the initial condition for
    % each state variable is set. Feel free to try out different initial
    % conditions.
    % x = [q, i, theta, omega]
    x0 = [0, 0, 0, 0];

    % Create a vector of time values that we desire to know x(t) at. The
    % larger the number of values, the more accurate the result is, but the
    % slower the integration runs. Try changing the time step (deltat) to
    % see the affects on the results.
    t = linspace(0, 10, 1000);

    % Call a function that integrates the system's equations and returns
    % x(t).
    % The @ is required to pass in functions to other functions, i.e. a
    % function name is not a standard variable name.
    [t, x] = euler_integrate(@f, t, x0);

    % Plot the results. Always label x and y axis and provide units! Note
    % that Octave/Matlab can render mathematical symbols using LaTeX
    % notation.
    figure(1);
    plot(t, x);
    title('Simulation with Euler''s Method');
    xlabel('Time [s]');
    legend('q [C]', 'i [A]', '\theta [rad]', '\omega [rad/s]');

    % We wrote our own integration function here, but Octave/Matlab includes
    % many better integration routines that can handle certain ODEs more
    % carefully, ensuring accurate results. For example ode45() works just
    % like euler_integrate() but uses the Runga-Kutta 4-5 integration
    % algorithm. This is a good algorithm for most non-stiff system
    % equations and will work with most of the models in this class. You use
    % it like so:
    [t, x] = ode45(@f, t, x0);

    % You should get almost exactly the same results as the custom
    % integration function:
    figure(2);
    plot(t, x);
    title('Simulation with Octave/Matlab''s Runga-Kutta 4-5 Method');
    xlabel('Time [s]');
    legend('q [C]', 'i [A]', '\theta [rad]', '\omega [rad/s]');
end

function [t, x] = euler_integrate(f, t, x0)
    % EULER_INTEGRATE - Integrates a set of first order ordinary
    % differential equations using Euler's integration method.
    %
    % Syntax: [t, x] = euler_integrate(f, t, x0)
    %
    % Inputs:
    %   f - An anonymous function that evaluates the right hand side of the
    %       first order ordinary differential equations, i.e. dx/dt. The
    %       function must follow the syntax dxdt = f(t, x) and return a size
    %       1xm vector where t is size 1x1 and x is size 1xm.
    %   t - Vector of monotonically increasing time values. [size 1xn]
    %   x0 - Vector a initial conditions for the states. [size 1xm]
    % Outputs:
    %   t - Vector of monotonically increasing time values (same as the
    %       input t). [size 1xn]
    %   x - Matrix of state values as a function of time. [size nxm]

    % Create an "empty" matrix to hold the results n x m.
    x = nan * ones(length(t), length(x0));

    % Set the initial conditions to the first element.
    x(1, :) = x0;

    % Use a for loop to sequentially calculate each new x.
    for i = 2:length(t)
        deltat = t(i) - t(i-1);
        x(i, :) = x(i - 1, :) + deltat * f(t(i - 1), x(i - 1, :));
    end

end

function xdot = f(t, x)
    % F - Returns the time derivative of the states.
    %
    % Syntax: xdot = f(t, x)
    %
    % Inputs:
    %   t - A scalar value of time, size 1x1.
    %   x - State vector at time t, size 1xm were m is the number of states.
    % Outputs:
    %   xdot - Time derivative of the states at time t, size 1xm.

    % Extract the state variables so we can use the variable names we want.
    q = x(1);
    i = x(2);
    theta = x(3);
    omega = x(4);

    % Declare the constants. Make sure units are compatible!
    L = 0.5;  % motor inductance [H]
    Rw = 1.0;  % motor winding resistance [Ohm]
    ktau = 1.5;  % motor torque constant [N*m/A]
    b = 1.8;  % Rotor viscous friction [N*m*s]
    J = 0.1;  % Rotor inertia [kg*m^2]

    % Initialize the empty vector for the derivative of the states. [1xm]
    xdot = nan * zeros(1, length(x));

    % The voltage is the source effort in this system. So we can specify what we
    % want it to be.
    % Example 1, constant voltage:
    V = 0.5;
    % Uncomment the following two examples to try them out.
    % Example 2, sinusoidal voltage (function of time):
    %V = 0.5*sin(pi*t);
    % Example 3, voltage switches on at 1 second (also function of time):
%    if t < 1
%        V = 0;
%    else
%        V = 0.5;
%    end

    % Fill the derivative entries based on the system's equations.
    xdot(1) = i;
    xdot(2) = (-Rw*i - ktau*omega + V) / L;
    xdot(3) = omega;
    xdot(4) = (-b*omega + ktau*i) / J;

end