├── README.md ├── Simulate.m ├── generate.m ├── generate2.m ├── pidctrl2.m ├── sigmoid.m ├── sigmoidGradient.m ├── wi7956.txt └── wo7956.txt /README.md: -------------------------------------------------------------------------------- 1 | # PIDwithBPNN 2 | 根据某市半年中每月最高最低温度,用三次样条插值生成三万多个温度数据,输入模型中模拟误差 3 | ## 模型结构 4 | 使用全连接层输出Kp、Ki、Kd,PID结合温度变化模型得出结果,然后输入全连接层不断迭代,类似RNN 5 | ![屏幕截图 2023-09-06 162430](https://github.com/realxmx/PIDwithBPNN/assets/95325546/321c1ccf-4833-480e-9f36-d724735dea5c) 6 | ![屏幕截图 2023-09-06 165507](https://github.com/realxmx/PIDwithBPNN/assets/95325546/e51b038b-3bfc-4518-ab3a-58e2523ed147) 7 | ![屏幕截图 2023-09-06 165421](https://github.com/realxmx/PIDwithBPNN/assets/95325546/79b9008a-5a88-45d0-b473-17190a1100ce) 8 | PID及温度模型 9 | ![屏幕截图 2023-09-06 165303](https://github.com/realxmx/PIDwithBPNN/assets/95325546/cbe54ec0-c06f-41a6-a84f-33205c8fa86f) 10 | ## 模拟结果 11 | 纯PID 12 | ![untitled2](https://github.com/realxmx/PIDwithBPNN/assets/95325546/1fcaa316-3293-4720-a5db-c73bbe1f10c3) 13 | 基于神经网络的PID 14 | ![untitled1](https://github.com/realxmx/PIDwithBPNN/assets/95325546/3ffe8634-96fd-401b-a3df-81553791e690) 15 | Kp、Ki、Kd变化 16 | ![屏幕截图 2023-09-06 162038](https://github.com/realxmx/PIDwithBPNN/assets/95325546/52ead66b-34e8-439f-89d0-f08deebb16c1) 17 | -------------------------------------------------------------------------------- /Simulate.m: -------------------------------------------------------------------------------- 1 | clear; 2 | close all; 3 | 4 | IN = 4;H = 5;Out = 3; %节点数 5 | 6 | data = readmatrix("datas.txt"); %环境温度数据 7 | data = data(1:35000); 8 | rate = 0.001;%学习率 9 | rate2 = 0.01;%惯性系数 10 | fx = [1 1000]; 11 | 12 | %生成随机权重 13 | %wt = 0.5; 14 | %w1 = wt*rands(H,IN); 15 | %w2 = wt*rands(Out,H); 16 | 17 | w1 = readmatrix("wi7956.txt"); 18 | w1_1 = w1;%缓存上一步的权重 19 | w1_2 = w1; 20 | 21 | w2 = readmatrix("wo7956.txt"); 22 | w2_1 = w2; 23 | w2_2 = w2; 24 | 25 | writematrix(w1); 26 | writematrix(w2); 27 | 28 | u_1 = 0;%上一步的pid输出 29 | 30 | y_1 = 7;%初始温度 31 | 32 | error_1 = 0;%上一步误差 33 | error_2 = 0; 34 | error_3 = 0; 35 | error_4 = 0; 36 | error_5 = 0; 37 | 38 | for k = 1:1:35000 39 | 40 | time(k) = k; 41 | %目标温度 42 | x(k) = 20; 43 | %实际温度(根据控制量和环境温差更新) 44 | y(k) = y_1; 45 | %误差 46 | error(k) = x(k) - y(k); 47 | %神经网络输入 48 | I1 = [x(k),y(k),error(k),1]; 49 | %[1,4]*[4,5] 50 | I2 = I1*w1'; 51 | 52 | O2 = zeros(H,1); 53 | 54 | for j = 1:1:H 55 | %隐藏层输出 56 | O2(j) = tanh(I2(j)); 57 | end 58 | %[3,5]*[5,1] 59 | I3 = w2*O2; 60 | 61 | for l = 1:1:Out 62 | %输出层输出 63 | O3(l) = sigmoid(I3(l)); 64 | end 65 | 66 | e = [error(k);error(k) + error_1 + error_2 + error_3 + error_4 + error_5;error(k)-error_1]; 67 | 68 | % 输出层输出结果,PID系数 69 | kp(k) = O3(1);ki(k) = O3(2);kd(k) = O3(3); 70 | 71 | Kpid = [kp(k),ki(k),kd(k)]; 72 | 73 | % 计算PID输出 74 | u(k) = Kpid*e; 75 | % 计算实际温度 76 | y(k) = y_1 + u(k) - 0.1*(y_1-data(k)); 77 | %计算实际温度与目标温度的误差 78 | error(k) = x(k) - y(k); 79 | 80 | %反向传播 81 | for j = 1:1:Out 82 | %输出层输入 83 | dO3(j) = sigmoidGradient(O3(j)); 84 | end 85 | 86 | % 符号函数,实际温度变化量/控制量的变化量(+0.0001避免出现除0) 87 | du(k) = sign((y(k)-y_1)/(u(k)-u_1+0.0001)); 88 | 89 | for l = 1:1:Out 90 | delta3(l) = error(k)*du(k)*e(l)*dO3(l); 91 | end 92 | 93 | for l = 1:1:Out 94 | for i = 1:1:H 95 | d_w2(l,i) = rate*delta3(l)*O2(i); 96 | end 97 | end 98 | 99 | w2 = w2_1+d_w2+rate2*2*(w2_1-w2_2); 100 | 101 | for i = 1:1:H 102 | %隐藏层输入 103 | dO2(i) = 1-tanh(I2(i))^2; 104 | end 105 | 106 | a = delta3*w2; 107 | 108 | for i = 1:1:H 109 | delta2(i) = dO2(i)*a(i); 110 | end 111 | 112 | d_w1 = rate*delta2'*I1; 113 | 114 | w1 = w1_1+d_w1+rate2*(w1_1-w1_2); 115 | 116 | %缓存本步参数 117 | u_1 = u(k); 118 | 119 | y_1 = y(k); 120 | 121 | w2_2 = w2_1; 122 | w2_1 = w2; 123 | 124 | w1_2 = w1_1; 125 | w1_1 = w1; 126 | 127 | error_5 = error_4; 128 | error_4 = error_3; 129 | error_3 = error_2; 130 | error_2 = error_1; 131 | error_1 = error(k); 132 | 133 | end 134 | 135 | %输出平均误差 136 | sum(abs(error))/k 137 | 138 | f1 = figure; 139 | f1.Position(1:2) = [0,350]; 140 | plot(time,x,'r',time,y,'b--',time,data); 141 | xlim(fx); 142 | xlabel('时间(6m)');ylabel('温度'); 143 | legend('目标','实际','环境'); 144 | grid on 145 | 146 | f2 = figure; 147 | f2.Position(1:2) = [500,350]; 148 | plot(time,u,'r'); 149 | xlim(fx); 150 | xlabel('时间(6m)');ylabel('控制量'); 151 | grid on 152 | 153 | f3 = figure; 154 | f3.Position(1:2) = [1000,350]; 155 | subplot(311); 156 | 157 | plot(time,kp,'r'); 158 | xlim(fx); 159 | xlabel('时间(6m)');ylabel('kp'); 160 | grid on 161 | subplot(312); 162 | 163 | plot(time,ki,'g'); 164 | xlim(fx); 165 | xlabel('时间(6m)');ylabel('ki'); 166 | grid on 167 | subplot(313); 168 | 169 | plot(time,kd,'b'); 170 | xlim(fx); 171 | xlabel('时间(6m)');ylabel('kd'); 172 | grid on 173 | -------------------------------------------------------------------------------- /generate.m: -------------------------------------------------------------------------------- 1 | %由每月最高温和最低温生成3588次温度变化 2 | data_O=[2 -13;7 -7;16 0;17 2;22 7]; 3 | data_N=[]; 4 | for i=1:5 5 | for j=1:30 6 | data_N=[data_N;data_O(i,1)+(20*rand-10),data_O(i,2)+(20*rand-10)]; 7 | end 8 | end 9 | data_temp=zeros(1,300); 10 | data_temp(1:2:end)=data_N(1:end,1); 11 | data_temp(2:2:end)=data_N(1:end,2); 12 | data=[]; 13 | for i=1:299 14 | data_rand = data_temp(i) + (data_temp(i+1)-data_temp(i)).*rand(1,11); 15 | if data_temp(i)>data_temp(i+1) 16 | data_rand = sort(data_rand,'descend'); 17 | else 18 | data_rand = sort(data_rand); 19 | end 20 | data = [data,data_temp(i) data_rand ]; 21 | end 22 | time=1:3588; 23 | plot(time,data); 24 | xlim([1,24]); 25 | ylim([-20,20]); 26 | 27 | data_temp=round(data*100)/100; 28 | writematrix(data_temp); 29 | data=round(data*100)/100; 30 | writematrix(data); -------------------------------------------------------------------------------- /generate2.m: -------------------------------------------------------------------------------- 1 | %数据插值生成35871次温度数据 2 | data=readmatrix('data.txt'); 3 | 4 | sizes=3588; 5 | time=1:sizes; 6 | x=1:0.1:sizes; 7 | y=spline(time,data,x); 8 | 9 | plot(y); 10 | xlim([1 24]); 11 | datas=round(y*100)/100; 12 | writematrix(datas); -------------------------------------------------------------------------------- /pidctrl2.m: -------------------------------------------------------------------------------- 1 | clear; 2 | close all; 3 | 4 | data = readmatrix("datas.txt"); 5 | 6 | % 定义模型参数 7 | Kp = 0.5; % 比例增益 8 | Ki = 0.1; % 积分增益 9 | Kd = 0.01; % 微分增益 10 | T = 1; % 控制周期 11 | Tf = 1; % 热传递时间常数 12 | Tamb = data(1:35001); % 环境温度 13 | Qloss = 0.1; % 每6m的热损失 14 | 15 | % 定义模拟时间和初始条件 16 | t = 0:1:35000; 17 | T0 = 7; 18 | 19 | % 初始化PID控制器 20 | e = 0; 21 | ei = 0; 22 | ed = 0; 23 | last_e = 0; 24 | 25 | % 开始模拟 26 | for i = 1:length(t) 27 | 28 | x(i)=20; 29 | % 计算误差 30 | e = 20 - T0(i); 31 | 32 | % 计算PID输出 33 | u = Kp*e + Ki*ei + Kd*ed; 34 | 35 | % 累加误差项 36 | ei = ei + e*T; 37 | 38 | % 计算微分项 39 | ed = (e - last_e)/T; 40 | 41 | % 更新上一次误差项 42 | last_e = e; 43 | 44 | % 计算下一个时刻的温度 45 | T1 = T0(i) + (u - Qloss*(T0(i)-Tamb(i)))/Tf; 46 | 47 | % 更新初始条件 48 | T0(i+1) = T1; 49 | end 50 | 51 | % 绘制温度随时间的变化曲线 52 | plot(t,x,'r',t,T0(1:end-1),'b--'); 53 | xlim([1 1000]); 54 | xlabel('时间 (6m)'); 55 | ylabel('温度 (C)'); 56 | title('PID 温控'); 57 | -------------------------------------------------------------------------------- /sigmoid.m: -------------------------------------------------------------------------------- 1 | % 定义sigmoid函数 2 | function g = sigmoid(z) 3 | % 计算sigmoid函数 4 | g = 1 ./ (1 + exp(-z)); 5 | end 6 | -------------------------------------------------------------------------------- /sigmoidGradient.m: -------------------------------------------------------------------------------- 1 | % 计算sigmoid函数的导数 2 | function g = sigmoidGradient(z) 3 | g = sigmoid(z) .* (1 - sigmoid(z)); 4 | end 5 | -------------------------------------------------------------------------------- /wi7956.txt: -------------------------------------------------------------------------------- 1 | -0.294876416010713,0.433367035373425,-0.280742763134625,-0.0849575312462127 2 | 0.295386865892225,0.102214607998047,0.384904384794935,0.0946665573399709 3 | -0.475530016677927,0.101176727619887,-0.451178016652787,-0.303204719616974 4 | -0.460220455796111,0.143866218140665,0.312039741124752,0.296091212333281 5 | 0.0298186359474254,0.421930576293345,-0.467408207719556,-0.289011782786303 6 | -------------------------------------------------------------------------------- /wo7956.txt: -------------------------------------------------------------------------------- 1 | -0.32558648149159,0.161564946484972,-0.119803249991751,0.40688653803507,0.060786270349853 2 | 0.113841779284192,-0.285101624834572,-0.465017715059097,0.368988066508274,-0.498911368598843 3 | 0.441056448782904,0.413589800435506,-0.272654901026853,0.0824686688705039,-0.373137886735174 4 | --------------------------------------------------------------------------------