BP神經網路+PID控制simulink模擬
最近看到楊藝的那篇《基於S函式的BP神經網路PID控制器及simulink模擬》,也想是否能夠實現Simulink模擬,於是上網搜尋相關資料,發現原來有許多前輩(1點選開啟連結 2 點選開啟連結 3點選開啟連結)早已經做過類似的工作了,並且總結出許多經驗和錯誤,但鑑於在論壇中許多錯誤沒有一個完整的回答,資訊都是零零散散,於是我打算把我做的一整套流程記錄下來,以免日後忘記,同時也希望可以幫助到一些人。
對於連結1裡面是我最早看到的資料,前輩1在MATLAB中文論壇中釋出自己搭建的工程檔案及其所遇到的問題,後面樓主說是解決了問題,但是沒有上傳(這個可以諒解),另外裡面有許多熱心網友的回答是非常有用的(這些回答對我自己後面解決相關問題,成功實現Simulink模擬是非常關鍵的,在這裡非常感謝論壇中的各位前輩
對於連結2這個確實是可以用的,只不過對MATLAB版本有限制。開始我下載之後用我的MATLAB2016b開啟工程,點選run後就報錯,The block 'BPPID/Subsystem/Unit Delay1' does not permit continuous sample time (0 or [0,0]) for the parameter 'SampleTime'.裡面分了兩大派,一部分人說親測有效,大讚跟帖;一部分人也像我一樣執行報錯,此時我疑惑了。於是猜測可能是MATLAB版本問題,於是在另一臺電腦上的MATLAB2014b版本執行,果然得到樓主那一條漂亮的曲線(雖然我的工作就是點選一下run,但是還是很開心
對於連結3非常感謝這個樓主的S函式程式碼,裡面註釋很詳細,我也是在這個樓主的基礎上修改的(非常感謝)。接下來我將把我除錯的整個流程做如下介紹:
1、編寫S函式(感謝上面三位樓主,如有侵權,通知我撤銷)
function [sys,x0,str,ts]=my_exppidf(t,x,u,flag) switch flag, case 0, [sys,x0,str,ts]=mdlInitializeSizes; case 2, sys=mdlUpdates(x,u); case 3, sys=mdlOutputs(t,x,u); case {1,4,9}, sys=[]; otherwise error(['unhandled flag=',num2str(flag)]);%異常處理 end function[sys,x0,str,ts]=mdlInitializeSizes sizes=simsizes;%用於設定模組引數的結構體用simsizes來生成 sizes.NumContStates=0;%模組連續狀態變數的個數 sizes.NumDiscStates=3;%模組離散狀態變數的個數 sizes.NumOutputs=4;%模組輸出變數的個數 sizes.NumInputs=7;%模組輸入變數的個數 sizes.DirFeedthrough=1;%模組是否存在直接貫通,1表示存在直接貫通,若為0,則mdlOutputs函式裡不能有u sizes.NumSampleTimes=1;%模組的取樣時間個數,至少是一個 sys=simsizes(sizes);%設定完後賦給sys輸出 x0=zeros(3,1);%系統狀態變數設定 str=[]; ts=[0 0];%取樣週期設為0表示是連續系統, % ts=[0.001 0];%取樣週期設為0表示是連續系統, function sys=mdlUpdates(x,u) T=0.001; x=[u(5);x(2)+u(5)*T;(u(5)-u(4))/T];%3個狀態量(偏差、偏差和以及偏差變化量),u(5)是偏差,u(4)是上一次的偏差,x(2)則是之前的偏差和 sys=[x(1);x(2);x(3)]; function sys=mdlOutputs(t,x,u) xite=0.2; alfa=0.05; IN=3;H=5;OUT=3; wi=rand(5,3);%產生一個5*3的隨機數矩陣,隨機數在(0,1)區間 wi_1=wi;wi_2=wi;wi_3=wi; wo=rand(3,5); wo_1=wo;wo_2=wo;wo_3=wo; Oh=zeros(5,1);%產生一個1*5的零矩陣(行矩陣) I=Oh; xi=[u(1),u(3),u(5)];%神經網路訓練的3個輸入,期望值、誤差以及實際值 epid=[x(1);x(2);x(3)];%3個狀態變數(偏差、偏差和、偏差變化量)(3*1矩陣,列向量) I=xi*wi';%隱層的輸入 for j=1:1:5 Oh(j)=(exp(I(j))-exp(-I(j)))/(exp(I(j))+exp(-I(j)));%隱層的輸出值(1*5矩陣)行矩陣 end K1=wo*Oh;%輸出層的輸入(3*1矩陣) for i=1:1:3 K(i)=exp(K1(i))/(exp(K1(i))+exp(-K1(i)));%得到輸出層的輸出(KP、KI、KD)(1*3矩陣,行向量) end u_k=K*epid;%計算得到控制律u,1個值 %%以下是權值調整 %隱含層至輸出層的權值調整 dyu=sign((u(3)-u(2))/(u(7)-u(6)+0.0001)); for j=1:1:3 dK(j)=2/(exp(K1(j))+exp(-K1(j)))^2; %輸出層的輸出的一階導 end for i=1:1:3 delta3(i)=u(5)*dyu*epid(i)*dK(i); %輸出層的delta end for j=1:1:3 for i=1:1:5 d_wo=xite*delta3(j)*Oh(i)+alfa*(wo_1-wo_2); end end wo=wo_1+d_wo; %以下是輸入層至隱含層的權值調整 for i=1:1:5 dO(i)=4/(exp(I(i))+exp(-I(i)))^2;%(1*5矩陣) end segma=delta3*wo;%(1*5矩陣,行向量) delta2 = dO.*segma; d_wi = delta2'*xi+alfa*(wi_1-wi_2); wi=wi_1+d_wi; wo_3=wo_2; wo_2=wo_1; wo_1=wo;%儲存輸出層本次調整後的權值 wi_3=wi_2; wi_2=wi_1; wi_1=wi;%儲存隱層本次調整後的權值 Kp=K(1);Ki=K(2);Kd=K(3); sys=[u_k,Kp,Ki,Kd];
2、搭建Simulink模型
其中Subsystem為:
3、相關引數配置
3.1 系統引數
3.2 Transport Delay 引數設定
3.3 Unit Delay 引數設定
tips:其中 系統引數fundamental sample time設定 與 Transport Delay 引數 Time delay 有聯絡,如果設定不好則會出現輸出一直為0的情況。
4、實驗結果
4.1 當fundamental sample time 設定為0.02時,實驗結果如下:
4.2 當fundamental sample time 設定為0.1時,實驗結果如下:
最後,由於作者水平有限,感謝各位大家批評指正。另外,我將自己的程式碼連結程式碼附上。點選開啟連結(https://download.csdn.net/download/zkzfengyi/10441272)