Algorytm regulatora PID

Znalazlem na stronie Atmel'a fragment programu realizujacy regulator PID dla uC. Czy w linii 93 nie ma aby bledu? Wedlug mnie powinna ona wygladac raczej tak

d_term = pid_st->D_Factor * (processValue - pid_st->lastProcessValue);

czy ktos moze potwierdzic poprawnosc ktores z wersji?

00060 { 00061 int16_t error, p_term, d_term; 00062 int32_t i_term, ret, temp; 00063 00064 error = setPoint - processValue; 00065 00066 // Calculate Pterm and limit error overflow 00067 if (error > pid_st->maxError){ 00068 p_term = MAX_INT; 00069 } 00070 else if (error < -pid_st->maxError){ 00071 p_term = -MAX_INT; 00072 } 00073 else{ 00074 p_term = pid_st->P_Factor * error; 00075 } 00076 00077 // Calculate Iterm and limit integral runaway 00078 temp = pid_st->sumError + error; 00079 if(temp > pid_st->maxSumError){ 00080 i_term = MAX_I_TERM; 00081 pid_st->sumError = pid_st->maxSumError; 00082 } 00083 else if(temp < -pid_st->maxSumError){ 00084 i_term = -MAX_I_TERM; 00085 pid_st->sumError = -pid_st->maxSumError; 00086 } 00087 else{ 00088 pid_st->sumError = temp; 00089 i_term = pid_st->I_Factor * pid_st->sumError; 00090 } 00091 00092 // Calculate Dterm 00093 d_term = pid_st->D_Factor * (pid_st->lastProcessValue - processValue); 00094 00095 pid_st->lastProcessValue = processValue; 00096 00097 ret = (p_term + i_term + d_term) / SCALING_FACTOR; 00098 if(ret > MAX_INT){ 00099 ret = MAX_INT; 00100 } 00101 else if(ret < -MAX_INT){ 00102 ret = -MAX_INT; 00103 } 00104 00105 return((int16_t)ret); 00106 }

__________ Informacja programu ESET NOD32 Antivirus, wersja bazy sygnatur wirusow 5103 (20100510) __________

Wiadomosc zostala sprawdzona przez program ESET NOD32 Antivirus.

formatting link
lub
formatting link

Reply to
roxy
Loading thread data ...

Raczej jest dobrze

jesli wejscie jest ponizej wartosci zadanej - to mamy wyjscie dodatnie.

Jesli jednak sygnal wejsciowy [szybko] rosnie, to nalezy _zmiejszyc_ wartosc wyjsciowa.

i ten czlon bedzie wtedy ujemny.

J.

Reply to
J.F.

Albo tak: d_term = pid_st->D_Factor * (pid_st->lastProcessValue - processValue); ret = (p_term + i_term + d_term)

Albo tak: d_term = pid_st->D_Factor * (processValue - pid_st->lastProcessValue); ret = (p_term + i_term - d_term)

W tym algorytmie PID część różniczkująca jest obliczana jako pochodna wartości wyjściowej z obiektu, a nie jako pochodna uchybu. Ta modyfikacja powoduje to, iż nie mamy w sygnale wyjściowym z PID dużego piku wartości w momencie zmiany wartości zadanej.

Gdybyśmy obliczali część różniczkującą "tradycyjnie" (pochodna uchybu) wtedy trzeba by zmienić znak (czyli tak jak ty chciałeś to zrobić).

SM

Reply to
SM

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.