Sterowanie gestami ma wiele zalet w szerokim zakresie aplikacji. W przypadku systemów sterowania gesty mogą być bardzo intuicyjne, co pozwala przyspieszyć naukę sterowania. Dodatkową zaletą tego rodzaju sterowania jest fakt, że pozwala zwolnić ręce kierującego. Nie musi on trzymać dłoni na kontrolerze, co pozwala mu na szybsze reagowanie na bodźce z otoczenia lub po prostu robienie czegoś innego w tym samym czasie. Nawet jeśli jest to zabawka, to demonstruje ciekawą koncepcję sterowania.
Zaprezentowany system do zdalnego sterowania pojazdu kołowego został zbudowany na bazie dwóch modułów micro:bit. Jeden jest odpowiedzialny za kontrolę silników w pojeździe, a drugi jest kontrolerem zdalnego sterowania, który odczytuje gesty użytkownika. Konstrukcja została opracowana, jak pisze autor – Anas Osama z Egiptu, na konkurs na portalu Instructables.com. Celem konkursu jest popularyzacja projektów zawierających moduł BBC micro:bit, dlatego moduł ten pełni zasadniczą funkcję w projekcie. Dodatkowo, jak pisze sam autor, jest to ciekawa odskocznia od Arduino, które wiele razy stosował w swoich projektach.
Potrzebne elementy
Do budowy kontrolera odczytującego gesty potrzebny będzie jedynie sam moduł BBC micro:bit wraz z zasilaniem dla niego. Zasilanie może pochodzić np. z powerbanku poprzez złącze USB na samym module.
Do budowy samochodziku potrzebnych będzie więcej komponentów, kluczowe z nich to:
- moduł BBC micro:bit,
- płytka wyprowadzeń dla micro:bit, która umożliwia podłączenie większej liczby linii do modułu,
- mostek H z driverem mocy dla silników,
- bateria 9 V,
- silniki zintegrowane z przekładniami i kołami – taki element istotnie upraszcza mechaniczną konstrukcję systemu.
Kontroler
Ten moduł jest odpowiedzialny za rozpoznawanie gestów. Do ich wykrywania wykorzystywany jest wbudowany akcelerometr. Kod programu zaprezentowany jest na dwa sposoby – w postaci graficznej, przygotowanej przy użyciu Microsoft MakeCode (rysunek 1) oraz w postaci skryptu, napisanego w Pythonie (listing 1). Niezależnie od sposobu zapisu program działa tak samo.
sensitivity = 215 # Stała, która odpowiada za poziom czułości kontrolera.
radio.set_group(5)
# W pętli program sprawdza akcelerometr i monitoruje kierunek pochylenia kontrolera.
def on_forever():
if input.acceleration(Dimension.Y) >= sensitivity and
input.acceleration(Dimension.Y) > input.acceleration(Dimension.X):
# Kontroler pochylony w przód
basic.show_arrow(ArrowNames.North)
radio.send_number(1) # Rusz auto do przodu
else:
if input.acceleration(Dimension.Y) <= 0 – sensitivity and
input.acceleration(Dimension.Y) < input.acceleration(Dimension.X):
# Kontroler pochylony do tyłu.
basic.show_arrow(ArrowNames.South)
radio.send_number(2) # Rusz auto do tyłu.
else:
if input.acceleration(Dimension.X) >= sensitivity and
input.acceleration(Dimension.X) > input.acceleration(Dimension.Y):
# Kontroler pochylony w prawo.
basic.show_arrow(ArrowNames.East)
radio.send_number(3) # Skręć w prawo.
else:
if input.acceleration(Dimension.X) <= 0 – sensitivity and
input.acceleration(Dimension.X) < input.acceleration(Dimension.Y):
# Kontroler pochylony w lewo.
basic.show_arrow(ArrowNames.West)
radio.send_number(4) # Skręć w lewo.
else: # Brak wykrytego pochylenia.
basic.show_icon(IconNames.No)
radio.send_number(0) # Zatrzymaj auto.
basic.forever(on_forever)
Po uruchomieniu system konfiguruje komunikację radiową do pracy w grupie piątej oraz ustawia stałą sensitivity jako 215. Stała ta definiuje poziom czułości kontrolera – jeśli nie odpowiada naszym potrzebom, możemy ją zmienić i dopasować do własnych potrzeb. Dalsza część programu składa się z jednej nieskończonej pętli, w której znajdują się instrukcje warunkowe. Za ich pomocą sprawdzane jest pochylenie modułu poprzez porównanie wartości przyspieszenia we wszystkich kierunkach. Kierunek, w którym jest największe przyspieszenie, jest kierunkiem, w którym poruszać będzie się auto (o ile rejestrowane przyspieszenie będzie większe niż czułość zdefiniowana stałą sensitivity).
Skąd bierze się przyspieszenie, mierzone przez akcelerometr, skoro jest on nieruchomy? Rejestrowane przyspieszenie to rzut przyspieszenia ziemskiego na osie X i Y (w płaszczyźnie Ziemi) akcelerometru. Jeśli kontroler znajduje się idealnie pionowo, to przyspieszenie ziemskie oddziałuje idealnie w osi Z akcelerometru. Im bardziej jest przechylany, tym bardziej przyspieszenie ziemskie oddziałuje na oś w kierunku której przechylany jest moduł, do momentu, gdy oś X lub Y znajdzie się w miejscu, gdzie początkowo znajdowała się oś Z i mierzyć będzie pełne przyspieszenie ziemskie. Taki system pozwala na wykrywanie położenia płytki względem ziemskiego pola grawitacyjnego, a w konsekwencji względem powierzchni Ziemi. Tego rodzaju algorytm używany jest np. w smartfonach do wykrywania przekręcenia telefonu, aby obrócić ekran, gdy przekręcamy urządzenie.
Sterownik pojazdu
Drugi moduł BBC micro:bit służy do sterowania silnikami, zgodnie z odbieranymi przez połączenie radiowe komunikatami, wysyłanymi z kontrolera. Moduł ten można, podobnie jak mikrokontroler w kontrolerze, oprogramować na dwa sposoby – graficznym kodem utworzonym w MS MakeCode (rysunek 2) lub skryptem w Pythonie (listing 2).
# Zmienna do przechowywania wartości odebranej przez radio
value = 0
radio.set_group(5)
# Nieskończna pętla jest pusta – nie jest potrzebna
# wszystko realizuje przerwanie radia
def on_forever():
pass
basic.forever(on_forever)
# Funkcja przerwania, uruchamiana po
# odebraniu informacji przez radio
def on_radio_received_number(arg0):
global Value
Value = arg0
# Ruch do przodu
if Value == 1:
basic.show_arrow(ArrowNames.North)
pins.digital_write_pin(DigitalPin.P2, 1)
pins.digital_write_pin(DigitalPin.P0, 1)
pins.digital_write_pin(DigitalPin.P1, 0)
pins.digital_write_pin(DigitalPin.P11, 1)
pins.digital_write_pin(DigitalPin.P5, 1)
pins.digital_write_pin(DigitalPin.P8, 0)
else:
# Ruch do tyłu
if Value == 2:
basic.show_arrow(ArrowNames.South)
pins.digital_write_pin(DigitalPin.P2, 1)
pins.digital_write_pin(DigitalPin.P0, 0)
pins.digital_write_pin(DigitalPin.P1, 1)
pins.digital_write_pin(DigitalPin.P11, 1)
pins.digital_write_pin(DigitalPin.P5, 0)
pins.digital_write_pin(DigitalPin.P8, 1)
else:
# Skręt w prawo
if Value == 3:
basic.show_arrow(ArrowNames.East)
pins.digital_write_pin(DigitalPin.P2, 1)
pins.digital_write_pin(DigitalPin.P0, 0)
pins.digital_write_pin(DigitalPin.P1, 1)
pins.digital_write_pin(DigitalPin.P11, 1)
pins.digital_write_pin(DigitalPin.P5, 1)
pins.digital_write_pin(DigitalPin.P8, 0)
else:
# Skręt w lewo
if Value == 4:
basic.show_arrow(ArrowNames.West)
pins.digital_write_pin(DigitalPin.P2, 1)
pins.digital_write_pin(DigitalPin.P0, 1)
pins.digital_write_pin(DigitalPin.P1, 0)
pins.digital_write_pin(DigitalPin.P11, 1)
pins.digital_write_pin(DigitalPin.P5, 0)
pins.digital_write_pin(DigitalPin.P8, 1)
else:
# Zatrzymanie pojazdu
basic.show_icon(IconNames.No)
pins.digital_write_pin(DigitalPin.P2, 0)
pins.digital_write_pin(DigitalPin.P0, 0)
pins.digital_write_pin(DigitalPin.P1, 0)
pins.digital_write_pin(DigitalPin.P11, 0)
pins.digital_write_pin(DigitalPin.P5, 0)
pins.digital_write_pin(DigitalPin.P8, 0)
radio.on_received_number(on_radio_received_number)
W konfiguracyjnej części kodu – tej, która uruchamiana jest jednorazowo po uruchomieniu mikrokontrolera, konfigurowane jest połączenie radiowe ponownie na kanał 5., aby nawiązać komunikację z kontrolerem. W tym miejscu inicjalizowana jest także zmienna globalna Value, która służy do przechowywania wartości kodu odebranego przez radio. Główna, nieskończona pętla programu jest pusta, a działanie programu skupia się w przerwaniu z odbiornika radiowego, które obsługiwane jest funkcją on_radio_received_number, która dołączona jest do modułu radiowego poprzez metodę: radio.on_received_number(on_radio_received_number). Funkcja obsługująca przerwanie otrzymuje pojedynczy argument – wartość kodu, przekazana przez moduł radiowy (arg0). Parametr ten przepisywany jest do zmiennej Value. Następnie w zależności od wartości zmiennej Value układ realizuje odpowiedni manewr: jeśli Value równe jest 1, pojazd jedzie do przodu; jeśli równe 2, pojazd jedzie do tyłu; jeśli 3 lub 4, samochód skręca, odpowiednio, w prawo lub w lewo. Przy otrzymaniu dowolnego innego kodu auto zatrzymuje się.
Kontrola silników krokowych jest bardzo prosta. Auto ma dwa zestawy silników, podłączone do dwóch mostków H, pozwalające na obracanie się w obu kierunkach. Silniki zasilane są z zewnętrznego źródła zasilania, gdyż potrzebują wyższego napięcia niż moduł micro:bit. W tym celu zastosowano baterię 9 V. Silniki podłączone są tak, jak na rysunku 3, w tym przypadku pokazano połączenia na płytce stykowej, ale nie powinno być to problemem w zrozumieniu schematu. Płytka BBC micro:bit dołączona jest poprzez moduł rozszerzeń do płytki stykowej. Sam moduł micro:bit nie ma takiej możliwości z uwagi na nietypowe wyprowadzenia w postaci złącza krawędziowego.
Do wyprowadzeń cyfrowych podłączony jest mostek H zintegrowany z kontrolerem w sposób opisany w tabeli 1.
Podsumowanie
Po załadowaniu programu do każdego z modułów (kontrolera i sterownika pojazdu) przez USB system jest gotowy do działania. Przechylanie pilota w odpowiednim kierunku spowoduje, że auto będzie podążało w danym kierunku. Trzymanie kontrolera prosto, bez pochylania go w którymś kierunku, powoduje, że auto się zatrzymuje. Jeśli sterowanie autem reaguje zbyt nagle na przechylenia pilota, konieczna może być redukcja czułości systemu poprzez zwiększenie stałej sensitivity. Należy dopasować ją do własnych wymagań, a następnie przekompilować i wgrać ponownie kod do pilota. Nie ma potrzeby aktualizowania oprogramowania kontrolera przy takiej zmianie.
Interfejs tego rodzaju może być implementowany w szerokiej gamie urządzeń – nie tylko zdalnie sterowanych zabawkach. Sterowanie za pomocą gestów, jak zaprezentowano powyżej, może być zaimplementowane np. w specjalnych rękawiczkach, które pozwalają na kontrolę systemu – przy jednoczesnym zachowaniu możliwości poruszania dłonią. Taki interfejs jest bardzo naturalny dla człowieka – sterowany pojazd podąża bezpośrednio za ruchami dłonią. Dodatkowo można w systemie zaimplementować np. sterowanie prędkością silników na podstawie kąta pochylenia sensora, a także zastosować szereg bardziej zaawansowanych algorytmów, redukujących wpływ szumu pomiarowego itp. na działanie układu.
Nikodem Czechowski, EP
Źródła projektu: