Adaptive PID Controller for Speed Control

16 views (last 30 days)
Mnh
Mnh on 18 Oct 2025 at 16:49
Edited: Mnh on 18 Oct 2025 at 16:51
I am currently encountering some issues with the motor control algorithm with Adaptive PID ConTroller in the real-world implementation. As you can see, at a speed of 5 rad/s, the plant does not accurately track the model and exhibits significant instability. This behavior similarly occurs within the speed range of 5–25 rad/s. When I set the speed to 30 rad/s, the motor initially overshoots and then experiences a severe drop in speed (sometimes even reaching zero or negative values, resulting in a brief reversal). Could you please provide me with some suggestions?
%% MRAS Adaptive PID (MIT rule) for DC Motor (MATLAB–Arduino Serial)
% Hardware:
% - Arduino UNO R3 + L298N + Encoder 334x34
% - The Arduino code transmits the motor speed (rad/s) via Serial communication
% - MATLAB performs the control computation and sends the PWM signal (0–255)
clc; clear; close all;
%% --- Serial Setup ---
port = "COM4"; baud = 115200;
s = serialport(port, baud);
configureTerminator(s, "LF");
flush(s);
disp('✅ Arduino Serial connection successful.');
pause(1);
%% --- MRAS-PID parameters ---
T = 0.05; % Control period (s)
setpoint = 5; % rad/s
am = 6.0; bm = 6.0; % Reference model
ym = 0;
gamma_p = 0.01; gamma_i = 0.003; gamma_d = 0.002;
norm_p = 0.08; norm_i = 0.02; norm_d = 0.05;
Kp = 1.8; Ki = 0.8; Kd = 0.05;
Kp_min=0.2; Kp_max=6.0; Ki_min=0; Ki_max=2.5; Kd_min=0; Kd_max=0.2;
I = 0; e_prev = 0; yp = 0; d_filt = 0;
deriv_alpha = 0.5; speed_alpha = 0.7;
PWM_MAX = 255; PWM_DEAD = 8; MAX_SPEED = 31;
%% --- Initialize plot ---
figure('Color','w');
subplot(2,1,1);
h1=animatedline('Color','r','LineWidth',1.5);
h2=animatedline('Color','b','LineWidth',1.5);
h3=animatedline('Color',[.7 .7 .7],'LineWidth',1,'LineStyle','--');
xlabel('Time (s)'); ylabel('Speed (rad/s)');
title('MRAS Adaptive PID Tracking');
legend({'Plant','Model','Ref'},'Location','best'); grid on;
subplot(2,1,2);
hKp=animatedline('Color','r'); hKi=animatedline('Color','b'); hKd=animatedline('Color','g');
xlabel('Time (s)'); ylabel('Gain'); grid on;
%% --- loop ---
disp('Starting control... Press Ctrl+C to stop');
t0 = tic;
while ishandle(h1)
t = toc(t0);
% --- Read speed from Arduino ---
if s.NumBytesAvailable > 0
line = readline(s);
yp_new = str2double(line);
if ~isnan(yp_new)
yp = speed_alpha*yp + (1-speed_alpha)*yp_new;
end
end
% --- Reference model ---
ym = ym + T*(-am*ym + bm*setpoint);
% --- error ---
e = setpoint - yp;
em = ym - yp;
% --- Basic PID ---
d_raw = (e - e_prev)/T;
d_filt = deriv_alpha*d_filt + (1-deriv_alpha)*d_raw;
I = I + e*T;
uP = Kp*e + Kd*d_filt;
u_tent = uP + Ki*I;
% Saturation and anti-windup
if (u_tent>=PWM_MAX && e>0) || (u_tent<=0 && e<0)
I = I*0.999;
end
u = uP + Ki*I;
pwmOut = min(max(u,0),PWM_MAX);
if pwmOut>0 && pwmOut<PWM_DEAD
pwmOut = PWM_DEAD;
end
% --- Send PWM to Arduino ---
writeline(s, string(round(pwmOut)));
% --- MRAS adaptation ---
freeze = ((pwmOut>=PWM_MAX && em>0) || (pwmOut<=0 && em<0));
if ~freeze
phi_p=e; phi_i=I; phi_d=d_filt;
Kp = Kp + gamma_p*em*phi_p/(1+norm_p*phi_p^2);
Ki = Ki + gamma_i*em*phi_i/(1+norm_i*phi_i^2);
Kd = Kd + gamma_d*em*phi_d/(1+norm_d*phi_d^2);
Kp = min(max(Kp,Kp_min),Kp_max);
Ki = min(max(Ki,Ki_min),Ki_max);
Kd = min(max(Kd,Kd_min),Kd_max);
end
% --- Real-time plotting ---
addpoints(h1,t,yp);
addpoints(h2,t,ym);
addpoints(h3,t,setpoint);
addpoints(hKp,t,Kp); addpoints(hKi,t,Ki); addpoints(hKd,t,Kd);
drawnow limitrate;
e_prev = e;
pause(T);
end
disp('⏹ STOP.'); clear s;

Answers (0)

Products


Release

R2024b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!