Jak zaimplementować regulator PID dla silnika z enkoderem?

Jak zaimplementować regulator PID dla silnika z enkoderem?

W artykule przedstawię proces projektowania regulatora PID do kontroli prędkości silnika DC wyposażonego w enkoder.

Najpierw zajmiemy się identyfikacją modelu silnika. Następnie dostroimy dla niego regulator PID, po czym sprawdzimy go w praktyce.

Wykorzystany sprzęt oraz oprogramowanie

W artykule wykorzystałem następujące elementy:

Kod na STM32 został napisany w środowisku Eclipse. Struktura programu jest podobna jak w moich wcześniejszych artykułach. Na mikrokontrolerze działa system FreeRTOS, a poszczególne zadania wykonywane są w wątkach. Do identyfikacji modelu transmitancyjnego silnika i zaprojektowania regulatora PID wykorzystałem środowisko MATLAB R2014a oraz pakiet Simulink wchodzący w jego skład.

Niezbędna teoria

Naszym obiektem sterowania jest silnik. Możemy nim sterować w pętli otwartej:

sch_open

Sterowanie w pętli otwartej

Gdzie u(t) to nasz sygnał wejściowy będący wartością sterowania podaną na silnik. Najczęściej jest to wypełnienie PWM. Natomiast y(t) to sygnał wyjściowy, którym jest prędkość obrotów silnika. Możemy ją odczytać za pomocą enkodera.

W tym wypadku w programie ustawiamy bezpośrednio wartość sterowania silnika. Dla tego samego sterowania prędkość może być różna w zależności od obciążenia. Program nie ma więc bezpośrednio kontroli nad prędkością silnika.

Przy sterowaniu w pętli otwartej podajemy pewną wartość na silnik wierząc, że spowoduje ona pojawienie się odpowiedniej wartości na wyjściu. Nie mamy jednak pewności, czy sterowanie odniosło pożądany skutek. Alternatywą jest sterowanie w pętli zamkniętej:

sch_closed

Sterowanie w pętli zamkniętej

Gdzie r(t) to sygnał zadany, czyli wartość prędkości, jaką chcieli byśmy uzyskać na wyjściu. Natomiast e(t) to uchyb sterowania czyli różnica między sygnałem zadanym, a sygnałem wyjściowym.

Tym razem w programie ustawiamy wartość prędkości, jaką chcieli byśmy zaobserwować na wyjściu. Regulator na podstawie sygnału uchybu dobierze odpowiednie sterowanie. W tym wypadku, jeśli zmieni się obciążenie silnika, zmieni się także sygnał sterujący.

Regulator PID jest implementowany za pomocą następującego wyrażenia:

Współczynniki kp, ki i kd, to parametry regulatora (człon proporcjonalny, całkujący i różniczkujący), e_sum to suma wszystkich wartości uchybu od początku sterowania, e_last to wartość uchybu z poprzedniej chwili czasu.

Pomiar charakterystyki silnika

Do pomiaru charakterystyki silnika potrzebujemy programu składającego się z:

  • obsługi sterowania silnikiem
  • obsługi enkodera
  • akwizycji danych

Sterowanie silnikiem zostało zrealizowane na timerze TIM2 odpowiedzialnym za generowanie sygnału PWM i dwóch wyjściach sterujących. Timer TIM3 został ustawiony w Encoder Mode z inkrementacją na zboczu rosnącym i opadającym na obu kanałach.

Dane dotyczące aktualnego sterowania podanego na silnik i wartości odczytanej z enkoderów są wysyłane do komputera przez USART połączony z modułem Bluetooth. Dane binarne zostały zapisane do pliku za pomocą programu RS-232 Data Logger, a następnie przekonwertowane do formatu tekstowego jako dwie kolumny pomiarów. Wyniki przedstawia wykres.

plot_motor1

Odpowiedź skokowa silnika w pętli otwartej

Z pobranych danych możemy wyznaczyć odpowiedź skokową. W tym celu posłużymy się skryptem matlabowym:

Skrypt wczytuje dane z pliku i tworzy z nich strukturę iddata z czasem próbkowania 0.005. Ważne tutaj jest określenie ile pierwszych próbek znajduje się przed skokiem sygnału sterującego i odpowiednie skrócenie podawanych wektorów. U mnie nie branych pod uwagę jest 19 pierwszych próbek. Następnie funkcja tfest dopasowuje optymalny model do danych pomiarowych.

Ustawiony model zawiera jeden biegun i zero zer oraz czas próbkowania 0.005. Dalsza część skryptu rysuje na wykresie odpowiedź skokową wyznaczonego modelu i realnego układu.

simulink_open_loop1

Model otwartej pętli sterowania w Simulinku

Aby porównać otrzymany model z danymi rzeczywistymi, utworzyłem model pętli otwartej w Simulinku, a wynik naniosłem na jeden wykres z danymi pomiarowymi. Parametry transmitancji wziąłem ze zmiennej motor_tf ze skryptu. Wysokość sygnału skokowego ustawiłem na 50 zgodnie z sygnałem pobudzającym wykorzystanym w pomiarach.

plot_est_real

Porównanie danych pomiarowych i symulacji w Simulinku dla pętli otwartej

Analizując wykres widzimy, że identyfikacja modelu zakończyła się sukcesem. Oba wykresy są do siebie bardzo podobne.

Projekt regulatora PID

Do doboru nastaw regulatora PID posłużymy się automatycznym tunerem wchodzącym w skład Matlaba. W tym celu należy stworzyć w Simulinku model pętli zamkniętej układu:

simulink_closed_loop

Model w Simulinku dla pętli zamkniętej

Tym razem wysokość sygnału skokowego ustawiłem na 11. W poprzednim przypadku sygnał skokowy był wyrażony w procentach wypełnienia PWM. Teraz jest to prędkość wyrażona jako ilość ticków enkodera na jednostkę czasu równą okresowi próbkowania - 5ms. We wszystkich elementach modelu i opcjach symulacji próbkowanie ustawiłem na 0.005.

Po otwarciu właściwości bloku PID otworzy nam się następujące okno:

okno_pid

Okno bloku PID w Simulinku

Na czerwono zaznaczyłem wybór rodzaju regulatora (np. PI, PD, PID), pole czasu próbkowania, pola z parametrami P, I, D, wykorzystywany wzór regulatora PID oraz przycisk Tune.

W tym oknie możemy ręcznie modyfikować wartości parametrów i sprawdzać jaki mają wpływ na jakość sterowania. W zakładce PID Advanced należy ustawić Output saturation na wartości 100 i -100. Jest to ograniczenie sygnału sterującego związane z maksymalnymi wartościami PWM. Następnie klikamy przycisk Tune. Ukaże nam się następujące okno:

okno_tuner

PID tuner

Za pomocą suwaków możemy tutaj modyfikować szybkość odpowiedzi skokowej układu zamkniętego. Krótszy czas ustalania wiąże się z większym przeregulowaniem.

Po osiągnięciu zadowalającej charakterystyki klikamy Update block i parametry PID zostają zaktualizowane. Moje wartości to P = 5.94, I = 347.19 i D = -0.03. Warto zauważyć, że wartości I oraz D są znormalizowane względem czasu próbkowania. Widać to na wzorze w oknie bloku PID. Tak więc wartość I jest mnożona przez czas próbkowania, a wartość D dzielona.

Obliczone wartości wprowadziłem do programu na STM, który został rozszerzony o obliczanie sterowania za pomocą algorytmu PID. Porównanie wyników w pętli otwartej i w pętli zamkniętej z nastrojonym PID prezentuje wykres:

plot_pid_compare

Porównanie sterowania w pętli otwartej(niebieski) i w pętli zamkniętej z PID(czerwony)

Podsumowanie

W artykule przedstawiłem sposób projektowania regulatora PID dla silnika z enkoderem. Wykorzystałem w nim gotowe funkcjonalności Matlaba takie jak funkcja tfest znajdująca model transmitancyjny dla danych pomiarowych, czy PID Tuner znajdujący automatycznie nastawy regulatora. Dzięki temu udało się uniknąć skomplikowanej teorii i wzorów.

W wyniku otrzymałem regulator PID, który znacząco przyspiesza czas ustalania prędkości w porównaniu ze sterowaniem w pętli otwartej. Dodatkową zaletą jest bezpośrednie sterowanie prędkością z poziomu funkcji sterującej, zamiast bardziej abstrakcyjnej wartości wypełnienia PWM.

Dzięki temu otrzymujemy gwarancję, że silnik będzie się kręcić z taką samą prędkością mimo np. rozładowującej się baterii, czy innej nawierzchni. Do artykułu załączam kod programu na STM z zaimplementowanym regulatorem PID.

enkoder, matlab, PID, regulator, robot, silnik

Załączniki

motor_ident (zip, 324 KB)

kod źródłowy programu na STM32

matlab (zip, 13 KB)

skrypt Matlabowy i projekt Simulink

out001.txt (plain, 3 KB)

Przykładowy plik out001.txt