Regularne + nowy termin spotkań

U niektórych jeszcze sesja (poprawkowa), więc frekwencja marna – ale nie ma co narzekać, bo dołączył do nasz jeden nowy student. W końcu nie w liczbie a w pomysłowości i intelekcie siła! 😀

To ostatnie zajęcia wtorkowe, terminy spotkań ulegają zmianie i będziemy się widywać w PIĄTKI o godz. 13:00 (sala 1064, Kampus, Wydział Fizyki – wiadomo).

(c) K. G. 2019

Nowy semestr = nowy termin

Sesja zakończona… w nowym semestrze proponuję spotkania we wtorki o godz. 16:15
Proszę pisać komentarze, jeśli to Państwu koliduje z innymi obowiązkami (choć uprzedzam, że dużego pola manewru nie mamy: środy odpadają, bo sala zajęta jest do godziny 17:30).

OSTATECZNIE wyszło na to, że będziemy się spotykać w PIĄTKI o godz. 13:00 – zapraszam!

(c) K.G. 2019

regularnie

Regularne zajęcia, omówienie planów na przyszłość – różne projekty.

  • finisz Line Folowera (brawo p. Bartek),
  • rozwiązanie kwestii Arduino Mega i biblioteki SoftwareSerial w kontekście obsługi modułu BlueTooth – nie działa z powodów opisywanych tutaj (zwracam uwagę na sekcję Limitations), ale … po co nam SoftwareSerial skoro Mega ma 3 part UARTów? Zamiana SoftwareSerial na Serial1 rozwiązuje problem,
  • pojazd (miniaturka) przekazany p. Mateuszowi – trzeba zrobić sterowanie, aby przenieść to na większy model,
  • sterowanie wieżyczką (2x serwo) – p. Łukasz ma zadanie z układem współrzędnych na kartce papieru i laserem sterowanym przez port szeregowy (ponownie UART),
  • kolorowe kółka (ws2812) ciągle czekają na p. Mariusza,
  • kolorowe ozdoby (ws2812) do naszego robota – p. Bartek?

(c) K.G. 2019

Opis algorytmu PD

Z tego wpisu dowiesz się:

  • Jak płynnie podążać za linią?
  • Jak przetwarzać sygnały z czujników by sterować szybkością poszczególnych silników?
  • Co to jest tzw. „pętla zwrotna”?

A wszystko po to, by oprogramować Line Followera (w skrócie LF)!

Regulator PD to “ucięta” wersja regulatora PID (ang. Proportional-Integral-Derivative). Posłuży nam on do płynnego sterowania linefollower’em. Regulator ten posiada 3 człony:
liniowy (P),
całkowy (I),
różniczkowy (D).

Człon P odpowiada za to, jak szybko silniki LF’a będą się obracać na podstawie położenia linii. Jeżeli linia będzie po prawej stronie czujnika to robot “wie”, że musi skręcić w tym kierunku i zmniejszy szybkość prawego silnika (lub zwiększy prędkość lewego, ale z reguły lepiej zastosować to pierwsze rozwiązanie). Jednak sama zależność liniowa nie wystarcza, żeby płynnie podążać za linią (chyba, że bardzo powoli). Żeby “przewidzieć” zmiany w kierunku ruchu i odpowiednio na nie zareagować przydaje się nam człon D regulatora. Jest to prosta różnica pomiędzy poprzednią a aktualną pozycją linii. W przypadku prostej linii różnica będzie nieznaczna, a podczas nagłej zmiany kierunku robot szybciej zmieni szybkość silników. Człon I pomijamy, bo nie jest on zbyt ważny w przypadku linefollower’ów (z doświadczenia).

Może i jest to na początek trochę skomplikowane, ale implementacja jest bardzo prosta i nie wymaga zbyt wiele pisania:

error_P = pozycja_linii * KP; // zależność liniowa
error_D = (pozycja_linii - poprzednia_pozycja_linii) * KD; // różnica pomiędzy pomiarami
Error = error_P + error_D; // suma członów regulatora
poprzednia_pozycja_linii = pozycja_linii;

Uzyskany w ten sposób Error możemy bezpośrednio wykorzystać do ustawienia prędkości silników. Współczynniki KP i KD określają jaki wpływ mają poszczególne człony na ruch LF’a i będą się znacząco różnić w zależności od algorytmu wykrywania pozycji linii czy samej budowy robota (np. pozycji czujnika). Właśnie w konkretnych wartościach KP, KD leży sekret działania dobrego regulatora PID. Żeby uzyskać płynny ruch trzeba się trochę “pobawić” z tymi współczynnikami i znaleźć najlepsze wartości. Można znaleźć wiele metod strojenia takiego regulatora (np. Metoda Zieglera-Nicholsa), jednak w tym przypadku najprościej jest to zrobić ręcznie czyli metoda prób i błędów, eksperymentalnie zmieniając KP i KD i sprawdzając na torze jak to wpływa na ruch LF.

Na początku ustawiamy KD = 0, i szukamy najmniejszego KP, żeby robot przy małej prędkości w miarę dobrze podążał po prostej linii lub lekkim łuku. Po znalezieniu odpowiedniego KP możemy stopniowo zwiększać współczynnik KD i prędkość, do uzyskania płynnego ruchu. Jako, że różnice w pomiarach są stosunkowo małe w porównaniu do położenia linii, często następuje zależność: KD > KP.

Określanie pozycji linii, wspólne działanie 5-ciu czujników

Jak przy pomocy wielu czujek jednoznacznie określić, gdzie znajduje się linia? Każda czujka zwraca tylko informację o ilości odbitego światła (wartości od 0 do 1023). Można by zastosować algorytm który wybiera jedną pozycję z największą wartością ale prowadzi on tylko do niepłynnego ruchu. Powinniśmy zastosować bardziej precyzyjny algorytm wykrywania linii ze średnią ważoną.

Każdemu czujnikowi przypisujemy wagi, na których postawie będziemy określać pozycję (np. -2000, -1000, 0, 1000, 2000 dla kolejnych czujek). Następnie czytamy wartości z czujników, mnożymy je razy wagę i sumujemy. Na koniec dzielimy otrzymaną wartość przez sumę wartości z czujek. W ten sposób dokładną informację nawet kiedy linia znajduje się na granicy dwóch czujników.

pozycja = (cz1*waga1+cz2*waga2+cz3*waga3+cz4*waga4+cz5*waga5)/(cz1+cz2+cz3+cz4+cz5)

W przypadku zastosowania wag: -2000, -1000, 0, 1000, 2000 dla kolejnych czujników, po przeliczeniu średniej ważonej otrzymamy jedną wartość od -2000 do 2000 (dla -2000 linia znajduje się po lewej stronie, dla 0 – na środku, a dla 2000 – po prawej).

Sterowanie prędkością silników

Jak wykorzystać wcześniej otrzymany Error do sterowania prędkością silników? Do ustawienia prędkości pojedynczego silnika używamy sygnału PWN. Będziemy tą wartość zmieniać w zależności od uzyskanego Error’a.

Jeżeli wartość Error’a jest ujemna to w naszym przypadku pozycja linii znajduje się po lewej stronie LF’a. Aby skorygować ruch będziemy zmniejszać prędkość lewego silnika. Analogicznie postępujemy w przypadku dodatniej wartości:

if(Error > 0){
pwn1=maxSpeed; //maxSpeed to wczesniej ustalona maksymalna wartość PWN LF’a
pwn2=maxSpeed-Error;
} else {
pwn1=maxSpeed+Error;
pwn2=maxSpeed;

Warto pamiętać, że Error może być znacznie większy od wartości maxSpeed. Jeżeli wartość nowego pwn1 lub pwn2 jest mniejsza od 0 to musimy ją ustawić na 0 (pwn powinien wynosić od 0 do 255). Po tych wszystkich operacjach uzyskujemy pwn’y do sterowania silnikami.

Mój LF w akcji:

(c) Bytler, 2019