|
Arduino als USB-Joystickinterface |
Die große Welt der kleinen Microcontroller und vorallem der sehr
günsigen Microcontroller und deren Vielfältigkeit, hat mich beim
folgenden 'Projektchen' wieder motiviert sie zu verwenden. Für die eher
weniger outdoorlastigen kalten Wintertage habe ich mir ein Projekt
vorgenommen, dass das Thema Retrocomputer betrifft. Zum einen habe
geplant, die Website um die Rubrik der alten Computer zu erweitern
(zumindest sollen die paar wenigen aus meiner Sammlung vorgestellt und
in Betrieb genommen werden...) und zum anderen will ich mir eine
Arcade-Station bauen, deren Kern das neue RaspBerry2 Modell ist . Auf
dem soll die Emulatorplatform
Retropie
aus dem gleichnamigen Projekt zu Einsatz kommen. Die ersten Versuche
mit den Images aus dem Projekt sehen sehr gut aus. Die alten 8-Bit und
16-Bit Computer laufen in der Emulation ausgezeichnet (C64, Atari, Amiga
usw...). Was die Anbindung von Eingabegeräten betrifft, kann man
natürlich Maus und Keyboard vom PC an den Raspberry anschliessen und
alles steuern. Die Jungs aus dem Projekt haben auch selbst einige Boards
entwickelt, die die Anbindung von Joysticks und co an des Raspberry
ermöglichen. (zB. den
GPIO Adapter).
Aber da ich ein paar Arduino Unos herumliegen habe, dachte ich mir,
warum nicht diese verwenden. Da es beim Arduino möglich ist, den Mega
16U2 zu flashen (der Chip wird als Programmer für den Atmega 328 auf dem
Uno - Board verwendet) und aus dem Uno-Board so zum Beispiel ein
USB-HID (Human Interface Device) zu machen -sprich Keyboard, Mouse, was
auch immer, bot sich der als ideale Platform an.
Tutorials, den Arduino zu einem HID-Interface zu flashen, gibt es mittlerweile schon sehr viele. Zum Beispiel findet man
hier eine
schöne Anleitung. Je nach dem welche Arduino-Uno Boardversion man hat,
kann man sich den zusätzlichen Widerstand fürs DFU-Flashen sparen.
(z.Bsp. bei meinen Boardversionen R3 ist der Widerstand nicht nötig.)
Auf den neuen Boards ist auch nicht mehr der Atmega 8U2 verbaut, sondern
der 16U2. Man muß einfach im Atmega Flash-Tool "
ATMEL-FLIP" den entsprechenden Chip auswählen. Die enstprechenden Firmwarefiles findet man im Netz...
Arduino-keyboard-0.3.hex
Arduino-mouse-0.1.hex
Ist
der Arduino dann geflasht, so wird er beim Anschluß an den PC eben als
Keyboard oder Maus erkannt. Jetzt braucht man nur mehr den gewünschten
Code in den Atmega328 zu schreiben und die Arduino UNO Eingänge führen
z.Bsp. Tastaturbefehle aus. Um die Firmware jetzt nicht jedes Mal
zwischen Programmer und USB-HID zu ändern, verwende ich einfach einen
zweiten UNO der als Programmer dient und stecke einfach den geflashten
Chip immer um (ist viel einfacher beim Testen).
Da das Interface jetzt soweit passt, habe ich mich mit dem
HID-Codetable beschäftigt und die entsprechenden Tasten, die die Joystickbewegungen an den PC senden sollen herausgesucht.
Hier der sehr einfache Code der momentan die alten Commodore Joystickbewegungen umsetzt:)
/* HID Joystickinterface für Arduino UNO im HID Modus Jun2015 by I.Bihlo
Die Tasten brauch i :) Taste/Hexcode/Dec-Code
KEY_LEFT_CTRL 0x01 //01
KEY_LEFT_SHIFT 0x02 //02
KEY_LEFT_ALT 0x04 //04
KEY_LEFT_GUI 0x08 //08
KEY_RIGHT_CTRL 0x10 //16
KEY_RIGHT_SHIFT 0x20 //32
KEY_RIGHT_ALT 0x40 //64
KEY_RIGHT_GUI 0x80 //128
KEY_RIGHT_ARROW 0x4F //79
KEY_LEFT_ARROW 0x50 //80
KEY_DOWN_ARROW 0x51 //81
KEY_UP_ARROW 0x52 //82
KEY_TAB 0x2B //43
KEY_ENTER 0x28 //40
KEY_SPC 0x2C //44 */
uint8_t keyNone[8] = { 0, 0, 0, 0, 0, 0, 0 };
uint8_t keyA[8] = { 0, 0, 4, 0, 0, 0, 0 }; //left
uint8_t keyD[8] = { 0, 0, 7, 0, 0, 0, 0 }; //right
uint8_t keyW[8] = { 0, 0, 26, 0, 0, 0, 0 }; //up
uint8_t keyS[8] = { 0, 0, 22, 0, 0, 0, 0 }; //down
uint8_t keySPACE[8] = { 0, 0, 44, 0, 0, 0, 0 }; //space
uint8_t keyLEFT[8] = { 0, 0, 80, 0, 0, 0, 0 }; //left
uint8_t keyRIGHT[8] = { 0, 0, 79, 0, 0, 0, 0 }; //right
uint8_t keyUP[8] = { 0, 0, 82, 0, 0, 0, 0 }; //up
uint8_t keyDOWN[8] = { 0, 0, 81, 0, 0, 0, 0 }; //down
uint8_t keyENTER[8] = { 0, 0, 40, 0, 0, 0, 0 }; //enter
// DEFINE inputs const int UPA = 12; const int DOWNA = 13; const int LEFTA = 2; const int RIGHTA = 3;
const int UPB = 4; const int DOWNB = 5; const int LEFTB = 6; const int RIGHTB = 7;
int out=0; //fürs Testen am Serial Monitor im Programmermodus
void setup() {
// Die Pins als Eingang definieren (Intern PullUP setzen - ist bei mir nötig da actice Low geschaltet wird
pinMode(UPA, INPUT_PULLUP); pinMode(DOWNA, INPUT_PULLUP); pinMode(LEFTA, INPUT_PULLUP); pinMode(RIGHTA, INPUT_PULLUP);
pinMode(A0, INPUT);
pinMode(UPB, INPUT_PULLUP); pinMode(DOWNB, INPUT_PULLUP); pinMode(LEFTB, INPUT_PULLUP); pinMode(RIGHTB, INPUT_PULLUP);
pinMode(A1, INPUT);
Serial.begin(9600);
}
void loop() {
// Joystickbewegungen abfragen und senden
// Da das Interface einen Invert-Schmitt Trigger verpasst bekommen hat, werden die Ausgänge auf active LOW abgefragt - wenn nix passiert sind alles Eingänge HIGH
if (digitalRead(UPA)==LOW) {out=120; Serial.write(keyW, 8);}
if (digitalRead(DOWNA)==LOW) {out=121; Serial.write(keyS, 8);}
if (digitalRead(LEFTA)==LOW) {out=122; Serial.write(keyA, 8);}
if (digitalRead(RIGHTA)==LOW) {out=123; Serial.write(keyD, 8);}
if (digitalRead(A0)==LOW) {out=124; Serial.write(keySPACE, 8);}
if (digitalRead(UPB)==LOW) {out=130; Serial.write(keyUP, 8);}
if (digitalRead(DOWNB)==LOW) {out=131; Serial.write(keyDOWN, 8);}
if (digitalRead(LEFTB)==LOW) {out=132; Serial.write(keyLEFT, 8);}
if (digitalRead(RIGHTB)==LOW) {out=133; Serial.write(keyRIGHT, 8);}
if (digitalRead(A1)==LOW) {out=134; Serial.write(keyENTER, 8);}
delay(20);
//Serial.println(out); //des is nur fürs debuggen im serial monitor
Serial.write(keyNone, 8); // den Tastendruck beenden
delay(20);
}
|
Lochrasterplatine am Arduino |
Als nächstes habe ich ein Interfaceboard (eine einfache
Lochrasterplatine) mit zwei 9-poligen SUB-D-Buchsen für den Anschluß der
Joysticks gebastelt. Da der Arduino genügend Ports besitzt, habe ich
auf ein Multiplexen oder Matrixverschalten der insgesamt zehn
Steuerleitungen verzichtet und jeden Joystickkontakt direkt auf einen
Port gelegt. Das funktioniert schon einmal ganz gut. Aber das Prellen
der Federkontakte und Microtaster in den Joysticks muß natürlich
softwaremäßig entfernt werden. Um jetzt nicht in jeder Softwareversion
einen debounce-code mitzuführen entschloss ich mich das Entprellen in
der Hardware zu machen. Einfach ein RC-Glied (10k - 1uF) an einen
Schmitt-Trigger und gut ist´s. Also schnell ein Board gelayoutet (das
geht schneller als am Lochrasterprint zu löten), geätzt und bestückt...
und heraus kam das Board hier:
|
Board geätzt und gebohrt |
Der Funktionstest verlief positiv. Die Bewegungen des Sticks werden sauber umgesetzt. Ein schneller Test mit
WinVice ließ sofort das Zockergefühl von vor 30 Jahren aufkommen ;)
|
fertig bestückt am Arduino |