Celem projektu było zdobycie doświadczenia w zakresie szeroko rozumianego “internetu rzeczy”. Rozpoczynając zabawę wiedziałem, że na RPi będzie działał serwer NodeJS i za jego pośrednictwem, z poziomu przeglądarki, będę sterował stanami pinów modułu GPIO. Szybko też zdecydowałem się, co do tych pinów podepnę. Wybór niezbyt oryginalny: zdalnie sterowany robot czyli “ever-green” tego typu projektów. Forma oklepana, ale też atrakcyjna i dająca duże pole dla inwencji. Wątkiem pobocznym projektu okazało się wysterowanie robota za pomocą klawiatury bezprzewodowej. Po pierwsze miałem taką na półce. Po drugie wiedziałem, że interfejs webowy nie zapewni swobodnej kontroli nad pojazdem. Przynajmniej nie w najbardziej konwencjonalnym rozumieniu, jak w samochodziku z pilotem.
Zacznijmy od listy zakupów:
- Raspberry Pi Model B 512MB RAM + ładowarka, karta pamięci
- DRV8835 – dwukanałowy sterownik silników – moduł
- Magician Chassis – podwozie robota
- Camera HD C – kamera dla Raspberry Pi zgodna z wersją oryginalną
- Karta sieciowa WiFi USB 150Mbps Dynamode WL-700N-RXS – Raspberry Pi
- Bezprzewodowa klawiatura DELL
- POWER BANK Kruger&Matz Ładowarka 7600 mAh USB
- Płytka prototypowa THT – Raspberry Pi
Płytka prototypowa nie jest niezbędna, ale bardzo ułatwia montaż i później wpięcie/wypięcie mikrokomputera z zestawu.
Podwozie
Wybrałem najtańsze spośród dostępnych w Botlandzie. Dwa niezależnie napędzane koła o średnicy 65 mm i metalowa kulka jako podpórka. Wiedziałem, że taki system umożliwi mi jazdę do przodu, do tyłu i skręcanie, jeśli tylko uda mi się uzyskać kontrolę nad dwoma silniczkami napędzającymi każde z koł. Do pełni szczęścia brakowałoby mi już wtedy tylko sterowania prędkością ich obrotów. No może nie zupełnie – ale o tym miałem się przekonać później.
Zasilanie
Potrzebowałem dwóch źródeł. Silniczki potrzebowały natężenia co najmniej 1A i napięcia około 4.5V. Z kolei aby zaspokoić wszystkie (potencjalne) potrzeby raspberry postanowiłem zapewnić natężenie 2.1A i napięcie 5V. Powerbank jest rozwiązaniem idealnym dla obu zastosowań. Bateria posiada dwa wyjścia USB. Wyjście 2.1A podłączyłem pod mikrokomputer. Z gniazda 1.0A zasiliłem napęd. Dodatkowo wymiary urządzenia umożliwiły łatwe umieszczenie go pod górnym pokładem robota (oczywiście zrezygnowałem z koszyczka na baterie).
Sterownik
Z mojego punktu widzenia (na co dzień zajmuję się programowaniem) najciekawsza część. Mostek łączący GPIO, silniczki i baterię. Urządzenie, poda prąd z baterii do silniczków. Ale (poprzez GPIO) umożliwi mi też modulację wypełnienia sygnału prądowego (PWM) i zmianę umownego kierunku prądu. Czyli jak szybko silniczki mają się kręcić i w jakim kierunku.
Wyzwaniem wydawał się już sam wybór modułu o parametrach odpowiednich dla poszczególnych komponentów zestawu. O poprawnym i precyzyjnym lutowaniu nie wspomnę. W praktyce zadanie okazało się jednak prostsze niż sądziłem. Uszkodziłem tylko dwa(!) sterowniki – trzeci działa bez zarzutu :) W pierwszym podejściu najprawdopodobniej przepaliłem ścieżki na płytce. Za drugiem razem już nawet wszystko działało… ale po kilku dniach przestało. Nie mam fiołkowego pojęcia co zaszło. Kiedy za trzecim razem poprawnie zlutowałem sterownik… natychmiast zalałem go klejem do klejenia na ciepło, aby zabezpieczyć go przed działaniem czynników mechanicznych, wyładowań elektrostatycznych czy owadzich odchodów. Działa do dziś! Schematu połączenia nie będę tu przytaczał. W opisie produktu na stronie Botlandu są dokładne i przejrzyste rysunki. Dla mnie nieoceniony był też film instruktażowy Cyryla Sochackiego – WIELKIE DZIĘKI! Kierując się tymi wskazówkami, bazując nawet na tak szczątkowej wiedzy z elektroniki jak moja, każdy poradzi sobie z połączeniem systemu.
Kamera
Ponieważ montowałem ją będąc już bardzo blisko celu, to dałem się porwać ułańskiej fantazji. Bardziej prowizorycznie się nie dało: taśma samoprzylepna, gumka, pudełko i gotowe.
Wiedziałem, że obraz z kamery ma być wyświetlany na stronie. Początkowo planowałem użyć protokołu rtsp i pluginu vlc w przeglądarce. Prosta instrukcja jak to skonfigurować znajduje się tutaj. Uzyskany obraz był płynny, choć po pewnym czasie zakłócany niedomaganiem raspberry. Ponad wszystko jednak dokuczliwe było opóźnienie (ok. 5 sekund) spowodowane potrzebą buforowania strumienia video. No nie – tak to nie mogło działać! Drugie podejście: Motion JPEG. Tutaj efekt okazał się dużo lepszy. Ze strony rapsberry wysiłek niewielki. Opóźnienie akceptowalne (mniej niż sekunda). Jak zwykle jednak – nic za darmo. Straciłem na płynności obrazu. Dla moich celów jednak wymiana była korzystna. Można być może lepiej dostosować parametry dla polecenia raspistill. Pozostawiam dociekliwym – moje rezultaty można ocenić na ostatnim filmiku. Jak zwykle pomocne okazały się źródła, w tym łopatologiczny tutorial – jak skonstruować i wyświetlić strumień.
Kod
Tutaj starałem się unikać prowizorki. Całość umieściłem do dyspozycji zainteresowanych na githubie: https://github.com/dominikdeka/vehicle-control/. Zaznaczę, że kontynuuję pracę nad projektem i w przyszłości stan repo może się nie pokrywać z efektami, które prezentuję w tym poście. Na chwilę obecną ostatni commit to: b9cce2d.
Klawiatura bezprzewodowa
Relatywnie dobry i najszybszy efekt udało mi się uzyskać sterując robotem za pomocą klawiatury bezprzewodowej. Tutaj umieściłem skrypt, który nasłuchuje klawiaturę i w zależności od jej stanu zmienia stany na pinach sterujących silnikami. Jak nasłuchiwać klawiatury radiowej nauczyłem się tu. Do sterowania GPIO z poziomu pythona użyłem tej biblioteki. Sterowanie odbywa się za pomocą strzałek. Klawisze 1, 2, 3, 4 to biegi. Oto demo:
Pojazd programowalny
Jak wspomniałem wyżej: tak swobodnej i płynnej kontroli poprzez przeglądarkę nie byłem w stanie uzyskać. Teoretycznie mogłem podpiąć akcje pod zdarzenia kliknięcia/puszczenia przycisków klawiatury i wysyłać requesty, na które pojazd by reagował. Ale nawet wtedy opóźnienie spowodowane komunikacją, zakłóciłoby płynność jazdy. Poza tym zatraciłbym charakter interfejsu WWW – a tego nie chciałem. Postanowiłem skupić się na mocnych stronach technologii, omijając słabsze. Tak powstał pomysł drugi: prosty interfejs pozwala zaprogramować trasę robota składającą się z sekwencji komend skręć w lewo/skręć w prawo/jedź naprzód. Założenie było takie, że krok naprzód miał wynosić 30cm, a kąt każdego skrętu 90 stopni. Chciałem w ten sposób zrealizować rodzaj gry, odbywającej się na szachownicy złożonej z kwadratów 30cmx30cm (np płytki na tarasie). Gracz miałby za zadanie skonstruować taki program, który “zaprowadziłby” pojazd z określonej pozycji startowej do wyznaczonej mety i, na przykład, ominął stojącą na drodze przeszkodę. Niestety słowo “chciałem” jest tu adekwatne. Niby mam pełną kontrolę nad silniczkami, ale tak precyzyjne wysterowanie pojazdu okazało się niemożliwe. Siły tarcia, wyważenie pojazdu, poślizgi, stan naładowania baterii i pewnie wiele innych czynników sprawiły, że nie udało mi się skalibrować dokładnie takich “kroków”, o jakie mi chodziło. Szczerze powiedziawszy nie udało mi się robota “zmusić” nawet do w całkowicie powtarzalnej jazdy po prostej. Tym bardziej o precyzyjnych i powtarzalnych zakrętach pod kątem prostym nie było mowy. Mam kilka pomysłów co można poprawić, a co dodać, ale jeśli ktoś ma własne propozycje to są one mile widziane. Tym nie mniej co do koncepcji samo programowanie trasy udało się zrealizować. Oto dowód:
Robot szpiegowski
Na koniec oczywiście obowiązkowy punkt programu, czyli sterowanie poprzez stronę i jednoczesny podgląd z kamery. Długo zastanawiałem się jak powinien wyglądać/działać taki interfejs. Obawiałem się dużego rozdźwięku pomiędzy stosunkowo szybkimi reakcjami pojazdu, a opóźnieniem strumienia video. Jak wspomniałem wcześniej, zredukowałem to opóźnienie poniżej sekundy. Dla pełnej harmonii pozostawało jeszcze tylko stworzyć… dostatecznie toporne sterowanie. Posłużyłem się tutaj przykładem Google Street View. Robot porusza się niewielkimi krokami przód/tył i lekkimi skrętami lewo/prawo. Korelacja pomiędzy kliknięciem na odpowiednią strzałkę, a reakcją obrazu z kamerki jest moim zdaniem zadowalająca. I tak oto posługując się dowolną przeglądarką możemy zacząć poszukiwania sprytnie ukrytego przedmiotu… na przykład lusterka:
Witaj,
fajny projekt, kilka razy przymierzałem się do tej platformy.
self::blockquote
…właściwie to powinno być “maksymalnie”. Jeżeli spojrzysz na zalinkowaną przez Ciebie specyfikację dokładniej: ‘no load current’ – czyli bieg jałowy, gdy silniki nie pokonują żadnego oporu, jest 190-250mA. 1A: masz chyba na myśli tzw. stall current – gdy silnik jest zablokowany (np. jak chwycisz za wał i nie pozwolisz mu się obrócić) – a więc natężenie maksymalne. W praktyce, przy tych oponach, nawet jeżeli uderzysz robotem w ścianę – kółka będą się ślizgać po podłożu. Ale 1A wydaje mi się bezpiecznym marginesem – stąd wybór sterownika jest poprawny. Zawsze trzeba kalkulować najgorszą sytuację.
ALE: skoro masz 2 silniki po 1A to dlaczego podłączasz je do wyjścia 1A a nie 2A? Bawiłem się tymi silniczkami kilka razy i zablokowane pobierają nadet to 1.2A, normalnie 300-400 (zależy od masy robota). Podłączając je pod wyjście 1A – jesteś na granicy. Temu modelowi Raspberry powinno wystarczyć nie więcej niż 400mA, Użyte akcesoria nie powinny aż tak ten apetyt zwiększyć. A więc – moim zdaniem, kable zasilające powinny być odwrotnie wpięte – rpi do 1A a silniki do 2A.
self::blockquote
Strasznie się namęczyłeś… Większość z połączeń dotyczy logiki, więc tak grube kable… są niepotrzebne. Zupełnie nie rozumiem też, dlaczego nie wlutowałeś pinów to sterownika a potem gniazd do płytki prototypowej… – zobacz załącznik.
O zalewaniu klejem nie wspomnę… Taki sterownik się grzeje i – szczerze mówiąc – nie wiem jak na jego pracę wpłynie oblanie go klejem… Wydaje mi się, że nie jest to standardowe postępowanie, pewnie miałeś więc wyraźny powód, żeby tak zrobić:)
self::blockquote
Duży plus za podawanie źródeł i wypróbowanie kilku opcji:) Minus za brak opisu instalacji. Nigdy nie podłączałem kamery – chciałbym się dowiedzieć, jak to zrobić – pomożesz?
self::blockquote
Duży plus za podawanie źródeł. Minus za brak komentarzy w kodzie źródłowym:) Kolejny minus za brak opisu instalacji. Jestem tu zwolennikiem jak najbardziej kompletnych poradników.
Podsumowując: ciekawy post, widać że włożyłeś w niego sporo (swojej) pracy i nie bałeś wyciągać wnioski, że coś nie działa. Fajne połączenie software i hardware (chociaż z wyraźnym wskazaniem na to pierwsze:)). Te silniki nie pozwalają na precyzyjne sterowanie – nie przy takiej cenie:)
Pozdrawiam.
Cześć,
dziękuję za wyrozumiały i konstruktywny post. Dzięki niemu zaczynając kolejny projekt kilku błędów już nie powtórzę, a o to w tej zabawie właśnie chodzi.
Opis silniczków rozumiałem tak, że maksymalny prąd (1A) jest pobierany nie tylko kiedy zblokuję koło, ale także wtedy gdy silnik zaczyna pracę. Dlatego założyłem, że ten maksymalny prąd muszę zapewnić ‘Zawsze trzeba kalkulować najgorszą sytuację.’. Niestety faktycznie nie pomnożyłem tego przez dwa. Wczoraj zamieniłem podłączenie źródeł, oczywiście nie widać różnicy – ale działa i rozumiem, że tak jest poprawnie.
Dzięki za instrukcje i zdjęcie ilustrujące jak elegancko powiniennem podłączyć sterownik. Kiedy zaczynałem nie znałem standardów i nie wiedziałem o gniadach do pinów. Nie do końca się zgodzę że większość połączeń to logika – chyba raczej pół na pół. Ale masz rację – namęczyłem się :) Możesz podesłać jeszcze zbliżenie pokazujące jak technicznie rozwiązałeś wyprowadzenia na GPIO?
Jeśli chodzi o zalewanie sterownika klejem, wiem że i tak się nie wybronię :) Byłem zfrustrowany tym, że mój drugi sterownik przestał działać. Przejawiało się to tym, że na piny sterujące prędkością obrotów, silniczki reagowały odwrotnie (najszybsza prędkość przy PWM = 0), a jeden z silniczków w jednym kierunku nie działał wcale (tzn. nie było napięcia na wyjściu).
Kamera. To najlepsza instrukcja podłączenia kamery jaką znalazłem: https://www.youtube.com/watch?v=T8T6S5eFpqE
Klawiatura. Ten link akurat znalazł się w opisie: http://learn.pimoroni.com/tutorial/robots/controlling-your-robot-wireless-keyboard i tu jest dokładna instrukcja podłączenia/rozpoznania klawiatury bezprzewodowej.
pozdrawiam