Hejże,
poradziłem sobie (tak mi się wydaje) z PID.
A mianowicie - Atmel (nie Atnel) udostępnia notę aplikacyjną wraz z całym kodem (króciutki) regulatora PID cyfrowego.
Nazwa noty to: "AVR221: Discrete PID controller"
link do noty na moim dropboxie:
https://dl.dropboxusercontent.com/u/608 ... oc2558.pdfi link do kodu:
https://dl.dropboxusercontent.com/u/608 ... avr221.zipInstrukcja: pid.h oraz pid.c dołączamy do naszego projektu. stdint.h nie musimy dołączać, już on jest w bibliotekach standardowych AVR (libc?).
Z pliku main.c kopiujemy obsługę przerwania, nastawy, strukturę i funkcje narzędziowe. Z funkcji main() również wszystko przenosimy.
Teraz tak: to nie jest proste copy-paste, bo musimy dopisać kilka rzeczy.
1) funkcja
Get_Reference(void): ma zwracać wartość zadaną (np. w regulacji temperatury zadaną (żądaną) temperaturę).
2) funkcja
Get_Measurement(void): ma zwracać wynik pomiarów na obiekcie (np. dane z czujnika temperatury)
3) funkcja
Set_Input(int16_t inputValue): ma wartość inputValue (wyliczoną uprzednio przez PID w pętli głównej) dawać na wejście obiektu, a dokładniej na element wykonawczy. Czyli np. na ogniwo Peltiera.
Trzeba pamiętać, że trzy powyższe funkcje operują na liczbach całkowitych (jak cała implementacja PID) i to 16-bitowych ze znakiem.
Więc jeżeli chcemy mieć słowo sterujące obiektem np. 8 bitowe bez znaku to musimy dokonać odpowiedniego przeskalowania.
Aha, jeszcze
TIME_INTERVAL => w komentarzach jest napisane co to jest (okres próbkowania w PID) i jak się liczy, może dopowiem tylko, że we wzorze tam trzeba uwzględnić częstotliwość w Hz już po preskalerze z timera odpowiedzialnego za PID.
Nastawy: co jeśli mamy Kp = 1.5? Przecież to liczba rzeczywista! No problemo, mądrzy ludzie z Atmela pomyśleli i mamy
SCALING_FACTOR który domyślnie jest równy 128 i każda nastawa (KP, KI, KD) jest przez niego mnożona. Więc sprawa jest prosta. 128*1 + 128*0.5 = 192. Całkowita liczba? Owszem.
Sama implementacja jest do bólu prosta, bardzo mało kodu i bardzo zrozumiała.
Nie rozumiem tylko po co jest funkcja
void pid_Reset_Integrator(pidData_t *pid_st) skoro nie jest nigdzie wywoływana.
Może do ręcznego resetu członu całkującego? Nie raz mi wpadł PID w nasycenie, może to wina złych nastaw, nie wiem, aż tak w tym zaawansowany nie jestem.
To taki mini-poradnik z mojej strony, bardziej tutorial niż poradnik jak to szybko użyć w swoim projekcie.
U mnie śmiga ładnie, ale jestem na etapie testów.
Wskazówka: reset regulatora można uzyskać poprzez jego ponowne zainicjalizowanie.
pozdrawiam
Jak moderator ma ochotę to może wydzielić moje wypociny do osobnego tematu-poradnika.