Samochodzik z RaspberryPi kamerką sterowany przez WWW ze smartphona [Out Of the box Project]

O kursie

Ten kurs – przedstawia budowę samochodu sterowanego przez przeglądarkę z wyświetlaniem obrazu z kamerki . Jest to dość specyficzny kurs – całość oprogramowanie jest już zrobiona, a dodanie plików do własnego konta w RemoteMe sprowadza się do paru kliknięć. Po tak dodanym projekcie można własnoręcznie i dowolnie edytować wszystkie pliki źródłowe (strona WWW skrypt pythonowy) – zwłaszcza, że same pliki projektu nie są skomplikowane, a kod jest dość czytelny i samo opisujący się (mam przynajmniej taką nadzieję 😉 )

Na dole kursu opisana jest bardziej szczegółowo zasada działania samochodu.

Kurs właściwy

W poprzednim kursie pokazałem jak sterować pozycją kamerki i przechwytywać obraz na przeglądarkę tutaj  i sterowanie kamerką tutaj . Teraz rozbudujemy ten projekt i zbudujemy samochód z napędem na 4 koła ( sterowany podobnie jak czołg – żeby skręcić prawa para kół musi się kręcić z inną prędkością niż lewa). Taki efekt otrzymamy na wideo też całość kursu – można zaglądnąć, gdy gdzieś utkniecie

Opóżnienia przesyły obrazu sieć lokalna 140ms, spoza sieci lokalnej ( z użyciem TURN serwera) 170ms

 

 

Części

Połączenia

RaspberryPI steruje serwami poprzez moduł PWM i napędem przez ustawianie stanu pinów na mostku oraz dostarczając sygnału PWM poprzez ten sam moduł, który wysyła sygnał do serwomechanizmów. ( Dzięki modułowi do generowanie sygnału PWM nie musimy tych sygnałów generować przez samo RaspberryPi – co jest dość problematyczne, poprostu przez I2C przesyłamy odpowiednie instrukcje do sterownika serw (poprzez bibliotekę pythonową dostarczoną przez adafruit), a ten generuje odpowiedni sygnał PWM dla serwo mechanizmów i do mostka H)

Schemat połączeń:

c

Poprzez magistrale I2C RPi steruje kontrolerem serwo mechanizmów, dwa ostanie wyprowadzenia kontrolera są podłączone do mostka H, gdzie wykorzystując sygnał PWM ustawiamy prędkość silników. Do mostka H są również podłączone piny RPi które stanami wysokim i niskim będą określać kierunek obrotu silników napędowych – po szczegóły odsyłam do dokumentacji układu TB6612FNG, równie dobrze można użyć mostka L298N lub podobnego.

Zaprojektowałem płytkę PCB, którą możecie użyć pliki eagle,gerber itd tutaj  plik pcb.zip Schemat płytki pokrywa się ze schematem powyżej

Wyprowadzenia płytki:

 

  1. Wejscie sygnału PWM z kanałów 15 i 14 modułu PWM

  1. Wejście zasilania silników do poruszania się
  2. Zasilanie układów (PWM, RPi) koniecznie dokładne +5V
  3. Wyjście silników napędu, pierwsze dwa wyjścia do jednej pary silników kolejne dwa do drugiej
  4. Zasilanie serw i w tym przypadku silników napędu w moim przypadku ~6V (należy sprawdzić w specyfikacji serw i silników, jakie maksymalne napięcie można podłączyć)
  5. ZWORKA gdy zepniemy dwa piny napięcie z 5 będzie podawane też do zasilania silników napędu
  6. ZWORKA gdy jest podłączona zasilane jest RaspberryPI z połączenia 3 przed podłączeniem zworki należy dokładnie sprawdzić napięcia, żeby nie uszkodzić Najdroższego komponentu czyli właśnie malinki
  7. Wlutowujemy kabelki, bo nie będziemy korzystali z konwertera stanów

 

Oczywiście jest jeszcze potrzebne odpowiednie zasilanie, w moim przypadku 6v jako napięcie silników napędu i serw, oraz 5v dla Raspberry Pi i kontrolerów.

Poniżej kilka zdjęć poglądowych całości samochodu:

 

 

Do podłączenia płytki z samochodem użyłem plastikowych dystansów.

Programowanie

Przed utworzeniem projektu skonfigurujcie kamerkę i komunikacje I2C używając raspi-config opisane tutaj

Ten projekt jest jednym z gotowych projektów, które możecie prosto zaimplementować kilkoma kliknięciami:

Otwórz projekt

Przejdźcie do zakładki “build It” i podążajcie krokami, na końcu klik w “Build Project” i otrzymacie:

Po kliknięciu “Get QR” pokaże się kod QR, który możecie zeskanować smartfonem, lub po prostu otworzyć stronę przyciskiem “Open” w przeglądarce na komputerze.

Narazie nie radzę zmieniać pozycji kamery dopóki nie ustawimy pozycji serw – w niektórych przypadkach możecie uszkodzić swoje serwomechanizmy

Samochód powinien jeździć jak na filmie – może się zdarzyć, że skręca w złą stronę albo serwa są źle skalibrowane, poniżej w omawianiu kodu napisałem jak to naprawić.

Omówienie tego, co się stało

Jak zauważyliście, tworzenie projektu było mocno zautomatyzowane. Dlatego omówię teraz, co się dokładnie wydarzyło i jak modyfikować Wasz projekt.

Przede wszystkim utworzyły się dwie zmienne (zakładka variables)

Zmienna cameraPos przesyła pozycje kamery, drive pozycje joysticka. Obie są typem “Small int x2” oznacza to, że wartoscią zmiennej są dwie liczby integer.

Strona internetowa zmienia nasze zmienne, a skrypt pythonowy te zmiany rejestruje i odpowiednio reaguje (jak rozwiniemy zmienne zobaczymy, że urządzeniem nasłuchującym na zmiany jest właśnie skrypt pythonowy). Zobaczmy jak wygląda kod Pythonowy (więcej o zmiennych tutaj)

Python

Skrypt pythonowy został automatycznie wgrany. Oczywiście możemy go podejrzeć i modyfikować ( żeby stworzyć nowy skrypt pythonowy np dla innych projektów zobacz tutaj) . Z informacji jakie teraz są Ci potrzebne to skrypt pythonowy to kolejne urządzenie w remoteMe jest zarządzalne przez skrypt (uruchomiony przez ./runme.sh) , do tego urządzenia możemy wysłać wiadomości, urządzenie reaguje też na zmiany zmiennych, które obserwuje i może te zmienne zmieniać.

Żeby otworzyć skrypt pythonowy kliknij python.py i wybierz Edit :

Wygląda on następująco. Poniżej omówię ciekawsze fragmenty

Sterowanie silnikami:

funkcja setMotor dla motorId 1 lub 2 ustawia prędkość speed (może być ujemna). poprostu najperw na odpowiednich pinach  ustawiamy odpowiednio stany  (ruch do przodu do tyłu, hamowanie), a następnie w zależności od prędkości ustawiamy odpowiednio wypełnienie PWM korzystając ze sterownika serw.

 

 

powyższa funkcja zostanie wywołana jak zmieni się zmienna drive – np po zmianie joysticka na stronie. x,y to poprostu wspolrzędne wychylenia joysticka (1024,1024) oznacza wychylenie maksymalnie do góry i w prawo. Na podstawie tych zmiennych wyliczamy prekość lewej i prawej strony samochodu.

Jeżeli samochód skręca, zamiast jechać do przodu, jedzie do tyłu zamiast do przodu :

setMotor(0, Y2*left)

setMotor(1, X2*right)

dajcie minusy w różnych kombinacjach (w miejsca X i Y) do czasu, aż samochód jedzie do przodu – gdy joystick jest wychylony do góry. (będzie to odpowiadać zamianą miejscami przewodów lewej strony dla miejsca Y i prawej strony dla miejsca X).

Następnie, jeżeli prawa i lewa strony są zamienione (samochód skręca w złą stronę ), w funkcji powyżej zamieńcie left i right miejscami.

 

 

Po prostu ustawiamy odpowiednie piny (te do sterowania mostkiem H) na wyjścia. I tworzymy obiekt do kontrolowania sterowania serw. (Uwaga żeby sterownik serw działał prawidłowo musimy włączyć komunikacje I2C używając raspi-config więcej tutaj )

 

Ustawienie RemoteMe i ustawienie jakie funkcję mają zostać wywołane, gdy zmienne do sterowania kamery i napędu zostaną zmienione.

To tyle w samym skrypcie pythonowym, jak widzicie, nie jest on zbyt skomplikowany, po więcej informacji zapraszam tutaj

Strona WWW

Tak naprawdę zostały stworzone dwie strony WWW — jedna do kalibracji druga — strona do sterowania samochodem i wyświetlania obrazu z kamerki. Otwórzmy stronę do kalibracji:

Otworzy się strona internetowa z dwoma suwakami. Ustawmy górny i dolny na środkową pozycję – kamera się poruszy-  górny suwak powinien poruszać kamerę w osi x, dolny y. Jeżeli się tak nie dzieje – zamieńcie miejscami przewody serwomechanizmu.

Następnie za pomocą suwaków ustalcie maksymalne wychylenie osi x i osi y dla mnie jest to:

  • x : 298 – 830 i centralna pozycja. Ważne, żeby centralna pozycja byłą dokładnie pomiędzy przedziałem u mnie ((298+830) /2 = 564)
  • y: 223 – 723 i podobnie centralna pozycja kamery w osi y powinna być w środku przedziału

Zapiszmy liczby gdzieś w notatniku i otwórzmy do edycji stronę do sterowania samochodem;

 

Są to automatyczne komponenty do sterowania samochodem i wyświetlaniem obrazu wideo.

Strona, którą otworzyliście zawiera już wszystkie komponenty potrzebne do sterowania waszym samochodem. Jedyne co trzeba zrobić to zmienić zakres ruchów serwo mechanizmów.  xMin,xMax,yMin,yMax,  zamieńcie na wartości jakie otrzymaliście na poprzedniej stronie z suwakami.

Jeżeli chcecie stworzyć własną stronę ze swoimi komponentami najlepiej utworzyć ją od początku pokazane tutaj – pozwoli Wam to dodawać komponenty w przy pomocy kreatora, gdzie ustalicie potrzebne parametry, albo po prostu edytować źródła tej już utworzonej strony – wcześniej warto utworzyć kopię, gdyby coś poszło nie tak (albo skasować pliki i utworzyć projekt jeszcze raz – wtedy nie zapomnijcie wcześniej wykasować też zmienne)

Po zmianie wartości x/y/Min/Max możemy otworzyć naszą stronę np w smartfonie, klikamy na index.html, ale tym razem wybieramy opcje get anymous link Następnie, klikamy ikonkę kodu QR, a kod, który się pojawi skanujemy smarfonem.

Oczywiście sterowanie działa również poprzez internet – nie tylko w sieci lokalnej, jednak w niektórych przypadkach jest potrzebna dodatkowa konfiguracja więcej o niej tutaj

 

Trochę szczegółów technicznych ( nie obowiązkowe )

RemoteMe serwuję stronę WWW do sterowania Waszym samochodem ( a dodatkowo Was loguje na Wasze konto – stąd token w linku otwieranym przez smartfon ) i uczestniczy w negocjowaniu tworzenia połączenia WebRTC. Połączenie webRTC jest to połączenie bezpośrednie (RaspberryPi – przeglądarka ( w niektórych przypadkach np za NATem jest potrzebny dodatkowo turn sewer)). Po stworzeniu połączenia webRTC stan zmiennych nie jest w ogóle wysyłany do remoteMe (bo pole “onlyDirect” w komponentach jest ustawione na true)

Program na RaspberryPi który odpalacie poleceniem ./runme.sh tworzy połączenie websocketowe z platformą RemoteMe oraz zarządza skryptem pythonowym (wysyła do niego wiadomości, przesyła wiadomości ze skryptu dalej do platformy etc ). Działanie skryptu pythonowego jest możliwe dzięki dodatkowym bilbiotekom RemoteMe (znajdują sie w folderze leafDevices/base/ ).

Sama strona internetowa po websocketach łączy się do platformy RemoteMe (pozwalają na to skrypty javascriptowe zaimportowane w headerze pliku index.html ze ścieżek /libs/). Ułatwiają i ustanawiają komunikacje z platformą RemoteMe. Same komponenty wstawione w index.html typu : <variable component="**" W funkcjach pliku remoteMeComponents.js są zastępowane na “standardowe” i “bootstrapowe” komponenty htmlowe, dodatkowo do komponentów przypinane są eventy reagujące na akcje użytkownika i wysyłające odpowiednie komunikaty do skryptu pythonowego. Można podejrzeć jak  remoteMeComponents.jszamienia i tworzy nowe komponenty – może to być interesujące gdy macie potrzebę stworzenia własnych komponentów, które RemoteMe nie pozwala dodać z kreatora. W większości przypadków akcje Waszych komponentów będą wykonywać zapis zmiennych w postaci

RemoteMe.getInstance().getVariables() .setSmallInteger2("cameraPos",123,456,true); 

która wyśle do skryptu pythonowego informacje o zmianie zmiennej, podobnie sterujemy silnikami ustawiając odpowiednią zmienną.

Podsumowanie

Tworząc tej projekt chciałem pokazać Wam jak w łatwy sposób sterować Waszym samochodem z widokiem  FPV. Projekt można rozbudowywać, lub zmieniać np, gdy korzystanie z innego mostka H niż ja. Zachęcam zatem do eksperymentowania ze źródłami projektu 🙂 . Gdy jest to Wasz pierwszy projekt, zachęcam do zrobienia na początek projektu z mrugającą diodą i poczytanie dokumentacji na www.remoteme.org

 

Pozdrawiam,

Maciej