%% DRFOC with PI tuned according to Kessler criteria:
%% the modulus optimum method and the symmetrical optimum method (AKA Naslin polynomial method).
%
% Bartlomiej Ufnalski
% Institute of Control and Industrial Electronics
% Warsaw University of Technology
% 2016.05.26
%
% For Extended Luenberger Observer demonstration
clear all;
rng('shuffle');
Tgraph=1e-3; % sampling period for graphs
% Direct rotor field oriented control (DRFOC) scheme is implemented here
k_measurement_i = 1/15;
tau_measurement_i = 1e-4; % delay
k_measurement_omega = 1/100;
tau_measurement_omega = 0.005; % delay
k_converter = 300;
tau_converter = 1.5e-4; % dealy related to digital implementation and PWM
out_sat = 1; % saturation level for all PI controllers
psir_ref = 0.65;
J_tot = 0.15;
% Motor parameters
Ls = 0.1004;
Lr = 0.0969;
Lm = 0.0915;
sigma = 1-Lm*Lm/Lr/Ls;
Rs = 1.54;
Rr = 1.294;
pb = 3;
c_viscosity = 1e-2;
Tr = Lr/Rr;
Ts = 1e-4; % controller at 10kHz
Imax = 15; % to determine noise signal
OMEGAmax = 80; % to determine noise signal
Umax = k_converter; % to determine noise signal
upper_speed = 70;
upper_torque = 13;
% Modulus Optimum (MO) for current controllers
R_MO = Rs + Rr;
L_MO = (Ls - Lm) + (Lr - Lm);
% the above are from the T-shaped equivalent model of the machine -- the vertical path with Lm neglected (model under short-circuit condition)
tau_MO_dominant = L_MO/R_MO;
tau_MO_sum_of_small = tau_converter + tau_measurement_i;
k_plant_MO = k_converter * 1/R_MO * k_measurement_i; % plant gain
T_reg_current_MO = tau_MO_dominant;
K_reg_current_MO = 1/2/k_plant_MO/tau_MO_sum_of_small;
kp_ix = K_reg_current_MO * T_reg_current_MO;
ki_ix = K_reg_current_MO;
kp_iy = kp_ix;
ki_iy = ki_ix;
% Symmetrical Optimum (SO) for speed controller
% Plant: 1/(2*tau_MO_sum_of_small*s+1) * (1/k_measurement_i) * 3/2 * Lm/Lr * pb * psir_ref
% * (1/c_viscosity)/(s*(J_tot/c_viscosity) + 1) * k_measurement_omega/(s*tau_measurement_omega + 1)
k_plant_SO = (1/k_measurement_i) * 3/2 * Lm/Lr * pb * psir_ref * (1/c_viscosity) * k_measurement_omega;
tau_SO_dominant = J_tot/c_viscosity;
tau_SO_sum_of_small = 2 * tau_MO_sum_of_small + tau_measurement_omega;
alpha = 3; % 4 produces critically damped system; 2 is the first hand choice; alpha = 4*zeta^2
T_reg_omega_SO = alpha^2 * tau_SO_sum_of_small;
K_reg_omega_SO = tau_SO_dominant/alpha^3/k_plant_SO/tau_SO_sum_of_small/tau_SO_sum_of_small;
kp_om = K_reg_omega_SO * T_reg_omega_SO;
ki_om = K_reg_omega_SO;
% Flux controller
plant_PSI = tf([1/k_measurement_i],[2*tau_MO_sum_of_small^2 2*tau_MO_sum_of_small 1]);
[z,p,k] = zpkdata(plant_PSI);
% this does not comply with SO method
step_PSI = stepinfo(plant_PSI);
disp(['Stator current rise time: ' num2str(step_PSI.RiseTime)]);
disp(['Suggested stator flux rise time: ' num2str(step_PSI.RiseTime*10)]);
% Flux controller tuned using PID Tuner -- see flux_controller_PID_Tuner.slx
% It is assumed here that the rise time of flux response is increased ca. tenfold in comparison to the current response.
% This is a typical approach to cascaded controllers.
kp_psi = 3;
ki_psi = 100;
% Reference speed, disturbance torque and noise generator seeds
seed_1 = round(rand*(2^32-1));
seed_2 = round(rand*(2^32-1));
seed_3 = round(rand*(2^32-1));
seed_4 = round(rand*(2^32-1));
seed_5 = round(rand*(2^32-1));
seed_6 = round(rand*(2^32-1));
seed_7 = round(rand*(2^32-1));
seed_8 = round(rand*(2^32-1));
seed_9 = round(rand*(2^32-1));
seed_10 = round(rand*(2^32-1));
seed_11 = round(rand*(2^32-1));
how_many_within = 98; % in percentage erf_inverse = 2.3263 for 98%
% erf_inverse = 2.3263;
erf_inverse = erfinv(how_many_within/100)*sqrt(2); % inverse Gauss error function
noise_psd_OMEGA = (OMEGAmax*0.01/erf_inverse)^2*Ts; % in digital encoders there is no typical noise, but still some non-neglegible inacuracies may be present
dpsirmax = 1e2;
system_psir_noise_PSD = (dpsirmax*0.005/erf_inverse)^2*Ts;
dismax = 2e3;
system_is_noise_PSD = (dismax*0.005/erf_inverse)^2*Ts;
domegamax = 3e2;
system_omega_noise_PSD = (domegamax*0.005/erf_inverse)^2*Ts;
noise_psd_I = (Imax*0.03/erf_inverse)^2*Ts;
%
t_stop = 5;
% That's all folks!