Hej,
w poprzednim kursie tutaj Zamieściłem kurs jak sterować i dostać obraz z kamerki na tablet, jest to tak naprawdę projekt wprowadzający do systemu remoteME. Tym razem coś fajniejszego. Samochód sterowany przez tablet z podglądem kamery.
Na filmie działanie:
UWAGA Nie posiadam wykształcenia elektronicznego więc proszę posprawdzajcie wszystkie połączenia samodzielnie
Co potrzebujemy:
- Podgląd
- Raspberry PI Zero W
- Dedykowanej kamery
- 12-kanał sterownik LED 16-bit PWM I2Czgodny z Adafruit ( link ) 22zł
- Dwa serwo mechanizmy kompatybilne z uchwytem na kamerkę (np SG90) ( link) 2*9.9zł =20zł
- Uchwyt na kamerke (link) 7.8 zł
- baterie – uzylem akumlatorkow AA w ilosci 10 sztuk
- mostek H do sterowania silnikami od kół (link) 29 zł
- najlepiej wytrawić sobie sterownik link do plikow eagle
- przetwornica napięcia link 4.9zl
- platforma robota link 75 zł
Połączenia
RaspberryPI steruje serwami poprzez modul PWM I napedem poprzez ustawianie stanu pinow na mostku I dostarczająć sygnału PWM poprzez ten sam moduł który wysyła sygnal do serwomechanizmow schemat połączeń (Urpszczony pominąłem konvertery stanów logicznych przy użyciu części o których wspomniałem konwetery nie są konieczne)
Ten sam schemat jako plytka PCB:
I po wytrawieniu ( na obrazku zamowiona plytka z allPCB)
I druga strona z opisem wyprowadzeń:
płytka w formacie Eagle do pobrania stąd zaprojektowałem ją tak żeby łatwo dało się ją skonstruować metodą termotransferu
- Wejście sygnału PWM z kanałów 15 i 14 modułu PWM:
- Wejście zasilania silników do poruszania się
- Zasilanie układów (PWM, RPi) koniecznie dokładne +5V
- Wyjście silników napędu, pierwsze dwa wyjscia do jednej pary silników kolejne dwa do drugiej
- Zasilanie serw i w tym przypadku silników napędu w moim przypadku ~7V (należy sprawdzić w specyfikacji serw i silników jakie maksymalne napięcie można podłączyć)
- ZWORKA gdy zepniemy dwa piny napięcie z 5 będzie podawane też do zasilania silników napędu
- 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
- Wlutowujemy kabelki bo nie będziemy korzystali z konwertera stanów
Całe oprogramowanie po stronie RPi jest napisane w pythonie przy użycoiu dwoch bibliotek:
- import RPi.GPIO as GPIO – sterowanie pinami 25, 8, 24, 23 do włączenia odpowiednich trybów MostkaH:
A/B IN1 A/B IN2 PWM A/B Wyjście silników stan
wysokistan
niski% wypełnienia Silnik kręci się z prędkością zadaną poprzez pwm, w prawą stronę stan
niskistan
wysoki% wypełnienia
>0
Silnik kręci się z prędkością zadaną poprzez pwm, w lewą stronę stan
niskistan
niskibez
znaczeniaswobodne hamowanie
stan
wysokistan
wysokibez
znaczeniaswobodne hamowanie
bez
znaczeniabez
znaczeniastan niski
wypelnienie =0
Zatrzymanie silników
- import Adafruit_PCA9685 do sterowania układem PWM
Piny w RPi podłączone są nasepująco 25-AIN1, 8-AIN2, 24-BIN1, 23-BIN2 (notacja BCM) i sterują trybem pracy mostka H. Mostek H wymaga również sygnału PWM do sterowania szybkością silników, ponieważ w projekcie mam już generator PWM który używam do sterowania serwo Mechanizmami użyłem go też do sygnałów PWM dla mostka.
Moduł PWM komunikuje się z RPi poprzez interfejs I2C i ardafruit udostępnił bilbioteke do jego sterowania : Adafruit_PCA9685 .
Składanie samochodu
zaczynamy od złożenia platformy robota. Silniki z prawej strony i lewej łączymy ze sobą i do obydwu doprowadzamy kabel zasilający. Ważne żeby po zasileniu silników kręciły się one w tą samą stronę tzn koła z prawej strony kręca się zawsze jednocześnie w tym samym kierunku, to samo lewa strona samochodu.
Całość wygląda tak:
Zasilanie
Opcja 1, ładowane akumlatorki AA
Uzylem 10 paluszkow AA w dwóch koszykach po 5 sztuk. Wg schematu:
Otrzymałem w ten sposób stabilne napięcie 5v do zasilania układu PWM i RPi oraz ~7V do zasilania serw i silników. Uwaga sprawdźcie maksymalne napięcie dla waszych serw i silników może się okazać ze 7v to za dużo.
Do baterii dołączyłem gniazdo Jack, wpinane do przetwornicy w stelażu z wygiętej pleksi
podłączenie baterii:
Na czerwono potrzebne zworki
Opcja 2: akumlator np Li-Po
W tym przypadku serwo mechanizmy i silniczki napędu są zasilane osobno różnym napięciem. Potrzebujemy dwie przetwornice napięcia:
na czerwono potrzebne zworki
Opcja z akumlatorem LI-PO jest lepsza:
- Większa pojemność
- Większe napięcie do sterowania silnikami napędu = większa szybkość
- Mniejsze prawdopodobieństwo ze w czasie ruszania spadek napięcia będzie na tyle duży ze zresetuje nam RPi
Lutowanie:
Oczywiśce moduł PWM i RPi jest wpinany poprzez gniazda.
dodatkowo moduł PWM jest usztywniony dystansami
Całość prezentuje się tak:
Tak zbudowaną konstrukcje umieściłem na nadbuduwce z plexy na samochodzie:
Wymagało to wywiercenia dodatkowego otworu w samej płytce.
Na końcu montujemy kamerkę (w kursie tutaj pisałem jak skalibrować położenie kamery, oraz jej zmontowanie). Jeżeli nie chcecie korzystać z tutoriala to po prostu ustawcie położenia serwo mechanizmów w pozycji centralnej ( ustalcie maksymalne wychylenie w prawo, w lewo i ustawcie pozycję pomiędzy). Tak ustawione serwo mechanizmy wmontujcie w uchwyt kamery tak, żeby kamera “patrzyła” na wprost (jak na screenie)
Całość prezentuje się tak:
Konfigurowanie Remoteme.org
Przedstawie jedynie kroki bez omawiania szczegołów, bo szczegóły omówiłem w kursie tutaj.
- Tworzymy konto
- przechodzimy do zakładki tokens przyciskiem new tworzymy nowy token
- nasz token to : ~1_&p@+BNnZ@A+x8 (oczywiście Wasz będzie inny)
RaspberryPI:
-
123git clone git://github.com/remoteme/remoteme.gitcd remotemepython3.5 install.py
- Potwierdzamy wpisująć Y na pytania instalatora
- gdy instalator prosi o token wklejamy ~1_&p@+BNnZ@A+x8 z poprzedniego kroku Enter
- nazwa np Rpi
- deviceId 1 Enter
- po zakończeniu pracy uruchamiamy program
-
1./runme.sh
Wracamy do systemu app.remoteme.org
nasze RPI powinno być podłączone:
Dodajemy skrypt samochodu:
po dodaniu nasz skrypt samochodu jest podłączony jego Id to 2:
teraz dodamy stronę internetową do sterowania najpierw wersja desktop:
New -> WebPage
Teraz musimy ustawić id skryptu pythonowego, żeby strona internetowa “wiedziała” gdzie wysyłać wiadomości:
W moim przypadku jest to liczba 2:
edycja index.html:
zmieniamy :
I otwieramy stronę w nowej zakładce:
Konfiguracja kamery:
Gdy poruszamy myszką w rejonie obrazu pozycja kamery powinna się nam zmieniać tak jak jest to w przypadku gier FPS
a gdy pozycja myszki jest w centrum samochów powinen “patrzeć” na wprost. skonfigurujmy zatem kamerę
Jeżeli poruszamy pozycją myszki i ruszamy myszką od lwewj do prawej a kamera nam się porusza góra dół, to zamieniamy miejscami kable serwo mechanizmów w układzie generowania PWM.
Centrowanie pozycji kamery i zakres ruchów
u mnie centrum kamery jest dla wartosści 560 i 430, zakres ruchów dla obu osi to 200. Poeksperymentujcie z wartościami tak żeby uzyskać najlepszy efekt. Jeżeli skorzystaliście z tego tutoriala to po prostu wpiszcie odpowiednie wartości.
Jeżdżenie:
jeżeli wciśniecie strzałki na klawiaturze zegary na stronie będą się poruszać najpierw wypróbujcie ruch przód tył jeżeli samochód zamiast jechać do przodu skręca:
w tych miejscach dajcie\usuwajcie minusy:
Wynika to z polaryzacji silników:
Minus “zamienia” wyjściami wyjście 1 z wyjściem 2 i 3 z 4. W moim przypadku wygodniej dopisać skasować minus niż bawić się z kablami bo one są już we wtyczce która pasuje tylko w jednej pozycji:
Po zabawie z minusami, samochód powinien jeździć prawidłowo przód/tył. Teraz skręcanie strzałka lewa na klawiaturze samochód skręca w lewo. Jeżeli tak się nie dzieje to zmieniamy miejscami wtyczki silników:
Albo jeżeli to niemożliwe bo wlutowaliście na stałe znajdujecie kod:
1 2 3 4 5 |
pos=putByte(ret, pos ,carController.getMotorMode(carController.getRightSideSpeed()) ); pos=putByte(ret, pos ,Math.abs(carController.getRightSideSpeed()*255 )); pos=putByte(ret, pos ,carController.getMotorMode(-carController.getLeftSideSpeed()) ); pos=putByte(ret, pos ,Math.abs(carController.getLeftSideSpeed()*255) ); |
i zamieniacie kolejność wysyłania silnika prawego i lewego
1 2 3 4 5 |
pos=putByte(ret, pos ,carController.getMotorMode(-carController.getLeftSideSpeed()) ); pos=putByte(ret, pos ,Math.abs(carController.getLeftSideSpeed()*255) ); pos=putByte(ret, pos ,carController.getMotorMode(carController.getRightSideSpeed()) ); pos=putByte(ret, pos ,Math.abs(carController.getRightSideSpeed()*255 )); |
i ustawiamy na nowo minusy ;)
Jak zauważycie jak wciśniemy strzałki do przodu to samochód nie jedzie z pełną prędkością tylko strzałka na liczniku zatrzymuje się w miejscu wtedy puszczamy strzałkę “do przodu” i szybko z powrotem ją wciskamy :)
Jak to działa
Strona internetowa wysyła do skryptu pythonowego wiadomosć w formacie:
- 1 bajtowy integer wartość 1
- 2 bajtowy integer pozycja kamery w osi X
- 2 bajtowy integer pozycja kamery w osi Y
- 1 bajtowy integer tryb pracy silników po prawej stronie samochodu (1 ruch do przodu, 3 ruch do tyłu, 2 swobodne chamowanie)
- 1 bajtowy integer prędkość pracy silników po prawej stronie
- 1 bajtowy integer tryb pracy silników po lewej stronie samochodu (1 ruch do przodu, 3 ruch do tyłu, 2 swobodne chamowanie)
- 1 bajtowy integer prędkość pracy silników po lewej stronie
skryp pythonowy odbiera tą wiadomość i na jej podstawie ustawia kamerę i silniki.
dokładny moment wysyłania wiadomości jest tutaj (script.js):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
function sendNow(){ carController.compute(); leftSideSpeedMeter.setValue(carController.getLeftSideSpeed()*255 ); rightSideSpeedMeter.setValue(carController.getRightSideSpeed()*255 ); var ret = new Uint8Array(9); var pos=0; pos=putByte(ret, pos ,1);//mode 1 send camera and motors pos=putShort(ret, pos ,carController.getCameraX() ); pos=putShort(ret, pos ,carController.getCameraY() ); pos=putByte(ret, pos ,carController.getMotorMode(carController.getRightSideSpeed()) ); pos=putByte(ret, pos ,Math.abs(carController.getRightSideSpeed()*255 )); pos=putByte(ret, pos ,carController.getMotorMode(-carController.getLeftSideSpeed()) ); pos=putByte(ret, pos ,Math.abs(carController.getLeftSideSpeed()*255) ); remoteme.sendUserMessageByFasterChannel(carScriptDeviceId,ret); } |
Po stronie pythona – plik python.py:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
def onUserMessage(senderDeviceId, data): global pwm data = struct.unpack('>BhhBBBB', data) if data[0] == 1: positionX = data[1] positionY = data[2] motorLeftMode = data[3] motorLeftSpeed = data[4] * 16; motorRightMode = data[5] motorRightSpeed = data[6] * 16; pwm.set_pwm(1, 0, positionX) pwm.set_pwm(0, 0, positionY) setMotor(0, motorLeftMode, motorLeftSpeed) setMotor(1, motorRightMode, motorRightSpeed) |
opis klas, funkcji itd:
Zachęcam do eksperymentowania :)
Sterowanie tabletem
Dodajemy stronę internetową identycznie jak desktopa tym razem wybieramy szablon:
następnie wszytko konfigurujemy identycznie jak stronę do sterowania przez komputer.
Format wysyłanej wiadomości jest taki sam więc korzystamy z tego samego skryptu pythonowego :)
Jeżeli sterowanie nie działa poza siecią lokalną należy skonfigurować serwer Turn opis tutaj
zamiast przypisywać adres do tabletu polecam zeskanować kod QR:
szczegółowy opis kodów QR tutaj
w miejsce 1 umieszczamy lewego kciuka, w 2 prawego, nie musimy to robić dokładnie system się skalibruje automatycznie. I sterujemy lewym kciukiem prędkość i kierunek, a prawym kamerkę.
Podsumowanie
Mam nadzieje że wszystko wydaje się proste, co do programów to zachęcam do eksperymentowania i zapoznania się z poprzednim kursem tutaj gdzie dokładniej omówiłem zagadnienia z systemem remoteme.org, a nawet wszytko umieściłem na filmie.
Pozdrawiam,
Maciek
Zostały mi płytki z allPCB (te zielone) rozdaje na moim FB
Gratuluję projektu. Dwa lata temu w oparciu o Rapsberry B konstruowałem podobny projekt https://majsterkowo.pl/pojazd-wielofunkcyjny/. Pod względem technicznym (wytrawiona płytka) Twoj jest o lata świetlne doskonalszy. Technologicznie Raspberry 0 też bije na głowę moją starą malinę. Najbardziej zazdroszę jednak tak płynnego obrazu. Widać tutaj ogromny postęp w kolejnych wersjach mikrokomputerów! Tym bardziej, że jeśli dobrze zrozumiałem wysyłasz obraz w chmurę. Jaki upload zapewnia Ci Twój operator? Zapewne to światłowód?
Dzieki,
” Najbardziej zazdroszę jednak tak płynnego obrazu. Widać tutaj ogromny postęp w kolejnych wersjach mikrokomputerów! ” <– to nie tak ;), moc obliczeniowa moca obliczeniowa ale tutaj sie liczy technologia przesylania. i slowo klucz WebRTC – tworzy on bezposrednie poleczenie RPiprzegladarka i obraz nie jest wysylany do chmury tylko bezposrednio do przegladarki ( no chyba ze NAT to wtedy jest serwer posredniczacy ale on nie daje duzych opoznien).
Co do wykorzystywania pasma – nie sprawdzilem :/. ALE zaimplementowalem mechanizm (bardzo pomocny ten projekt z githuba https://github.com/kclyu/rpi-webrtc-streamer ) który dopasowuje rozdzielczosc przesylanego obrazu do przepustowosci :) no i oczywiscie kodek H.264 wiec wykrozystanie pasma mysle ze dosc niskie i napewno swaitlowod nie jest potrzebny ;)
Nad systemem app.remoteme.org spedzilem juz pol roku (oczywisice nie full time tylko takie radosne klikanie w klawiature po godzinach) wiec ciesze sie ze widać efekty :)
Ok wypróbuję WebRTC na tej starej malince i dam znać czy wyrabia. Pewnie już po ptakach… jest jeszcze szansa na płytkę?
Ciekawe czy dojdą do takiego zakresu, żeby zrobić DDoS nie na serwery danej firmy, ale żeby zatkać całe łącze, np. podmorski światłowód.
Czy można prosić o reupload zdjęć do projektu?