我在功能方面遇到了一些麻烦" lsqnonlin"在Matlab上。我试图通过使用具有PID的系数(Kp,Ki,Kd)作为决策变量的函数来优化Arduino内部的PID控制器,并且目标函数是最小化响应的最小平方差减去参考值。
此链接更好地解释了我正在做的事情:http://it.mathworks.com/help/optim/ug/lsqnonlin-with-a-simulink-model.html。
该示例与我的问题之间的区别在于我想执行一种硬件在环仿真,将Simulink执行的仿真替换为我设计的实际系统,其中传感器与Arduino接口提供响应" yout"通过串行通信到Matlab。
问题是Matlab上的算法用一个非常小的步骤(10 ^ -8或类似的东西)改变变量(Kp,Ki,Kd),所以我看不到实际的变化响应。经过几次迭代后,算法停止说:" lsqnonlin因为当前步长小于 步长容差的选定值"。
我无法理解为什么这些步骤如此之少以及它为什么会这样停止。我的代码如下。
pid0 = [10 0 0]; %inizialization of PID parameters
options = optimset('LargeScale','off','Display','iter',...
'TolX',0.001,'TolFun',0.001);
pid = lsqnonlin(@trackpid, pid0, [0 0 0], [], options)
Kp = pid(1); Ki = pid(2); Kd = pid(3);
trackpid功能是:
function F = trackpid(pid)
% Serial communication
s = serial('/dev/cu.usbmodemFD131');
set(s,'BaudRate', 9600);
set(s,'DataBits', 8);
set(s,'StopBits', 1);
% Global Variables
numberOfDatas = 700;
Kp = pid(1)
Ki = pid(2)
Kd = pid(3)
i = 1;
fopen(s);
pause(1.7); %i need to wait 1.7s in order to read the values
%Send to Arduino the PID coefficients
fprintf(s,num2str(Kp));
fprintf(s,num2str(Ki));
fprintf(s,num2str(Kd));
while (fscanf(s,'%c') ~= 't') %Wait for Arduino to start the simulation
end
%Scan
while(i <= numberOfDatas)
yout(i) = fscanf(s,'%f');
i = i + 1;
end
fclose(s);
yout
F = yout - 21; %evaluate the difference between the response and the reference
提前谢谢。