W poprzednim wpisie opisałem swoje zmagania z robotem Micromouse z zamierzchłych czasów. Dzisiaj opiszę drugą próbę, którą podjąłem w zeszłym roku. Od poprzednio opisywanego projektu minęły 3 lata. Przez ten czas nabrałem świadomości swoich słabości, z których za największą uznałem posługiwanie się lutownicą. Poza tym z dystansem podchodziłem do swoich umiejętności w dziedzinach elektroniki i mechaniki. W przeciwieństwie do poprzedniego podejścia, tym razem fundusze nie były takim problemem. Na projekt jednak mogłem przeznaczyć dużo mniej czasu niż poprzednio. Dodatkowo miała to być okazja na sprawdzenie w praktyce dobrych praktyk i narzędzi do prowadzenia projektu. Dlatego miałem projekt założony na GitLabie z gitem, issue trackerem, wiki i milestonami. Poza tym do kodu miałem pisać unit testy, a nawet próbowałem okiełznać gitlabowe continuous integration. Ktoś może powiedzieć, że to przerost formy nad treścią, ale te umiejętności już niedługo miały mi się przydać w pracy, a ten projekt był dobrym poligonem doświadczalnym.

Projekt hardware

Założenia i wykorzystane elementy bazowały na poprzednim projekcie, jednak było klika istotnych zmian:

  • Aluminiowe mocowania do silników.
  • STM32F401 – procesor ze wsparciem floatów, żeby udźwignął bardziej zaawansowaną matematykę.
  • Debug po SWD.
  • Debugowa konsola UART – docelowo do podpięcia modułu bluetooth, żeby zbierać pomiary w trakcie jazdy.
  • Gotowy moduł akcelerometru z żyroskopem MinIMU-9 Pololu wpinany do płytki goldpinami.

Poza tym przy kupowaniu części przewidziałem, że coś może pójść nie tak i będą potrzebne zapasowe. Okazało się to ważne już na początku realizacji, bo pierwsze próby polutowania elementów to była droga przez mękę. Robiły się zwarcia, elementy się grzały, przegrzane pady odpadały od płytki. Myślałem początkowo, że tak beznadziejnie lutuję, jednak problemem okazał się sprzęt. Po kupieniu grotu minifali, topnika żelowego w strzykawce i nowej plecionki okazało się, że jednak polutowanie ręcznie obudowy TQFP mnie nie przerasta. Można więc było przejść do programowania.

Tutaj wyszedł problem, ponieważ OpenOCD, którego używałem do wgrywania programu przez ST-LINK sypał błędami. Okazało się, że ze starszą wersją kompilatora wszystko działało poprawnie. Miałem też problemy z zakłóceniami. Zdecydowałem się więc na zrobienie nowej płytki z przeprojektowanym torem zasilania. Zasilanie z baterii Li-Pol 2S szło na silniki i na przetwornicę, która obniżała napięcie do 5V. Z 5V zasilane były diody IR. Dalej był stabilizator LM1117, który dawał 3.3V używane przez resztę układów. Nowa płytka po zlutowaniu nie chciała działać. Okazało się, że problemem były przelotki, które w niektórych miejscach nie przewodziły. Na szczęście miałem zamówione dwie płytki i na drugiej ten problem nie występował. Hardware miałem działający. Zrobiłem też implementację driverów do peryferiów STMa. Można było przejść do ciekawszych rzeczy.

Wykrywanie ścian

Pierwszą z nich było napisanie modułu wykrywającego ściany labiryntu. Schemat działania tego modułu był dosyć prosty. Najpierw mierzyłem napięcie na wszystkich fototranzystorach przy wyłączonych diodach. Następnie zapalałem jedną diodę, mierzyłem napięcie na odpowiadającym fototranzystorze i z różnicy wyznaczałem odległość. Prawdziwym wyzwaniem nie była jednak część programistyczna. Najgorsze było ustawienie diody i fototranzystora po obu stronach w odpowiedniej pozycji tak, żeby odczyty się pokrywały dla całego zakresu wykrywanych odległości ściany od czujnika. W tym celu zaopatrzyłem się nawet w bardzo specjalistyczny hajendowy sprzęt widoczny na obrazku.

Posłużył on też do zebrania charakterystyki czujnika potrzebnej do określenia wzoru do konwersji z jednostek ADC na milimetry. Ustawienie czujników nie było jeszcze końcem męki. Aby pomiary były wiarygodne, należało jeszcze zapewnić, żeby elementy nie zmieniły swojej pozycji. Dlatego postanowiłem zalać je klejem. Oczywiście w trakcie tej operacji elementy się przesuwały i obliczona wcześniej charakterystyka się rozjeżdżała.

Sterowanie silnikami

Sterowanie silnikami jest być może najważniejszym elementem decydującym o sukcesie robota micromouse. Od jego jakości zależy, czy nasza mysz będzie poruszała się tak jak sobie założyliśmy. Bez tego algorytmy znajdujące ścieżkę w labiryncie i zadające aktualną prędkość na silniki są bezwartościowe. Dlatego do tego punktu bardzo się przyłożyłem. Pierwszym testem silników było zadanie pewnego wypełnienia PWM i zobaczenie jak robot sobie radzi. Okazało się, że rusza jak dragster i podnosi przód. Musiałem więc go dociążyć metalowymi płytkami. Kolejnym zadaniem było wysterowanie regulatorów PID. Projekt zakładał, że algorytm wyższego poziomu wyznaczy prędkości zadane dla obu silników, a algorytm sterowania silnikami wyliczy wypełnienia PWM, które należy podać na silniki. Żeby dobrać nastawy PID zebrałem odczyty enkoderów w kolejnych chwilach czasu dla pobudzenia stałym PWM. Czyli innymi słowy zebrałem odpowiedź na skok jednostkowy. Wykres odpowiedzi unaocznia poważny problem – duże zakłócenia odczytu z enkodera.

pwm20

Mają one cykliczny charakter. Nie wiem do końca co jest ich przyczyną. Może to mieć związek ze złym wypozycjonowaniem magnesu względem enkodera, albo przemieszczaniem sie osi silnika lub umieszczonego na niej magnesu względem enkodera podczas obrotu. Próbowałem poprawić ułożenie enkoderów oraz zmieniać magnesy na inne, ale te działania nie przynosiły poprawy. Innym pomysłem była filtracja sygnału z enkodera. Jako wartość wejściowa dla PID podawałem więc sygnały przefiltrowane za pomocą filtru alfa-beta. Wynik nawet wyglądał obiecująco.

Jednak wykres nieco przekłamuje obraz, ponieważ prezentowany jest przefiltrowany sygnał sterujący, na którym nie widać szumów. Wykres sygnału sterującego pokazuje dość duże wahania, a momentami wręcz wartość ujemną, oznaczającą, że silnik ma kręcić się w drugą stronę.

Po długich walkach stwierdziłem, że nie jestem w stanie nic z tym zrobić i przeszedłem do zadawania ruchu obrotowego. Tutaj wyszedł problem, bo projekt początkowo przewidywał PID dla silnika lewego i prawego, więc wartości zadane musiały wcześniej uwzględniać korektę związaną z ruchem obrotowym. Trzeba było zmienić założenia i teraz sterowanie silnikami składało się z PID dla ruchu postępowego i PID dla ruchu obrotowego, a z otrzymanych wartości wyznaczana była ostateczna wartość podawana na silnik.

Przystąpiłem więc do zebrania odpowiedzi jednostkowej. Sygnałem wyjściowym była tym razem wartość zwracana przez żyroskop dla osi Z. O ile w przypadku ruchu postępowego wyznaczenie nastaw PID było dosyć proste – początkowe nastawy wyznaczałem symulacyjnie, potem je trochę zmieniałem ręcznie obserwując zbierane charakterystyki, to dla ruchu obrotowego nie byłem w stanie dobrać dobrych nastaw. Wartości wyznaczone symulacyjnie kompletnie się nie sprawdzały, próbowałem coś dobierać na oko, ale wyniki nie były zadowalające. W końcu musiałem więc obniżyć wygórowane oczekiwania i powiedzieć sobie „close enough”.

Podczas jednej z prób walki z zakłóceniami enkoderów uszkodziłem ostatnią działającą płytkę, jaką miałem. Pomyślałem, że to dobry moment, żeby zmienić niektóre założenia projektowe i wprowadzić większe zmiany. Czeka mnie zmiana silników na takie z wbudowanymi enkoderami (Faulhaber 1717T006SR z enkoderem o 16 tickach na obrót). Jako, że do tych silników nie pasują używane przeze mnie koła i obejmy, chcę zaprojektować własne części na drukarce 3D. Przy okazji chcę przejść z dwóch kół na 4, dzięki czemu odejdzie mi problem trzeciego punktu podparcia. Będę musiał też przeprojektować PCB, żeby dopasować je do tych zmian. O postępach tych zmian, jak i późniejszych walkach nad ujarzmieniem micromouse’a będę pisał w najbliższym czasie.