Adaptive PID Controller for Speed Control
16 views (last 30 days)
Show older comments
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;

0 Comments
Answers (0)
See Also
Categories
Find more on PID Controller Tuning in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!