Вот реализация ПИД алгоритма.
В процедуре DoChart 4-е цикла с разными реализациями ПИД алгоритма.
Язык программирования Delphi 7.0 .
Функция для регулироания fPID внутри процедуры DoChart.
Для тестирования и применения в ваших программах.
.
Код
function TForm1.ChangeValPoint(s : String) : String;
var
i : Integer;
begin
Result:=s;
i:=Length(s);
while (i > 0) and (Result[i] <> '.') do Dec(i);
if (i > 0) then Result[i]:=',';
end;
procedure TForm1.DoChart;
var
f : array[1..4000] of Real;
f1 : array[1..4000] of Real;
f2 : array[1..4000] of Real;
f3 : array[1..4000] of Real;
A, B : Real;
i : Integer;
n : integer;
min_integ_error,
max_integ_error,
integral : Real;
diapazon : Real;
T0 : Real; { Ïåðèîä êâàíòîâàíèÿ (äèñêðåòèçàöèè) }
Ti : Real; { Ïîñòîÿííàÿ èíòåãðèðîâàíèÿ }
Td : Real; { Ïîñòîÿííàÿ äèôåðåíöèðîâàíèÿ }
q0 : Real;
q1 : Real;
q2 : Real;
Uk : Real; { Òåêóùåå çíà÷åíèå U(k) }
Uk1 : Real; { Ïðåäûäóùåå çíà÷åíèå U(k-1) }
ek : Real; { Òåêóùåå çíà÷åíèå îøèáêè e(k) }
ek1 : Real; { Ïðåäûäóùåå çíà÷åíèå îøèáêè e(k-1) }
ek2 : Real; { Ïðåäûäóùåå çíà÷åíèå îøèáêè íà äâà øàãà íàçàä e(k-2) }
Uust : Real; { Çíà÷åíèå óñòàâêè (âõîäíîé âåëå÷èíû) }
Kp : Real;
Ki : Real;
Kd : Real;
Ku : Real;
function fPID(i : Integer; Uk : Real) : Real;
begin
B:=0.2;
A:=i / 10.0;
// Result:=Uk * ((1.0 / A) / (B + 1.0 / A));
// t:=(i - 1) / 250000.0;
// f[i]:=k * (1.0 - Exp(-1.0 * t / Tau));
// Result:=10.0 * sin(((i - 1) - Uk) / 40.0);
Result:=sin(((i - 1) - Uk) / 40.0);
end;
begin
{ Series1 - Ôóíêöèÿ äëÿ ðåãóëèðîâàíèÿ }
{ Series2 - PID }
{ Series3 - PID + Ôóíêöèÿ ðåãóëèðîâàíèÿ }
{ Series4 - Îøèáêà }
Form1.LabeledEdit1.Text:=ChangeValPoint(Form1.LabeledEdit1.Text);
Form1.LabeledEdit2.Text:=ChangeValPoint(Form1.LabeledEdit2.Text);
Form1.LabeledEdit3.Text:=ChangeValPoint(Form1.LabeledEdit3.Text);
Form1.LabeledEdit4.Text:=ChangeValPoint(Form1.LabeledEdit4.Text);
Form1.LabeledEdit5.Text:=ChangeValPoint(Form1.LabeledEdit5.Text);
Form1.LabeledEdit6.Text:=ChangeValPoint(Form1.LabeledEdit6.Text);
Form1.LabeledEdit7.Text:=ChangeValPoint(Form1.LabeledEdit7.Text);
Form1.LabeledEdit8.Text:=ChangeValPoint(Form1.LabeledEdit8.Text);
Form1.LabeledEdit9.Text:=ChangeValPoint(Form1.LabeledEdit9.Text);
Uust:=StrToFloat(Form1.LabeledEdit1.Text);
Kp:=StrToFloat(Form1.LabeledEdit2.Text);
Ki:=StrToFloat(Form1.LabeledEdit3.Text);
Kd:=StrToFloat(Form1.LabeledEdit4.Text);
T0:=StrToFloat(Form1.LabeledEdit5.Text);
n:=StrToInt(Form1.LabeledEdit6.Text);
Ku:=StrToFloat(Form1.LabeledEdit7.Text);
min_integ_error:=StrToFloat(Form1.LabeledEdit8.Text);
max_integ_error:=StrToFloat(Form1.LabeledEdit9.Text);
// n:=200;
for i:=1 to n do
begin
f[i]:=Ku * fPID(i, 0.0);
Series1.AddXY(i, f[i]);
end;
diapazon:=Uust;
Uk:=0.0;
Uk1:=0.0;
ek:=0.0;
ek1:=0.0;
ek2:=0.0;
integral:=0.0;
if (CheckBox1.State = cbChecked) then begin
for i:=1 to n do
begin
ek:=Uust - Uk;
f1[i]:=ek;
Series4.AddXY(i, f1[i]);
// integral:=integral + ek;
if ((min_integ_error < ek) and (ek < max_integ_error))
then integral:=integral + ek
else integral:=0.0;
Uk:=Kp * ek + Ki * integral * T0 + (Kd * (ek - 2.0 * ek1 + ek2)) / T0;
// Uk:=Kp * ek + Ki * integral + (Kd * (ek - 2.0 * ek1 + ek2));
if (-1.0 * diapazon > Uk) then Uk:=-1.0 * diapazon;
if (Uk > diapazon) then Uk:=diapazon;
f2[i]:=Uk;
Series2.AddXY(i, f2[i]);
f[i]:=Ku * fPID(i, Uk);
Series3.AddXY(i, f[i]);
ek2:=ek1;
ek1:=ek;
Uk:=f[i];
{ http://kazus.ru/forums/showthread.php?t=11558 }
{ http://kazus.ru/forums/showthread.php?t=11558&page=4 }
end;
end
else begin
Series2.Clear;
Series3.Clear;
Series4.Clear;
end;
Uk:=0.0;
Uk1:=0.0;
ek:=0.0;
ek1:=0.0;
ek2:=0.0;
integral:=0.0;
if (CheckBox2.State = cbChecked) then begin
for i:=1 to n do
begin
ek:=Uust - Uk;
f1[i]:=ek;
Series7.AddXY(i, f1[i]);
integral:=ek;
if ((min_integ_error < integral) and (integral < max_integ_error))
then integral:=integral
else integral:=0.0;
Uk:=Uk1 + Kp * (ek - ek1) + Kp * Ki * integral + Kp * Kd * (ek - 2.0 * ek1 + ek2);
if ((-1.0 * diapazon) > Uk) then Uk:=-1.0 * diapazon;
if (Uk > diapazon) then Uk:=diapazon;
f2[i]:=Uk;
Series5.AddXY(i, f2[i]);
f[i]:=Ku * fPID(i, Uk);
Series6.AddXY(i, f[i]);
ek2:=ek1;
ek1:=ek;
Uk:=f[i];
Uk1:=Uk;
{ http://ru.wikipedia.org/wiki/%D0%9F%D0%98%D0%94-%D1%80%D0%B5%D0%B3%D1%83%D0%BB%D1%8F%D1%82%D0%BE%D1%80 }
end;
end
else begin
Series5.Clear;
Series6.Clear;
Series7.Clear;
end;
{ Ñêîðîñòíîé ìåòîä }
q0:=Kp * (1.0 + Kd);
q1:=Kp * (-1.0 - 2.0 * Kd + Ki);
q2:=Kp * Kd;
Uk:=0.0;
Uk1:=0.0;
ek:=0.0;
ek1:=0.0;
ek2:=0.0;
if (CheckBox3.State = cbChecked) then begin
for i:=1 to n do
begin
ek:=Uust - Uk;
f1[i]:=ek;
Series10.AddXY(i, f1[i]);
Uk:=Uk1 + q0 * ek + q1 * ek1 + q2 * ek2;
if (-1.0 * diapazon > Uk) then Uk:=-1.0 * diapazon;
if (Uk > diapazon) then Uk:=diapazon;
f2[i]:=Uk;
Series8.AddXY(i, f2[i]);
f[i]:=Ku * fPID(i, Uk);
Series9.AddXY(i, f[i]);
ek2:=ek1;
ek1:=ek;
Uk:=f[i];
Uk1:=Uk;
{ http://www.rlda.ru/PID_Control_Tutor.htm }
end;
end
else begin
Series8.Clear;
Series9.Clear;
Series10.Clear;
end;
{ Ìåòîä òðàïåöèè }
q0:=Kp * (1.0 + 0.5 * Ki + Kd);
q1:=Kp * (-1.0 - 2.0 * Kd + 0.5 * Ki);
q2:=Kp * Kd;
Uk:=0.0;
Uk1:=0.0;
ek:=0.0;
ek1:=0.0;
ek2:=0.0;
if (CheckBox4.State = cbChecked) then begin
for i:=1 to n do
begin
ek:=Uust - Uk;
f1[i]:=ek;
Series13.AddXY(i, f1[i]);
Uk:=Uk1 + q0 * ek + q1 * ek1 + q2 * ek2;
if (-1.0 * diapazon > Uk) then Uk:=-1.0 * diapazon;
if (Uk > diapazon) then Uk:=diapazon;
f2[i]:=Uk;
Series11.AddXY(i, f2[i]);
f[i]:=Ku * fPID(i, Uk);
Series12.AddXY(i, f[i]);
ek2:=ek1;
ek1:=ek;
Uk:=f[i];
Uk1:=Uk;
{ http://www.rlda.ru/PID_Control_Tutor.htm }
end;
end
else begin
Series11.Clear;
Series12.Clear;
Series13.Clear;
end;
end;
Сообщение отредактировал Jenyok2 - Oct 9 2011, 16:43