Arduino jako joystick USB (LUFA i HID) – cz. 3

W poprzednich odcinkach (część 1 oraz część 2) udało mi się przekompilować firmware czipu AtMega16U2 komunikującego Arduino UNO z arduino_joystick_shieldkomputerem. Teraz spróbuję zamienić Arduino z nałożnym rozszerzeniem Funduino w… kontroler do gier dla RetroPie:)
W tym celu wymienię firmware AtMega16U2 na taki, dzięki któremu Arduino będzie rozpoznane jako akcesorium USB typu joystick z przyciskami.

Funduino

Funduino to rozszerzenie dla Arduino UNO/Mega, które ma na sobie joystick i 7 przycisków. Joystick działa w 2 osiach. Reaguje również na wciśnięcie (przycisk K). Na płytce są 4 kolorowe przyciski (A, B,C, D) oraz 2 mniejsze tact-switche E i F.

Osie joysticka podłączono do wejść analogowych A0 i A1. Przyciski podłączono do pinów cyfrowych:

Przycisk PoRT
A 2
B 3
C 4
D 5
E 6
F 7
Oś X A0
Oś Y A1

Całkiem fajny kod do obsługi znalazłem na blogu All About Circuits. Czytanie z joystika nie jest problemem – wystarczy tu funkcja analogRead(), np:

Kolejną przydatną funkcją jest „map()”. Funkcja „map()” skaluje wartość zmiennej z jednego przedziału na wartość z innego przedziału. Funkcja „analogRead()” zwraca wartości z przedziału 0..1023. Załóżmy, że pozycja joysticka zawiera się w granicach -100…100. Wtedy:

Dlaczego akurat-100 i 100? Do tego dojdziemy za chwilę.

A co z czytaniem przycisków. Schemat postępowania jest następujący:

Kilka szczegółów:

  • W funkcji „setup()”, port. do którego podłączony jest klawisz, ustawiamy jako wejściowy (pinMode(…,INPUT);),
  • Wywołanie „digitalWrite(…,HIGH)” powoduje włączenie na porcie rezystora podciągającego do stanu wysokiego. w ten sposób, gdy przycisk jest rozłączony – pin nie „pływa” (jest w stanie wysokim). Jeżeli przycisk jest wciśnięty – zwracana jest wartość niska – stąd porównanie do LOW,
  • W funkcji loop() sprawdzamy stan portu funkcją digitalRead() – jeżeli jest niski, wciśnięto przycisk.

Tą samą procedurę należy zastosować dla każdego z przycisków.

Jeszcze jedna uwaga konstrukcyjna: Funduino nałożone na Arduino wystaje poza jego krawędź. Jeżeli myślicie nad jakąś sprytną obudową – weźcie to pod uwagę.

Firmware AtMega16U2

Cały potrzebny mi kod znalazłem na githubie harlequin-tech. Przykłady zbudowano na Lightweight USB Framework for AVRs – LUFA. W największym skrócie, LUFA to takie specjalne oprogramowanie, które pozwala zamieniać kontrolery AVR w urządzenia USB.

Przykłady dostarczone przez harlequin-tech zbudowano na dość starej wersji LUFA:100807. W tej chwili na stronie tego projektu LUFA wystawiono wersję 151115. W porównaniu do 100807 zaimplementowano wiele zmian – również w samym API. Z tego powodu przykłady z harlequin-tech wymagają kilku poprawek. Możecie to zrobić, ja (po krótkim, acz nieudanym teście) postanowiłem pozostać przy wersji 100807. Zwłaszcza, że jeżeli spojrzycie do katalogu Arduino IDE: „.hardware/arduino/avr/firmwares/atmegaxxu2/” (a więc źródła dla AtMega16U2 zamontowanego na płytce Arduino), w pliku „readme.txt” znajdziecie: should be compiled against LUFA 100807. Dlatego ta wersja wydaje mi się dobrym pomysłem.

Kilka poprawek do firmware…

Tutaj oparłem się (prawie) całkowicie na kodzie z forum Arduino. oraz kodzie z githuba harlequin-tech. Będę operował na plikach w katalogu ‚./firmwares/arduino-joystick’. Trzeba wykonać kilka zmian.

W makefile:

Załóżmy teraz, że do przesyłania danych z Funduino, użyjemy takiej struktury:

Zmienne x i y dotyczą joysticka. Zmienna buttons dotyczy klawiszy. Każdy klawisz to 1 bit w buttons. Ustawiony na „1” oznacza „wciśniśnięty”, 0 – zwolniony. Zamieńcie oryginalną strukturę USB_JoystickReport_Data_t w pliku Arduino_joystick.h na tą podaną powyżej.

W pliku Arduino_joystick.c podmieńcie funkcję na poniższą:

Oryginalny przykład obsługuje tylko 2 przyciski – Funduino ma 7. W związku z tym, w pliku descriptors.c trzeba zmienić zawartość tablicy JoystickReport na taki:

Zadeklarowaliśmy właśnie struktury, w jakich wysyłane będą dane z Arduino. Przyznam się szczerze, że nie chciało mi się przebijać przez dokumentację do HID i kod zmieniłem… trochę metodą prób i błędów. Każda para liczb to kod poszczególnych deskryptorów i ich wartości. Poprawne ustawienie tych deskryptorów jest warunkiem, żeby Arduino zostało prawidłowo rozpoznane a podłączone do niego urządzenie – zrozumiało nadawane przez niego dane.

Znaczenie niektórych wpisów (0x oznacza liczby heksadecymalne):

  • Report size (0x75): rozmiar danych wysyłanych do hosta, tutaj: w bitach. Pozycję joysticka będziemy wysyłać po bajcie (int8_t, 8 bitów), stąd dla joysticka 0x75, 8 w górnej sekcji; każdy klawisz zajmie 1 bit, stąd 0x75,1 w dolnej sekcji;
  • Report count (0x95): w wolnym tłumaczeniu: ilość raportowanych zmiennych; dla joysticka to 2 (pozycja x i y) – stąd 0x95,2; dla przycisków wysyłam 7 bitów (po jednym na przycisk) – 0x95,7; ALE UWAGA: dla przycisków muszę dopełnić te 7 bitów do 32 – rozmiaru zmiennej buttons w strukturze. Stąd na dole dodatkowy raport (jeden; 0x75,1) o rozmiarze 25 bitów (bo 7+25=32) – 0x95,25
  • Usage minimum (0x19): minimalna ilość przycisków: 1
  • Usage maximum (0x21): maksymalna ilość przycisków: 7
  • Logical Minimum (0x15): minimalna wartość zmiennej w raporcie; dla przycisku to będzie 0 (0x15,0) – dla joysticka… no właśnie: pozostawiłem -100 jak w oryginale,
  • Logical Maximum (0x25): maksymalna wartość zmiennej; dla przycisku: 1 (wciśnięty) a joysticka 100 (0x25,0x64).

Autor posta użył 32 bitowej zmiennej buttons po to, żebyście mogli wygodnie dodawać więcej przycisków. Przykładowo dla 10, dolna sekcja mogłaby wyglądać tak:

Teraz pozostało skompilować. Wejdźcie do katalogu ./firmwares/arduino-joystik i po prostu wykonajcie komendę najpierw „make clean” a potem „make”.

Ja używam linuxa – ale w poprzednim tekście na ten temat (tutaj) podałem sposób na kompilację pod windows.

Powinno się udać. W wyniku kompilacji powinniście uzyskać plik Arduino-joystick.hex.

Teraz podłączcie atmega16u2 do programatora (szpilki bliżej gniazda USB) i wgrajcie na niego nowy firmware:

Szkic

Teraz czas na szkic. Niestety musicie go wgrywać przy pomocy programatora – przecież właśnie przeprogramowaliście czip USB:)

Pod Windows…

Możecie sprawdzić działanie Funduino na Windows. Podłączcie Arduino z Funduino do portu USB i w Windowsie:

  • Wciśnijcie klawisz ‚Windows’ i wpiszcie ‚USB’
  • Z listy wybierzcie: Skonfiguruj kontrolery gier podłączane przez USB:
    widows8_install_usb
  • Otworzy się okno ‚Kontrolery gier’:
    arduino_lufa_joystick
  • Kliknijcie ‚Właściwości’ – będziecie mogli przetestować działanie joystika:
    windows_00

I demo:

Źródła

  • http://forum.arduino.cc/index.php?topic=99.0
  • https://github.com/NicoHood/HoodLoader2
  • http://hunt.net.nz/users/darran/blog/
  • http://smartinteractionlab.com/lufa-example-turning-your-arduino-into-a-keyboard/
  • http://forum.arduino.cc/index.php?topic=111.30
  • http://hunt.net.nz/users/darran/

Dodaj komentarz