Mit Hilfe einer Fernbedienung wird auf einem TFT-Monitor ein Ball durch ein kleines Labyrinth bewegt. Beim Druck auf die *-Taste wird die Zeitmessung gestartet.
So sieht es aus:
Benötigte Bauteile:
- Keyes Fernbedienung
- Infrarotempfänger
- Adafruit 1,8 Zoll TFT ST7735
- Leitungsdrähte
Baue die Schaltung auf:
1 -> Gnd -> GND
2 -> VCC -> 5V
3 -> RESET -> D9
4 -> D/C -> D8
5 -> CARD_CS (nicht angeschlossen)
6 -> TFT_CS -> D10
7 -> SDO -> D11
8 -> SCK -> D13
9 -> SDI (nicht angeschlossen)
10 -> LITE ->5V
Pinbelegung Adafruit 1,8 Zoll TFT ST7735
Das verwendete TFT-Modul von Adafruit hat eine Bildschirmdiagonale von 1,8 Zoll und eine Bildschirmauflösung von 160×128 Pixeln.
Achte auf die Pinbelegung der Infrarotempfänger.
Achte darauf, dass die Batterie richtig eingelegt wurde. Der Minus-Pol liegt oben.
Die Fernbedienung sendet beim Druck auf die Tasten einen Zahlencode.
Tastencodes Keyes-Fernbedienung
Pfeil oben | |||
Tastencode | 70 | ||
Pfeil links | Taste OK | Pfeil rechts | |
Tastencode | 68 | 64 | 67 |
Pfeil unten | |||
Tastencode | 21 | ||
Taste 1 | Taste 22 | Taste 3 | |
Tastencode | 22 | 25 | 13 |
Taste 4 | Taste 5 | Taste 6 | |
Tastencode | 12 | 24 | 94 |
Taste 7 | Taste 8 | Taste 9 | |
Tastencode | 8 | 28 | 90 |
Taste * | Taste 0 | Taste # | |
Tastencode | 66 | 82 | 74 |
⇒Tastencodes OpenSmart Fernbedienung
⇒Testprogramm beliebige Fernbedienung
Benötigte Bibliotheken:
Die Tastencodes kannst du mit folgendem Programm herausfinden. Sie werden im Seriellen Monitor angezeigt.
// benötigte Bibliothek einbinden
#include "IRremote.h"
// der Pin, an dem der Infrarot-Empfänger angeschlossen ist
int EmpfaengerPin = 11;
void setup()
{
// Seriellen Monitor starten
Serial.begin(9600);
// Infrarot-Empfänger starten
IrReceiver.begin(EmpfaengerPin);
}
void loop()
{
// decode() -> Daten lesen
if (IrReceiver.decode())
{
// kurzes delay, damit nur ein Tastendruck gelesen wird
delay(200);
// resume -> nächsten Wert lesen
IrReceiver.resume();
/*
der Empfänger empfängt zwischendurch Signale,
die nicht ausgewertet werden können
es sollen dehalb nur die korrekt erkannten Tasten ausgewertet werden
die Dezimalwerte der korrekten erkannten Tasten liegen zwischen > 0 und < 95
es wird abgefragt, ob das empfangene Kommando decodedIRData.command
zwischen 0 und (&&) 95 liegt
*/
if (IrReceiver.decodedIRData.command > 0 && IrReceiver.decodedIRData.command < 95)
{
Serial.print("Dezimalwert: ");
// IrReceiver.decodedIRData.command = Wert der gedrückten Taste
Serial.print(IrReceiver.decodedIRData.command);
Serial.print(" -> ");
// Werte abfragen und anzeigen
if (IrReceiver.decodedIRData.command == 22) Serial.println("Taste 1");
if (IrReceiver.decodedIRData.command == 25) Serial.println("Taste 2");
if (IrReceiver.decodedIRData.command == 13) Serial.println("Taste 3");
if (IrReceiver.decodedIRData.command == 12) Serial.println("Taste 4");
if (IrReceiver.decodedIRData.command == 24) Serial.println("Taste 5");
if (IrReceiver.decodedIRData.command == 94) Serial.println("Taste 6");
if (IrReceiver.decodedIRData.command == 8) Serial.println("Taste 7");
if (IrReceiver.decodedIRData.command == 28) Serial.println("Taste 8");
if (IrReceiver.decodedIRData.command == 90) Serial.println("Taste 9");
if (IrReceiver.decodedIRData.command == 82) Serial.println("Taste 0");
if (IrReceiver.decodedIRData.command == 66) Serial.println("Taste *");
if (IrReceiver.decodedIRData.command == 74) Serial.println("Taste #");
if (IrReceiver.decodedIRData.command == 68) Serial.println("Pfeil links");
if (IrReceiver.decodedIRData.command == 67) Serial.println("Pfeil rechts");
if (IrReceiver.decodedIRData.command == 70) Serial.println("Pfeil oben");
if (IrReceiver.decodedIRData.command == 21) Serial.println("Pfeil unten");
if (IrReceiver.decodedIRData.command == 64) Serial.println("OK");
}
}
}
Funktionen der Bibliothek Adafruit ST7735
Schlüsselwort | Parameter | Aktion |
---|---|---|
width(); | Bildschirmbreite feststellen | |
height(); | Bildschirmhöhe feststellen | |
begin() | TFT starten | |
initR(initR(INITR_*TAB);); | BLACKTAB GREENTAB REDTAB | Farbschema bestimmen |
setRotation(Richtung); | Richtung = 0 → nicht drehen Richtung = 1 → 90° drehen Richtung = 2 → 180° drehen Richtung = 3 → 270 ° drehen | Bildschirm ausrichten |
fillScreen(Farbe); | Standardfarben: ST7735_BLACK ST7735_WHITE ST7735_GREEN ST7735_RED ST7735_BLUE ST7735_YELLOW ST7735_ORANGE ST7735_MAGENTA ST7735_CYAN | Bildschirmhintergrund |
drawLine(StartX, StartY, EndeX, EndeY, Farbe); | Linie zeichnen | |
drawFastHLine(StartX, StartY, Länge, Farbe); | horizontale Linie zeichnen | |
drawFastVLine(StartX, StartY, Länge, Farbe); | vertikale Linie zeichnen | |
drawRect(StartX, StartY,, Breite, Höhe, Farbe); | Rechteck zeichnen | |
drawRoundRect(StartX, StartY, Breite, Höhe, Eckenradius, Farbe); | abgerundetes Rechteck zeichnen | |
fillRect(StartX, StartY, Breite, Höhe, Füllfarbe); | ausgefülltes Rechteck zeichnen | |
drawCircle(MittelpunkX, MittelpunktY, Radius, Farbe); | Kreis zeichnen | |
fillCircle(MittelpunktX, MittelpunktY, Radius, Füllfarbe); | Ausgefüllten Kreis zeichnen | |
setCursor(x, y); | Cursor setzen | |
setTextSize(Textgröße); | Textgröße: 1 - 4 | Textgröße bestimmen |
setTextColor(Farbe); | Textfarbe setzen | |
print("Text"); println("Text"); | Text schreiben | |
setTextWrap(true/false); | false → Text fließt über den Rand des TFTs hinaus true → Text wird am Ende umgebrochen | Zeilenumbruch |
⇒Beispiel mit Grafik und Text
So sieht es aus:
Adressierung der Bildpunkte
Binde die benötigen Bibliotheken ein und definiere die Variablen. Beachte die Kommentare.
/*
Pinbelegung:
GND (1) - GND
VCC (2) - 5V
RESET (3) - D9
D/C (4) - D8
CARD-CS (5) -
TFT-CS (6) - D10
SDO (7) - D11
SCK (8) - D13
SDI (9) -
LITE (10) - 5V
*/
#include "IRremote.h"
int EmpfaengerPin = 6;
#include "Adafruit_GFX.h"
#include "Adafruit_ST7735.h"
#include "SPI.h"
// Pins definieren
#define TFT_CS 10
#define TFT_RST 9
#define TFT_DC 8
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);
/*
Farben als hexadezimal definiert
alternativ:
int SCHWARZ = 0;
int BLAU = 15;
. . .
*/
// Farben
#define SCHWARZ 0x0000 // dezimal 0
#define BLAU 0x000F // dezimal 15
#define ROT 0xF800 // dezimal 406664
#define GRUEN 0x0E81 // dezimal 3713
#define CYAN 0x07FF // dezimal 2047
#define MAGENTA 0xF81F // dezimal 63519
#define GELB 0xAFE5 // dezimal 65504
#define WEISS 0xFFFF // dezimal 65535
#define BRAUN 0xFC00 // dezimal 64512
#define GRAU 0xF7F0 // dezimal 63472
#define GRUENGELB 0xAFE5 // dezimal 45029
#define DUNKELCYAN 0x03EF // dezimal 1007
#define ORANGE 0xFD20 // dezimal 64800
#define PINK 0xFC18 // dezimal 64536
// Farbe der Blöcke
#define FARBE GRUEN
// Farbe des Kreises
#define KREISFARBE GELB
// Farbe der Schrift
#define SCHRIFTFARBE WEISS
// Spiel starten wenn * gedrückt wurde
bool SpielStart = false;
// Radius des kreises
const int Radius = 10;
// Abstand zu den Rändern
const int Abstand = Radius * 2;
// je höher, dest langsamer
const int Geschwindigkeit = 100;
// Bewegung des Kreises in Pixeln
const int Bewegung = 5;
// Startposition des Kreises
int CursorX = Radius;
int CursorY = tft.height() / 2 - Abstand;
// Variable für die Zeitmessung
long Start;
Der setup-Teil:
void setup()
{
// Startbildschirm
// schwarzes Farbschema vertkale Ausrichtung (nicht drehen)
// Cursor setzen, Schriftgröße und -farbe definieren
tft.initR(INITR_BLACKTAB);
tft.setRotation(0);
tft.fillScreen(SCHWARZ);
tft.setTextSize(2);
tft.setCursor(1, 10);
tft.setTextColor(ROT);
tft.println("Start:");
tft.print("-> *");
IrReceiver.begin(EmpfaengerPin);
}
Der loop-Teil. Beachte die Kommentare.
void loop()
{
if (IrReceiver.decode())
{
delay(100);
// nächsten Wert lesen
IrReceiver.resume();
// Start mit *
if (IrReceiver.decodedIRData.command == 0x42)
{
// Spiel wird gestartet
SpielStart = true;
// Parcours bauen
ParcoursBauen();
// Zeitmessung starten
Start = millis();
}
}
// wenn der Button * gedrückt wurde
if (SpielStart)
{
// Taste OK
if (IrReceiver.decodedIRData.command == 0x40)
{
// Kreis an der aktuellen Position anhalten
tft.fillCircle(CursorX, CursorY, Radius, KREISFARBE);
}
// Taste nach oben
if (IrReceiver.decodedIRData.command == 0x46)
{
// Kreis an der aktuellen Position "löschen"
tft.fillCircle(CursorX, CursorY, Radius, SCHWARZ);
// wenn der Bildschirmrand oben noch nicht erreicht wurde
// rückwärts -> Richtung x = 1 bewegen
if (CursorY > Radius) CursorY -= Bewegung;
// Kreis an der neuen Position zeichnen
tft.fillCircle(CursorX, CursorY, Radius, KREISFARBE);
delay(Geschwindigkeit);
}
// Taste nach unten
if (IrReceiver.decodedIRData.command == 0x15)
{
// Kreis an der aktuellen Position "löschen"
tft.fillCircle(CursorX, CursorY, Radius, SCHWARZ);
// wenn der Bildschirmrand rechts noch nicht erreicht wurde
// vorwärts -> Richtung tft.height() bewegen
if (CursorY < tft.height() - Radius) CursorY += Bewegung;
// Kreis an der neuen Position zeichnen
tft.fillCircle(CursorX, CursorY, Radius, KREISFARBE);
delay(Geschwindigkeit);
}
// Taste nach links
if (IrReceiver.decodedIRData.command == 0x44)
{
// Kreis an der aktuellen Position "löschen"
tft.fillCircle(CursorX, CursorY, Radius, SCHWARZ);
// wenn der Bildschirmrand links noch nicht erreicht wurde
// rückwärts -> Richtung linken Bildschirmrand bewegen
if (CursorX > Radius) CursorX -= Bewegung;
// Kreis an der neuen Position zeichnen
tft.fillCircle(CursorX, CursorY, Radius, KREISFARBE);
delay(Geschwindigkeit);
}
// Taste nach rechts
if (IrReceiver.decodedIRData.command == 0x43)
{
// Kreis an der aktuellen Position "löschen"
tft.fillCircle(CursorX, CursorY, Radius, SCHWARZ);
// Abfrage, ob der rechte Rand erreicht wurde, nicht nötig
// wird in der nächsten bedingung abgefragt
CursorX += Bewegung;
// Kreis an der neuen Position zeichnen
tft.fillCircle(CursorX, CursorY, Radius, KREISFARBE);
delay(Geschwindigkeit);
}
// rechter Bildschirmrand erreicht -> Spielende
if (CursorX > tft.height() - Radius)
{
ErgebnisZeigen();
}
}
}
Jetzt fehlen noch die ⇒Funktionen ErgebnisZeigen() und ParcoursBauen():
void ErgebnisZeigen()
{
// Zeit berechnen
int Sekunden;
long VerstricheneZeit = millis() - Start;
Sekunden = int(VerstricheneZeit / 1000);
// Zeit anzeigen
tft.fillScreen(SCHWARZ);
tft.setTextSize(2);
tft.setCursor(1, 10);
tft.println("Zeit:");
tft.println(String(Sekunden) + " s");
tft.setCursor(1, 40);
tft.setTextColor(ROT);
tft.println();
tft.println("Neustart:");
tft.println("-> *");
SpielStart = false;
}
void ParcoursBauen()
{
CursorX = Radius;
CursorY = tft.height() / 2 - Abstand;
tft.fillScreen(SCHWARZ);
// Kreis anzeigen
tft.fillCircle(CursorX, CursorY, Radius, KREISFARBE);
// Parcours "bauen"
tft.fillRect(65, 35, 5, 45, FARBE);
tft.fillRect(1, 1, 35, 35, FARBE);
tft.fillRect(1, 80, 70, 80, FARBE);
tft.fillRect(110, 1, 70, 95, FARBE);
tft.fillRect(110, 130, 140, 160, FARBE);
}
Verwandte Anleitungen:
- Automatische Tür mit Hall-Sensoren
- Countdown mit einer einstelligen 7-Segment-Anzeige
- Countdown mit einem OLED-Display
- Datum und Zeit mit dem NTP-Protokoll anzeigen
- ESP32-Wroom – BMP280/DHT Zeit und Messdaten auf TFT anzeigen
- Farbenspiele mit einer RGB-Matrix
- Glücksrad mit NeoPixel-Ring
- Labyrinthspiel mit Joystick und TFT
- Länder-Info
- LED-Matrix - Countdown
- LED-Matrix - Joystick-Spiel
- LED-Matrix - Lauflicht
- LED-Matrix Würfeln
- Lottozahlen - Anzeige auf einem LCD
- Lottozahlen - Anzeige auf einem OLED-Display
- Multiplikations-Taschenrechner
- Spiel mit einer RGB-Matrix
- Spielautomat mit einer RGB-Matrix
- Taschenrechner Grundrechenarten
- Würfeln einstellige 7-Segment-Anzeige und Fernbedienung
- Würfeln - Anzeige auf einem OLED-Display
- Würfelspiel mit einer vierstelligen Anzeige
- Würfeln mit einer einstelligen Anzeige
Letzte Aktualisierung: