Portable Spielekonsole mit Joystick-Shield und Nokia 5110 Display
Bei meiner Suche nach Sensoren für den Arduino bin ich auch über dieses Joystick Shield gestolpert. Die Idee dazu stammt wohl von Funduino, die das Original entwickelt haben.Mir kam schon öfters die Idee mit dem Arduino eine kleine, portable Spielekonsole zu realisieren und dieses Shield sah wie gemacht dafür aus. Der Joystick ist fest auf die Platine aufgelötet und mit 4 großen und zwei kleinen Knöpfe (plus den einen Knopf unter dem Joystick) waren auch reichlich Eingabetasten vorhanden.
Bei dem Preis habe ich mir natürlich gedacht: "Dafür kannst du nichts falsch machen!" und es bestellt.
Das Spiel muss natürlich auch irgendwo dargestellt werden, sprich: ich brauche ein Display. Da fiel die Wahl leicht. Denn auf das Display schien es, kann man oben links einfach ein Nokia 5110 Display stecken. Das war auch nicht teuer und wurde gleich mitbestellt.
Der Kosten wegen habe ich die Teile direkt in Südost-Asien bestellt. Ich wusste schon: jetzt brauche ich nur noch ein wenig Geduld, bis die Teile ankommen. Mittlerweile sind ein paar Wochen vergangen und es ist endlich angekommen.
Das erste was mir auffiel, war die aufgedruckte Bezeichnung: "JoySTlck Shleld V1.A" heißt es da. Ich frage mich dann immer, ob es für Chinesen genau so schwierig ist, lateinische Zeichen zu erkennen und wiederzugeben wie für uns Europäer chinesische.
Nach dem kleinen Lacher wurde der Rest der Platine inspiziert. Ich scheine Glück gehabt zu haben, denn die Bauteile waren alle vernünftig und gerade einglötet. Ich habe Videos gesehen von Leuten, die hatten da ein wenig Pech und bei denen waren die Taster und andere Komponenten schief eingelötet. Das dann alles wieder gerade umzulöten macht echt keinen Spaß. Dann lieber gleich einen Bausatz und alles selbst einlöten.
Das Shield passte gleich perfekt auf meinen Arduino Uno. Ja, das Sandwich machte sogar einen recht stabilen Eindruck und lag ziemlich gut in der Hand von der Höhe und Breite. Natürlich war es immer noch ein bisschen kantig. Zudem muss man aufpassen, wo man seine Finger lässt, damit man nicht die Widerstandswerte verfälscht oder einen Kurzschluss verursacht. Dem woltle ich begegnen, indem ich entsprechenden Gehäuse für den Handheld mit meinem 3D-Drucker designen und ausdrucken wollte.
Das Display sollte folgende Eigenschaften haben (Vorsicht: "chinglish")
Use a 3.3V controller, otherwise the display could be quite vague.
Power supply voltage: 2.7V-3.3V, 5V is OK,but part of the screen becomes black when tested
Data interface level: 2.7-5V
Backlight power supply voltage:highest 3.3V
Installation diameter: 2mm
Backlight: White
Pin-Layout:
1.RST----------- reset
2.CE------------ chip selection
3.DC------------ data/commands choice
4.DIN----------- serial data line
5.CLK----------- serial Clock Speed
6.3.3V---------- VCC
7.LIGHT--------- backlight control terminal (linked with GND, the backlight to be lit)
8.GND----------- power negative
Features:
- 84 X 48 dot matrix LCD
- Transfer rate up to 4Mbps
- Low power supply, the working current in normal situation is lower than 200µA
- Controller Philp PCD8544 LCD controller .
- input voltage :2.7-3.3v
- can be driverd by Arduino/STM32/8051/AVR/PIC and other low power controllers
- Compatible with Nokia 3310 LCD driving source code
Was ich der Produktbeschreibung entnehmen konnte, war, dass das Modul besser mit 3.3 Volt betrieben wird, denn es würde wohl zu komischen Effekten bei 5 Volt kommen.Erfreulicherweise werden die entsprechenden 3.3 Volt gleich am Header bereitgestellt.
Doch was ist das? Beim Blick auf die Rückseite des Display-Moduls sehe ich, dass die Belegung auf dem Modul eine ganz andere ist, als die, die an dem Joystick-Shield herausgeführt wird. Einfach Header ins Modul löten und dann anstecken wird nicht funktionieren.
Aus einem Youtube-Video eines anderen Makers ersehe ich, wie das originale Nokia 5110 Modul beschaltet ist:
Da hilft alles nichts, da muss ich wohl einen kleinen Umbelegungsplan kreieren...
... und eine kleine Adapterplatine löten.:
Auf die Rückseite löte ich an die entsprechende Stelle gleich einen Zweier-Header als Jumper ein, um die Hintergrundbeleuchtung damit ein- oder auszuschalten. Später ersetze ich das dann doch durch einen Schiebeschalter, weil mir auffällt, dass die Ablesbarkeit bei genügend Licht ohne Hintergrundbeleuchtung besser ist. Es besteht also der Bedarf, hier öfter mal umzuschalten.
Als nächstes designe ich ein Gehäuse für das Platinen-Duo aus Arduino und Joystick-Shield mit abgerundeten Ecken, damit es sich besser halten lässt:
Es folgen eine Frontplatte, durch die Joystick und Knöpfe genau passen plus zwei kleine Knöpfe, die unten auf den Shield-Knöpfen ruhen und nach oben durch Löcher geführt sind, um sie leichter bedienen zu können.
Außerdem entwerfe und drucke ich noch ein Gehäuse für das Display, damit man die wüste Verdrahtung nicht mehr sehen muss und dass dem Display ein wenig mehr Halt an dem Gehäuse gibt. Fertig ist der Gamuino.
Zur Zeit habe ich nur ein kleines Programm laufen, dass die Joystick-Position und die Knöpfe auswertet und den Status auf dem Display ausgibt. Als nächstes ist ein simpleres Spiel angedacht, um ein Gefühl für die Fähigkeiten des Arduino als Gaming-Handheld zu bekommen. Schließlich sind hier Ausführungsgeschwindigkeit und Speicher sehr begrenzt.
Den Zusammenbau und den ersten Test des Gamuino zeigt das folgende Video:
Software
Zur Ansprache des 5510-Moduls via SPI gibt es schon fertige Libraries. Ich habe mich für die von Adafruit entschieden, weil es mit denen eigentlich immer auf Anhieb geklappt hat und ich den Eindruck hatte, dass die APIs durchdacht sind.Über den Bibliotheksverwalter in der Arduino IDE sind zu installieren:
- Adafruit GFX Library by Adafruit Version 1.4.9
- Adafruit PCD8544 Nokia 5110 LCD library by Adafruit Version 1.0.0
Source-Code
////////////////////////////////////////////////////////
// (C) 2019 by Oliver Kuhlemann //
// Bei Verwendung freue ich mich über Namensnennung, //
// Quellenangabe und Verlinkung //
// Quelle: http://cool-web.de/arduino/ //
////////////////////////////////////////////////////////
#include <SPI.h> // SPI Interface für Display
#include <Adafruit_GFX.h> // Grafik-Library
#include <Adafruit_PCD8544.h> // für das Nokia 5110 Display
// welcher Button hängt an welchem Pin?
#define btnA 2
#define btnB 3
#define btnC 4
#define btnD 5
#define btnE 6
#define btnF 7
#define btnK 8
#define joyX 0
#define joyY 1
#define ButtonForDirection true // auf true setzen, damit die Buttons zur Richtungssteuerung benutzt werden
// Schalter auf 5V
#define center 512 // Wert Joystick Zentrum
#define centerrange 200 // wie groß ist der Mittelbereich, in dem eine Joystick-Bewegung noch nicht gewertet wird?
//Schalter auf 3V3
// #define center 343 // Wert Joystick Zentrum
// #define centerrange 150 // wie groß ist der Mittelbereich, in dem eine Joystick-Bewegung noch nicht gewertet wird?
boolean ba=false; // Zustandsspeicher Buttons
boolean bb=false;
boolean bc=false;
boolean bd=false;
boolean be=false;
boolean bf=false;
boolean bk=false;
int jx=512; // Zustandsspeicher Joystickposition
int jy=512;
boolean dl=false; // Zustandsspeicher Joystick-Direction digital (left, right, up, down)
boolean dr=false;
boolean du=false;
boolean dd=false;
Adafruit_PCD8544 display = Adafruit_PCD8544(9, 10, 11, 13, 12); // Pins für SCLK, DIN, D/C, CS, RST
void setup() {
pinMode (btnA, INPUT_PULLUP);
pinMode (btnB, INPUT_PULLUP);
pinMode (btnC, INPUT_PULLUP);
pinMode (btnD, INPUT_PULLUP);
pinMode (btnE, INPUT_PULLUP);
pinMode (btnF, INPUT_PULLUP);
pinMode (btnK, INPUT_PULLUP);
pinMode (joyX, INPUT);
pinMode (joyY, INPUT);
Serial.begin (115200);
display.begin();
display.setContrast(60);
display.clearDisplay();
}
void loop() {
display.setTextSize(1);
display.setTextColor(BLACK);
while (1) {
display.clearDisplay();
display.setCursor(0,0);
display.println ("Joystick Test\n");
// Zustände einlesen und in Variablen speichern
ba=!digitalRead(btnA);
bb=!digitalRead(btnB);
bc=!digitalRead(btnC);
bd=!digitalRead(btnD);
be=!digitalRead(btnE);
bf=!digitalRead(btnF);
bk=!digitalRead(btnK);
jx=analogRead(joyX);
jy=analogRead(joyY);
dl = (jx < center - centerrange);
dr = (jx > center + centerrange);
du = (jy > center + centerrange);
dd = (jy < center - centerrange);
if (ButtonForDirection) {
if (!dl) dl=bd;
if (!dr) dr=bb;
if (!du) du=ba;
if (!dd) dd=bc;
}
display.print ("X:");
display.print (jx);
display.print (" Y:");
display.println (jy);
display.print ("Btns: ");
if (ba) display.print ("A");
if (bb) display.print ("B");
if (bc) display.print ("C");
if (bd) display.print ("D");
if (be) display.print ("E");
if (bf) display.print ("F");
if (bk) display.print ("K");
display.println();
display.print ("Dir.: ");
if (dl) display.print ("left ");
if (dr) display.print ("right ");
if (du) display.print ("up ");
if (dd) display.print ("down ");
display.println();
display.display();
delay(30);
}
}