
Witajcie moi drodzy
Dzisiaj przedstawię mój projekt prostego gamepada (urządzenia sterującego na USB) z 4 osiami i dwoma przyciskami opartego o mikrokontroler PIC18F45K50.
Mój gamepad będzie oferować 4 tryby pracy (4 różne wsady):
- tryb UART (wymagający przejściówki)
- tryb gamepada/joysticka USB/HID Plug And Play
- tryb myszki USB/HID Plug And Play
- tryb CDC (wirtualny port COM podłączamy przez USB)
Skupię się tutaj na powyżej opisanych firmware i oczywiście udostępnię je wraz z kodem źródłowym.
Wstęp
Przedstawię tutaj zrobiony przeze mnie prosty gamepad zgodny ze standardem HID i działający na zasadzie plug and play. Będzie on składać się z następujących elementów:
- obudowa - zaprojektowana przeze mnie w 3D i wydrukowana na drukarce 3d (Creality Ender 3 PRO)
- serce układu (płytka z PIC18F45K50) - zaprojektowana przeze mnie w programie Eagle, samo PCB wyprodukowane w chinach, ale zlutowane już samodzielnie
- dwóch modułów gałek/joysticka - kupionych na Ebay
- odpowiedniego firmware dla mikrokontrolera - napisanego w MikroC PRO for PIC (właściwie to przedstawię kilka różnych firmware)
Kody źródłowe i pliki projektowe udostępnię w tym temacie do pobrania.
Do wgrywania firmware na PICa użyję mojego klona programatora PICKIT2.
Użyty moduł joysticka/gałki
Cały projekt oparłem o ogólnodostępne, tanie moduły gałki:

Oferują one:
- oś X (wychylanie prawo/lewo)
- oś Y (wychylanie przód/tył)
- przycisk (wciskanie gałki)
Obie osie oczywiście działają tak jak potencjometr, stanowią dzielnik napięcia między VDD i GND i można je odczytać poprzez ADC (Analog-to-Digital Converter).
Wyjścia modułu joysticka są opisane na PCB, ale można je przedstawić prosto na obrazku:

Do projektu użyłem dwóch takich modułów, by docelowo mieć 4 osie i 2 przyciski.
Użyte PCB
Do projektu użyłem zaprojektowanej przeze mnie wcześniej płytki PIC18F4550/PIC18F45K50 wykonanej w technologii SMD.
Jej rozmiar to 45mm na 30mm.


Schemat:

Jedna z wykonanych wcześniej sztuk:

Całość opisana jest tutaj:
https://www.elektroda.pl/rtvforum/topic3601583.html
Do projektu użyłem tej płytki w wersji z PIC18F45K50 bez zewnętrznego oscylatora, gdyż jego wewnętrzny oscylator 16MHz jest wystarczający dla USB:

Tutaj macie pełną notę katalogową mikrokontrolera którego użyłem (PIC18F45K50):
Zdaję sobie sprawę z tego, że nieco ładniej całość gamepada by wyszła na dedykowanej pod ten projekt płytce (można by zaprojektować te PCB tak, by moduły gałek joysticka wchodziły w nią na złączach kątowych), ale po prostu zostało mi tych starych płytek trochę i chciałem z nich skorzystać.
Załącznik: źródła Eagle tej płytki:
Załącznik: Gerbery tej płytki:
Lutowanie serca kontrolera z PIC18F45K50
Na potrzeby projektu zlutowałem kolejną sztukę mojej płytki z PIC18F45K50.
Przygotowałem mniej więcej to co będzie potrzebne:

Ta niebieska szpulka na zdjęciu powyżej to spoiwo lutownicze cynel Sn60Pb40 (o ile dobrze pamiętam) 0.1mm.
Do tego użyłem jeszcze m. in. topnik którego brakuje na zdjęciu.
Dodatkowo oczywiście moje "narzędzie do lutowania SMD":

... czyli najtańszą lutownicę oporową z regulacją temperatury.
Zacząłem od przylutowania złącza USB:

Następnie przylutowałem mikrokontroler PIC18F45K50 w obudowie TQFP44:

Potem przylutowałem też kondensatory 100nF, kondensator 220nF na pin VUSB oraz rezystor 10k od układu RESET i przycisk RESET.
Na koniec przylutowałem goldpiny:


Tak prezentowała się gotowa całość, jeszcze przed czyszczeniem z topnika:

Płytkę jeszcze dla pewności sprawdziłem multimetrem, ale nie było zwarć/zimnych lutów.
Pierwsze testy na stole
Na początek złożyłem wszystko poza obudową gamepada i testowałem na stole:

Obie gałki podłączyłem do pinów z ADC, czyli AN*:

Przyciski podłączyłem do portu B, a dokładnie do pinów RB0 i RB1, gdyż port B w PIC18F45(K)50 ma programowalne rezystory pull up:

(włącza się je wszystkie na raz z pomocą bitu RPBU z INTCON2)
Całość podłączyłem do mojego klona programatora PICKIT2 i jego softu używałem do programowania:


Dodatkowo do pinu TX PICa podłączyłem przejściówkę UART<->USB by móc szybciej testować czy całość działa.

Model 3D prototypu gamepada
Pierwszy model gamepada oparłem o zwymiarowany już poprawnie element z Thingiverse (Thumbstick Joystick Case) dostępny na licencji Creative Commons:

Link: https://www.thingiverse.com/thing:1162200
Całość w zasadzie oszczędziła mi tylko mierzenia płytki od modułu z gałką.
Początkowo chciałem zrobić mój gamepad tak, że jego prawa strona byłaby idealnym odbiciem lustrzanym lewej strony, ale niestety okazało się, że moduł z gałką nie jest symetryczny.
Uznałem, że całość będzie składała się z dwóch części - dolnej i górnej.
Zacząłem od testowych wydruków do przymiarek:

Przymiarka do płytki od PICa:

Przymiarka do gałek:

Ostatecznie przystanąłem na taki design prototypu:



Mocowanie obu połówek gamepada zaplanowałem z pomocą śrub M2:

Wykorzystać do tego można te same otwory które są od mocowania dwóch modułów gałek:

Filament nie jest gwintowany, ale dzięki jego plastyczności dobrze się w niego wkręca śrubki.
Moduły gałki niestety muszą być przylutowane kabelkami do PCB. Jest to bardzo niefortunne, ale ciężko to inaczej było zrealizować w tej wersji. W następnej wersji projektu planuję zrobić PCB pod gamepad takie, że po prostu goldpiny gałek będą wchodzić w złącza na bokach głównej płytki i całość będzie się łatwo łączyć i rozłaczać.

Kabelki lutowałem do spodu gamepada:

Zdjęcie pochodzi jeszcze z prototypu-prototypu obudowy, który nie miał wypełnionego spodu tylko dlatego, że przy testach oszczędzałem filament.
Po całym złożeniu:


W sam raz do pierwszych testów. W przyszłości zamierzam pod projekt zrobić dedykowana PCB, więc też powstanie lepsza obudowa.
Firmware - tryb UART
Pierwszy, najprostszy kod obsługi gamepada/joysticka nie posiada wcale wsparcia USB. Opracowałem go w ramach pierwszych testów tego czy sam PIC18F45K50 działa poprawnie, czy ma dobrze skonfigurowany oscylator oraz czy sam odczyt ADC i przycisków jest w porządku.
Kod napisany jest tak, że wypisuje bieżący stan gamepada na UART (pin TX PIC18F45K50):

i by ten stan odebrać, potrzebna jest przejściówka USB-UART do komputera (ja użyłem HW-597):

Wyniki tak prezentują się w RealTerm:

Całość poprawnie wykrywa częściowe wychylenie gałki oraz wciśnięcia przycisków:

Załącznik (cały projekt w MikroC dla PIC18F45K50 wraz z .hex do pobrania):
Firmware - tryb wirtualny port COM aka VCP (wymaga sterowników!)
Tryb wirtualnego portu COM korzysta już ze sprzętowego USB od PICa które znajduje się na jego pinach D+ i D- i zasadniczo nie wymaga żadnych dodatkowych komponentów do działania.
Działa podobnie jak te znane przejściówki oparte o CH340.
Ten firmware oparty jest o darmową bibliotekę VCPDemo od MikroE, pobraną stąd:
https://libstock.mikroe.com/projects/view/568/usb-device-library
Załączam jej bieżącą wersję:
Oraz wymagane przez nią sterowniki:
Sterowniki testowałem na systemie Windows 7.
Windows po podłączeniu PICa z wsadem VCP nie daje rady samodzielnie zainstalować sterowników:

Urządzenie pokazuje się z wykrzyknikiem w Menedżerze Urządzeń, nazywa się tam "VCP Demo":

Ma tam pokazany kod błędu 28 (brak sterowników):

Sterowniki oczywiście trzeba zainstalować ręcznie poprzez wskazanie systemowi ścieżki do nich:

W trakcie instalacji trzeba potwierdzić, że ufamy sterownikom od "Niezweryfikowanego wydawcy" (aka Mikroelektronika):

Po potwierdzeniu sterowniki instalują się już pomyślnie:

Urządzenie zaczyna być widoczne jako "Port COM" (już nie "VCP Demo"):

I można się z nim skomunikować poprzez RealTerm:

Poprawnie odbierane są stany gałek i przycisków gamepada:

Zauważyłem jednak, że po ponownym wgraniu wsadu (?) muszę odłączyć przewód USB od PICa do komputera i podłączyć go ponownie bo inaczej wirtualny port COM się blokuje. Podejrzewam, że to jest wina użytej biblioteki VCP. Jednak nie uważam tego za duży problem, ponieważ i tak raczej zamierzam docelowo używać czystego USB/HID.
UWAGA: To rozwiązanie z wirtualnym portem COM ma pewną dość dużą wadę.
A mianowicie nie poradzi sobie ono z takim kodem:
Code: c
Taki kod spowoduje wysyłanie śmieci, ponieważ funkcja Send_Data_To_Uart kopiuje tekst do wysłania do bufora 'buffer' o adresie 0x500 w pamięci RAM USB z PIC18F45K50, a sam kod biblioteki VCP nie sprawdza, czy nie nadpisuje czegoś co nie zostało jeszcze wysłane.
To po stronie programisty tutaj leży dopilnowanie, by nie nadpisywać niewysłanych danych.
Co ciekawe, w przypadku użycia zwykłego UART z PIC (UART_Write) nie byłoby tego problemu.
Poprawnym natomiast rozwiązaniem jest zrobienie czegoś w stylu:
Code: c
i dodanie odpowiedniego oczekiwania (delay) po wysłaniu pakietu.
Załącznik (cały projekt w MikroC dla PIC18F45K50 wraz z .hex do pobrania):
Firmware - tryb gamepada USB/HID (Plug and play)
Ten tryb działa już jak pełnoprawny, normalny gamepad/joystick. Oparty jest o biblioteki HID/USB od MikroC i używa sprzętowego USB PICa. Ten wsad nie wymaga żadnych sterowników po stronie komputera, wszystko jest Plug And Play.
Gamepad widziany jest przez komputer jako "Urządzenie wejściowe USB":

Jego identyfikatory sprzętu (USB\VID_1403&PID_0005&REV_0001) są zgodne z tym, co jest zdefiniowane w kodzie (plik USB CDC_Descriptor.c):

Gamepad z miejsca działa z różnymi programami, a nawet ze stroną HTML5 Gamepad Tester, dostępną tutaj:
https://html5gamepad.com/
Ta strona pozwala testować różne gamepady/joysticki w przeglądarce:

Po podłączeniu mojej konstrukcji od razu wykrywa nowe urządzenie:

(jeśli nie wykrywa, to warto ruszyć którąś z osi na gamepadzie lub wcisnąć przycisk by go 'obudzić')
Małym niedociągnięciem jest to, że pokazane wartości w stanie spoczynku są niezerowe, ale można to łatwo naprawić w kodzie (skalibrować odczyt wartości z ADC).
Strona GamePad Tester jest też w stanie poprawnie odczytywać stany osi:

Delikatne przesunięcie gałki gamepada skutkuje odczytaniem wartości innej niż 1.
Przyciski również są poprawnie wykrywane:

Na potrzeby tego firmware opracowałem specjalny HID Descriptor dla mojego gamepada. W dużym skrócie, standard HID pozwala opisać jakie informacje przesyła nasze urządzenie do komputera. Można tam określić, ile mamy przycisków, osi, jaki jest zakres wartości osi (też ich rozmiar w bajtach), itp.
Oto kod deskryptora HID mojego gamepada (wersja okrojona; pełna jest w załączniku):
Code: c
Powyższy deskryptor HID mówi, że PIC przesyła kolejno do USB w pakiecie cztery wartości osi (X,Y,Z, Rx - każda 8 bitów) a potem kolejne 8 bitów, z czego 2 bity używane są dla przycisków.
Oczywiście, samo to przesyłanie też musi być w kodzie i jest u mnie w funkcji main().
Załącznik (cały projekt w MikroC dla PIC18F45K50 wraz z .hex do pobrania):
Firmware - tryb myszki USB/HID (Plug and play)
Ten firmware powstał raczej w ramach ciekawostki. Jak już mamy obsługę USB/HID to równie prosto jak gamepad/joystick można zrobić myszkę. I właśnie na te potrzeby opracowałem deskryptor HID który pozwala mojemu gamepadowi udawać myszkę.
Działa oczywiście bez instalacji sterowników, tak jak każda myszka na USB.
Użyty deskryptor HID (wersja okrojona; pełna jest w załączniku):
Code: c
Powyższy deskryptor HID mówi, że PIC przesyła kolejno do USB w pakiecie jeden bajt którego trzy bity to przyciski (pozostałe nie są używane), a następnie wartość przesunięcia myszki X, Y oraz wartość scrolla (kółko myszy)..
Oczywiście, samo to przesyłanie też musi być w kodzie i jest u mnie w funkcji main().
Dzięki temu po podłączeniu mojego gamepada do komputera można z jego pomocą sterować kursorem (prawa gałka pada), scrollem (lewa gałka - tylko góra/dół) oraz klikać (prawy i lewy przycisk myszki).
Po prostu pełnoprawna myszka.
Załącznik (cały projekt w MikroC dla PIC18F45K50 wraz z .hex do pobrania):
Nowy, lepszy model 3D gamepada
Przedstawiony tu wydruk 3D w początkowym założeniu miał być tylko wersją testową. Zaprojektowałem nowy model, bardziej smukły, który prezentuje się tak:



Niestety ze względu na awarię drukarki 3D (wciąż czekam aż przyjdą części zza oceanu) nie mam jak go teraz wydrukować, więc całość jest w takiej postaci w jakiej jest.
Całkiem możliwe, że już zamiast drukować ten model to zrobię jeszcze nowszą wersję - z dodatkowymi przyciskami i lepszym PCB.
Dalszy rozwój projektu
Widzę co najmniej kilka możliwości co można by dalej w kwestii mojego gamepada zrobić. Są to m. in:
- można zaprojektować/wykonać lepszą obudowę (już było napisane)
- można zaprojektować specjalną płytkę pod projekt która łączy się z modułami gałek gamepada za pomocą dwóch złącz kątowych
- można dodać kalibrację ADC, albo ręczną albo całkiem automatyczną (po włączeniu gamepad odczytuje jakie są wartości w stanie spoczynku i wysyła ich zmianę)
- można by poprawić deskryptor USB gamepada by używał komplementarnych osi (teraz używam X, Y, Z oraz rX; to chyba przez to na GamePad Tester pokazuje mi 6 osi, a nie 4; można spróbować użyć X, Y oraz rX i rY).
Podsumowanie
Z mojego gamepada jestem zadowolony. Standard HID okazał się bardzo prosty w użyciu, a PIC18F45K50 naprawdę wymaga absolutnego minimum elementów do ogarnięcia USB (nie trzeba nawet zewnętrznego oscylatora!). W planach mam już kolejną, bardziej rozbudowaną wersję kontrolera którą wzbogacę o dodatkowe przyciski i przede wszystkim wymodeluję w bardziej przyjaznym dla użytkownika kształcie.
Finalny software/firmware projektu zasadniczo jest gotowy, a w przyszłości zamierzam pod całość zaprojektować dedykowaną płytkę i zrobić wygodniejszą, dobrze leżącą w ręce obudowę.
Cool? Ranking DIY