1. 程式人生 > >使用粒子群PSO演算法實現MPPT-M語言模擬

使用粒子群PSO演算法實現MPPT-M語言模擬

在Octave上,模擬了使用粒子群PSO實現MPPT的過程。

目錄

本文主要是程式碼。可以在Octave上執行。我的軟體環境是winxp(32bit),Octave4.4.0。

1、先繪製出PV曲線

光伏電阻串聯的方法如下圖。每個光伏電池都有各自的反向並聯二極體。此處二極體的作用是保護光伏電池避免經過大電流,造成過度發熱。

程式碼中模擬得到了,由4個光伏電池串聯成的光伏電池組特性曲線,如下圖。

紅色線代表理想情況下的曲線。而藍色線是串聯起來的光伏電池組的PV特性曲線。沒達到理想曲線的原因是,每個光伏電池都受到不同程度的遮擋。以下是程式碼。

clear
clc

%-----------------------------------------------
%-----------------------------------------------
%pannel in series
%first pannel
S_1=1000;
Tair_1=25;

Sref=1000;  %1000W/m^2
Tref=25;    %25degree celcius

Uoc=44.2;
Um=35.4;
Isc=5.29;
Im=4.95;

a=0.00255;
b=0.55;
c=0.00285;

T_1 = Tair_1 + 0.028*S_1;
T_delta_1 = T_1 - Tref;
S_delta_1 = S_1/Sref - 1;

Isc_comp_1 = Isc*S_1/Sref*(1+a*T_delta_1);
Uoc_comp_1 = Uoc*(1-c*T_delta_1)*log(e+b*S_delta_1);
Im_comp_1  = Im*S_1/Sref*(1+a*T_delta_1);
Um_comp_1  = Um*(1-c*T_delta_1)*log(e+b*S_delta_1);

C2_1=(Um_comp_1/Uoc_comp_1-1)*(log(1-Im_comp_1/Isc_comp_1))^(-1);
C1_1=(1-Im_comp_1/Isc_comp_1)*exp(-Um_comp_1/(C2_1*Uoc_comp_1));

U_1=0:0.01:Uoc_comp_1;
Iph_1=Isc_comp_1*(1-C1_1*(exp(U_1/(C2_1*Uoc_comp_1))-1));


%-----------------------------------------------
%second pannel
S_2=800;
Tair_2=25;

Sref=1000;  %1000W/m^2
Tref=25;    %25degree celcius

Uoc=44.2;
Um=35.4;
Isc=5.29;
Im=4.95;

a=0.00255;
b=0.55;
c=0.00285;

T_2 = Tair_2 + 0.028*S_2;
T_delta_2 = T_2 - Tref;
S_delta_2 = S_2/Sref - 1;

Isc_comp_2 = Isc*S_2/Sref*(1+a*T_delta_2);
Uoc_comp_2 = Uoc*(1-c*T_delta_2)*log(e+b*S_delta_2);
Im_comp_2  = Im*S_2/Sref*(1+a*T_delta_2);
Um_comp_2  = Um*(1-c*T_delta_2)*log(e+b*S_delta_2);

C2_2=(Um_comp_2/Uoc_comp_2-1)*(log(1-Im_comp_2/Isc_comp_2))^(-1);
C1_2=(1-Im_comp_2/Isc_comp_2)*exp(-Um_comp_2/(C2_2*Uoc_comp_2));

U_2=0:0.01:Uoc_comp_2;
Iph_2=Isc_comp_2*(1-C1_2*(exp(U_2/(C2_2*Uoc_comp_2))-1));



%-----------------------------------------------
%third pannel
S_3=600;
Tair_3=25;

Sref=1000;  %1000W/m^2
Tref=25;    %25degree celcius

Uoc=44.2;
Um=35.4;
Isc=5.29;
Im=4.95;

a=0.00255;
b=0.55;
c=0.00285;

T_3 = Tair_3 + 0.028*S_3;
T_delta_3 = T_3 - Tref;
S_delta_3 = S_3/Sref - 1;

Isc_comp_3 = Isc*S_3/Sref*(1+a*T_delta_3);
Uoc_comp_3 = Uoc*(1-c*T_delta_3)*log(e+b*S_delta_3);
Im_comp_3  = Im*S_3/Sref*(1+a*T_delta_3);
Um_comp_3  = Um*(1-c*T_delta_3)*log(e+b*S_delta_3);

C2_3=(Um_comp_3/Uoc_comp_3-1)*(log(1-Im_comp_3/Isc_comp_3))^(-1);
C1_3=(1-Im_comp_3/Isc_comp_3)*exp(-Um_comp_3/(C2_3*Uoc_comp_3));

U_3=0:0.01:Uoc_comp_3;
Iph_3=Isc_comp_3*(1-C1_3*(exp(U_3/(C2_3*Uoc_comp_3))-1));



%-----------------------------------------------
%forth pannel
S_4=400;
Tair_4=25;

Sref=1000;  %1000W/m^2
Tref=25;    %25degree celcius

Uoc=44.2;
Um=35.4;
Isc=5.29;
Im=4.95;

a=0.00255;
b=0.55;
c=0.00285;

T_4 = Tair_4 + 0.028*S_4;
T_delta_4 = T_4 - Tref;
S_delta_4 = S_4/Sref - 1;

Isc_comp_4 = Isc*S_4/Sref*(1+a*T_delta_4);
Uoc_comp_4 = Uoc*(1-c*T_delta_4)*log(e+b*S_delta_4);
Im_comp_4  = Im*S_4/Sref*(1+a*T_delta_4);
Um_comp_4  = Um*(1-c*T_delta_4)*log(e+b*S_delta_4);

C2_4=(Um_comp_4/Uoc_comp_4-1)*(log(1-Im_comp_4/Isc_comp_4))^(-1);
C1_4=(1-Im_comp_4/Isc_comp_4)*exp(-Um_comp_4/(C2_4*Uoc_comp_4));

U_4=0:0.01:Uoc_comp_4;
Iph_4=Isc_comp_4*(1-C1_4*(exp(U_4/(C2_4*Uoc_comp_4))-1));

plot(U_1,Iph_1)
plot(U_2,Iph_2)
plot(U_3,Iph_3)
plot(U_4,Iph_4)
%-----------------------------------------------
% 4 in series
% U=C2*Uoc*log((Isc-I)/(C1*Isc)+1)
%Iph_1 > Iph_2 > Iph_3


U_s = 0:0.01:Uoc_comp_1*4;
Iph_s=Isc_comp_1*(1-C1_1*(exp(U_s/(C2_1*Uoc_comp_1*4))-1));
plot(U_s,Iph_s,'k')

U_ss = zeros(1,size(U_1)(2)+size(U_2)(2)+size(U_3)(2)+size(U_4)(2));
Iph_ss = U_ss;
%for i = 1 : size(U_1)(2)
%    U_ss(i) = U_1(i);
%    Iph_ss(i) = Iph_1(i);
%end


for i = 1 : size(U_1)(2)
    if Iph_1(i)>=Iph_2(1)
        U_ss(i) = U_1(i);
        Iph_ss(i) = Iph_1(i);
        step1 = i;
    else
        break;
    end
end
for i = 1 : size(U_2)(2)
    if Iph_2(i)>Iph_3(1)
        U_ss(step1+i) = U_2(i) + U_ss(step1);
        Iph_ss(step1+i) = Iph_2(i);
        step2 = step1+i;
    else
        break;
    end
end
for i = 1 : size(U_3)(2)
    if Iph_3(i)>Iph_4(1)
        U_ss(step2+i) = U_3(i) + U_ss(step2);
        Iph_ss(step2+i) = Iph_3(i);
        step3 = step2+i;
    else
        break;
    end
end
for i = 1 : size(U_4)(2)
    U_ss(step3+i) = U_ss(step3) + U_4(i);
    Iph_ss(step3+i) = Iph_4(i);
end

%plot(U_1,Iph_1)               I-U
%plot(U_2,Iph_2)
%plot(U_ss,Iph_ss,'+')
%plot(U_ss,Iph_ss,'+')

figure(1)
plot(U_ss,Iph_ss,'+')
xlabel('U/V')
ylabel('I/A')
title('U-I')
figure(2)
P_ss = U_ss .* Iph_ss;
plot(U_ss,P_ss)
xlabel('U/V')
ylabel('P/W')
title('U-W')
hold on
P_1 = U_1*4 .* Iph_1;
plot(U_1*4,P_1)


執行完以後,會得到電壓電流特性曲線見figure(1)和電壓功率特性曲線見figure(2),還有好多引數在工作區內。

function result=GetResult_P_from_PUcurv(Voutput,P_ss)
    if  round(Voutput*100)==0
        result = P_ss(1);
    else
        result=P_ss(round(Voutput*100));    
    end
endfunction

把這函式存成GetResult_P_from_PUcurv.m,放在工作目錄內。

這函式功能是根據工作電壓,查表得到當前的輸出功率。在實際專案中,這個功率是經過電壓電流取樣計算得到。

2、PSO演算法

演算法的作用是,在PV曲線中均勻佈防4只個體。4只個體會共享資料,並能引導群體往最優值靠近。因此並不會陷入區域性最優,可以找到整體最優解。

% initialize
currentN = 1;
maxN = 100;
%2. 
N=4;
Uoc_module = Uoc;
Uoc_array = Uoc * N;
v_i = 0.25/(N-1)*Uoc_module;
x_max = 0.95 * Uoc_array;
v_max = Uoc_module;


i=1;
Vo_1 = 0.7* i*Uoc_module;    %i<N
i=2;
Vo_2 = 0.7* i*Uoc_module;    %i<N
i=3;
Vo_3 = 0.7* i*Uoc_module;    %i<N
i=4;
Vo_4 = 0.7* Uoc_array;          %i=N;
Uoc_array = Uoc * N;
v_i = 0.25/(N-1)*Uoc_module;
x_max = 0.95 * Uoc_array;
v_max = 3;

P_1_max = 0;
P_2_max = 0;
P_3_max = 0;
P_4_max = 0;
Power_1_max = 0;
Power_2_max = 0;
Power_3_max = 0;
Power_4_max = 0;
f_g = 0;
f_g_voltage =0;
c1_begin = 2.7;
c1_end = 1.2;
c2_begin = 0.5;
c2_end = 2.2;

v_1 = 0.25/(N-1)*Uoc_module;
v_2 = 0.25/(N-1)*Uoc_module;
v_3 = 0.25/(N-1)*Uoc_module;
v_4 = 0.25/(N-1)*Uoc_module;

%----------------------------------------------------------------------
Power_1 = GetResult_P_from_PUcurv(Vo_1,P_ss);
Power_2 = GetResult_P_from_PUcurv(Vo_2,P_ss);
Power_3 = GetResult_P_from_PUcurv(Vo_3,P_ss);
Power_4 = GetResult_P_from_PUcurv(Vo_4,P_ss);
Power_N = [Power_1,Power_2,Power_3,Power_4]
Vo_N = [Vo_1, Vo_2, Vo_3, Vo_4];
disp(currentN)
disp(Vo_N);
disp(Power_N);
    

for currentN = 1 : maxN-1

    
    r1 = rand();
    r2 = rand();
    c1 = c1_begin + (c1_end - c1_begin)*(1-acos(-2*currentN/maxN+1)/pi);
    c2 = c2_begin + (c2_end - c2_begin)*(1-acos(-2*currentN/maxN+1)/pi);
    

    %f_avg = sum(f_i)/N;   //paticle power average
    %f_avg = (P_1+ P_2 + P_3 + P_4)/4;
    f_avg = sum(Power_N)/N;
    if f_g < max(Power_N)
        f_g = max(Power_N);
        for j=1:N
            if Power_N(j) == max(Power_N)
                f_g_voltage = Vo_N(j);
            endif
        endfor
    endif
    
    phi = abs(f_g-f_avg);   %f_g: the optimized one
    
    f_1 = Power_1;
    w_1=abs((f_1-f_avg)/phi);
    f_2 = Power_2;
    w_2=abs((f_2-f_avg)/phi);
    f_3 = Power_3;
    w_3=abs((f_3-f_avg)/phi);
    f_4 = Power_4;
    w_4=abs((f_4-f_avg)/phi);
    w_N = [w_1, w_2, w_3, w_4];
    

    if Power_1_max < Power_1
        P_1_max = Vo_1;
        Power_1_max = Power_1;
    end
    if Power_2_max < Power_2
        P_2_max = Vo_2;
        Power_2_max = Power_2;
    end
    if Power_3_max < Power_3
        P_3_max = Vo_3;
        Power_3_max = Power_3;
    end
    if Power_4_max < Power_4
        P_4_max = Vo_4;
        Power_4_max = Power_4;
    end
    P_N_max = [P_1_max, P_2_max, P_3_max, P_4_max];
    Power_N_max = [Power_1_max, Power_2_max, Power_3_max, Power_4_max];
    
    v_1_next = w_1 * v_1 + c1*r1*(P_1_max - Vo_1) + c2*r2*(f_g_voltage - Vo_1);
    v_2_next = w_2 * v_2 + c1*r1*(P_2_max - Vo_2) + c2*r2*(f_g_voltage - Vo_2);
    v_3_next = w_3 * v_3 + c1*r1*(P_3_max - Vo_3) + c2*r2*(f_g_voltage - Vo_3);
    v_4_next = w_4 * v_4 + c1*r1*(P_4_max - Vo_4) + c2*r2*(f_g_voltage - Vo_4);
    

    if v_1_next > v_max
        v_1_next = v_max;
    end
    if v_1_next < -v_max
        v_1_next = -v_max;
    end
    if v_2_next > v_max
        v_2_next = v_max;
    end
    if v_2_next < -v_max
        v_2_next = -v_max;
    end
    if v_3_next > v_max
        v_3_next = v_max;
    end
    if v_3_next < -v_max
        v_3_next = -v_max;
    end
    if v_4_next > v_max
        v_4_next = v_max;
    end
    if v_4_next < -v_max
        v_4_next = -v_max;
    end
    v_N_next = [v_1_next, v_2_next, v_3_next, v_4_next];
    
    
    
    Vo_1 = Vo_1 + v_1_next;
    Vo_2 = Vo_2 + v_2_next;
    Vo_3 = Vo_3 + v_3_next;
    Vo_4 = Vo_4 + v_4_next;
    if Vo_1 < 0
        Vo_1 = 0;
    end
    if Vo_2 < 0
        Vo_2 = 0;
    end
    if Vo_3 < 0
        Vo_3 = 0;
    end
    if Vo_4 < 0
        Vo_4 = 0;
    end
        
    if Vo_1 > 0.95*Uoc_array
        Vo_1 = 0.95*Uoc_array;
    end
    if Vo_2 > 0.95*Uoc_array
        Vo_2 = 0.95*Uoc_array;
    end
    if Vo_3 > 0.95*Uoc_array
        Vo_3 = 0.95*Uoc_array;
    end
    if Vo_4 > 0.95*Uoc_array
        Vo_4 = 0.95*Uoc_array;
    end  
    
    
    Power_1 = GetResult_P_from_PUcurv(Vo_1,P_ss);
    Power_2 = GetResult_P_from_PUcurv(Vo_2,P_ss);
    Power_3 = GetResult_P_from_PUcurv(Vo_3,P_ss);
    Power_4 = GetResult_P_from_PUcurv(Vo_4,P_ss);
    Power_N = [Power_1,Power_2,Power_3,Power_4]
    Vo_N = [Vo_1, Vo_2, Vo_3, Vo_4];
    disp(currentN)
    disp('P_N_max: individual output voltage of maximum power')
    disp(P_N_max);
    disp('Power_N_max: individual maximum power output')
    disp(Power_N_max)
    disp('f_g: global max')
    disp(f_g)
    
    
    disp('v_N_next')
    disp(v_N_next)
    
    disp('Vo_N: output voltage')
    disp(Vo_N);
    disp('power_N: output power')
    disp(Power_N);


    figure(3)
    clf
    plot(Vo_N, Power_N,'d')   
    axis([0 200 0 400]) 
    xlabel('U/V')
    ylabel('P/W')
    title('U-W')

    %disp('v_N_next')
    %disp(v_N_next)
    v_1 = v_1_next;
    v_2 = v_2_next;
    v_3 = v_3_next;
    v_4 = v_4_next;

    v_N = [v_1, v_2, v_3, v_4];
    
    differ = (abs(Vo_1-sum( Vo_N)/N) + abs(Vo_2-sum( Vo_N)/N) + abs(Vo_2-sum( Vo_N)/N) + abs(Vo_4-sum( Vo_N)/N))
    
    
    if differ< (0.01*Uoc_array)
        break;
    end
    
        
end



%v_i_next = w*v_i_k + c1*r1*(P_max - V_i_output) + c2*r2*(G_max - V_i_output);
plot(f_g_voltage, f_g, 'k+')
	

3、模擬結果

初始化將4個個體均勻放置在曲線上。

第7次迭代計算:

第13次迭代計算:

第14次迭代計算:

我每次只允許個體改變2V電壓,因此速度有點慢。

第33次迭代計算,個體的差異低於設定值1.768V,因此結束計算: