Сообщение от ua_gruzin
|
Спасибо всем за отклики.
Посидел, разбирался, чуть закодил.
Ниже екзешка. Прога котороя отрабатывает и отображает выход ПИД регулятора при изменении его параметров. К сожалению функция которая служит для отображения динамии процесса фиксирована.
Диапазон выходного воздействия сделан в диапазоне от минус величины "Диапазон ПИД" до плюс ее же.
Обратите внимание, что даже при воздействии ПИд-а не можно понизить температуру, или наоборот ее повысить. Температура идет по функции. К сожалению ПИД не может подавить мою функцию .
Посмотрите нету ли именно ошибок в сути работы ПИДа при разных параметров.
П.С. Вирусни и троянов нету. Сам не писал и не вставлял их туда. Прога собрана под Delphi7. На компу стоит НОД32 с обновлением постоянным. Думаю на счёт этого проблем не должно быть.
Прикрепленный файл: 2323796.zip
|
.
Скачал програмку, посмотрел графики...
Сделал аналогичный код для начальных условий, немного модифицировав исходники...
Получил почти аналогичные графики... Процедура 1 ...
Работает...
Код приведен ниже...
Delphi 7.0
.
Код:
|
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.Labe ledEdit1.Text);
Form1.LabeledEdit2.Text:=ChangeValPoint(Form1.Labe ledEdit2.Text);
Form1.LabeledEdit3.Text:=ChangeValPoint(Form1.Labe ledEdit3.Text);
Form1.LabeledEdit4.Text:=ChangeValPoint(Form1.Labe ledEdit4.Text);
Form1.LabeledEdit5.Text:=ChangeValPoint(Form1.Labe ledEdit5.Text);
Form1.LabeledEdit6.Text:=ChangeValPoint(Form1.Labe ledEdit6.Text);
Form1.LabeledEdit7.Text:=ChangeValPoint(Form1.Labe ledEdit7.Text);
Form1.LabeledEdit8.Text:=ChangeValPoint(Form1.Labe ledEdit8.Text);
Form1.LabeledEdit9.Text:=ChangeValPoint(Form1.Labe ledEdit9.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.Tex t);
max_integ_error:=StrToFloat(Form1.LabeledEdit9.Tex t);
// n:=200;
for i:=1 to n do
begin
f[i]:=Ku * fPID(i, 1.0);
Series1.AddXY(i, f[i]);
end;
// Uust:=10.0;
diapazon:=Uust;
// T0:=0.1;
// Kp:=1.0;
// Ki:=0.3;
// Kd:=0.1;
// min_integ_error:=-1.2;
// max_integ_error:=1.2;
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]);
// if ((min_integ_error ‹ ek) and (ek ‹ max_integ_error))
// then integral:=integral + ek
// else integral:=0.0;
integral:=integral + ek;
Uk:=Uk1 + Kp * ek + Ki * T0 * integral + (Kd * (ek - 2.0 * ek1 + ek2)) / T0;
// if (-1.0 * diapazon › Uk) then Uk:=-1.0 * diapazon;
// if (Uk › diapazon) then Uk:=diapazon;
// f2[i]:=Uk; // 30.0 * (1.0 - exp(-0.2 * Uk));
// -------------------------------------------------------------------
// Uk:=Uk + 0.1;
// Uk:=1.0 / (Uk * Uk + 1.0);
// Uk:=10.0 * sin((i - Uk) / 40.0);
f2[i]:=Uk;
Series2.AddXY(i, f2[i]);
f[i]:=Uust - Ku * fPID(i, Uk);
Series3.AddXY(i, f[i]);
ek2:=ek1;
ek1:=ek;
Uk:=f[i];
// Uk1:=Uk;
{ https://kazus.ru/forums/showthread.php?t=11558 }
{ https://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 * T0 * integral + (Kp * Kd / T0) * (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]:=Uust - Ku * fPID(i, Uk);
Series6.AddXY(i, f[i]);
Uk:=f[i];
ek2:=ek1;
ek1:=ek;
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%D 1%80 }
end;
end
else begin
Series5.Clear;
Series6.Clear;
Series7.Clear;
end;
Ti:=Kp * (T0 / Ki);
Td:=(Kd / Kp) * T0;
q0:=Kp * (1.0 + Td / T0);
q1:=(-1.0) * Kp * (1.0 + 2.0 * (Td / T0) - (T0 / Ti));
q2:=Kp * (Td / T0);
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]:=Uust - Ku * fPID(i, Uk);
Series9.AddXY(i, f[i]);
Uk:=f[i];
ek2:=ek1;
ek1:=ek;
Uk1:=Uk;
{ http://www.rlda.ru/PID_Control_Tutor.htm }
end;
end
else begin
Series8.Clear;
Series9.Clear;
Series10.Clear;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
Series1.Clear;
Series2.Clear;
Series3.Clear;
Series4.Clear;
Series5.Clear;
Series6.Clear;
Series7.Clear;
Series8.Clear;
Series9.Clear;
Series10.Clear;
DoChart;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
Close;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
LabeledEdit1.Text:=FloatToStr(10.00);
LabeledEdit2.Text:=FloatToStr(1.00);
LabeledEdit3.Text:=FloatToStr(0.30);
LabeledEdit4.Text:=FloatToStr(0.10);
LabeledEdit5.Text:=FloatToStr(0.10);
LabeledEdit6.Text:=IntToStr(200);
LabeledEdit7.Text:=FloatToStr(10.0);
LabeledEdit8.Text:=FloatToStr(-1.2);
LabeledEdit9.Text:=FloatToStr(1.2);
CheckBox1.State:=cbChecked;
CheckBox2.State:=cbChecked;
CheckBox3.State:=cbChecked;
end; |
.
Далее сделал PID регулятор, описанный здесь... Процедура 2 ...
http://ru.wikipedia.org/wiki/%D0%9F%...82%D0%BE%D1%80
.
А графики то получились совсем другие !!!
НО !!! Этот алгоритм взят с официального описания PID регулятора !!!
.
Далее сделал PID регулятор, описанный здесь... Процедура 3 ...
http://www.rlda.ru/PID_Control_Tutor.htm
.
Графики получились аналогичные, описанные на предыдущем шаге, но не на шаге № 1 ...
НО !!! Этот алгоритм взят с официального описания PID регулятора !!!
.
Внимание ворос ?
Какой алгоритм правильный ?
Что не правильно в реализации алгоритмов ?
Возможно в первой процедуре (первый цикл PID, TCheckBox1), возможно, не хватает следующей строки в конце цикла, строка закоментирована, в оригинальном алгоритме, представленным здесь на форуме, данной строки не было...
Uk1:=Uk; { U(k-1):=U(k) }