kk logo

Du planst einen Bingo-Abend und hast keine Lust auf klappernde Plastikkugeln oder unhandliche Lostrommeln? Dann ist dieser selbstgebaute digitale Bingo-Generator genau das Richtige für dich. Mit einem Arduino und einem großen 4-Zoll-Display bringen wir den Spieleklassiker ins digitale Zeitalter, absolut fair, perfekt lesbar und kinderleicht zu bedienen.

Spiel 66 aus der 200 Arduino Spiele Sammlung.

 

Einleitung: Warum ein digitaler Bingo-Zähler?

Bingo ist der Inbegriff von Spannung und Gemeinschaft. Doch wer kennt es nicht: Eine Kugel rollt unters Sofa oder man vergisst, welche Zahlen bereits gezogen wurden. Dieses Arduino-basiertes Bingo-System löst diese Probleme elegant. Auf einem hochauflösenden 4" TFT-Display (ILI9486) behältst du immer den Überblick über alle 75 Zahlen. Dank intelligenter Programmierung ist jede Ziehung absolut zufällig und jede Zahl kommt garantiert nur einmal vor.

Wie Bingo funktioniert: Die Klassischen Regeln

Bevor wir in die Technik eintauchen, kurz die Grundlagen des Spiels:

  • Der Zahlenraum: Klassisches Bingo wird mit den Zahlen von 1 bis 75 gespielt.
  • Die Ziehung: Ein Spielleiter zieht nacheinander zufällige Zahlen.
  • Das Ziel: Die Spieler markieren die gezogenen Zahlen auf ihren Bingo-Karten. Wer zuerst ein bestimmtes Muster (z. B. eine Reihe, eine Spalte oder ein volles Haus) hat, ruft laut "BINGO!".
  • Die Herausforderung: Es muss sichergestellt werden, dass keine Zahl doppelt gezogen wird und die Reihenfolge für alle Teilnehmer unvorhersehbar ist.

Hardware-Anschlussplan (Pin-Belegung)

Da das ILI9486 Display meistens mit 5V (VCC) betrieben wird, aber die Logik-Pins oft 3,3V erwarten, stelle sicher, ob dein Shield/Modul bereits Pegelwandler verbaut hat (die meisten 4" Shields für den Arduino Uno/Mega haben das).

Arduino Pin Display / Bauteil Pin Beschreibung
5V VCC Stromversorgung Display
GND GND Gemeinsame Masse
13 SCLK / SCK SPI Taktleitung (Clock)
11 MOSI / SDI SPI Datenleitung
10 CS Chip Select (laut Code)
9 RST / RESET Display Reset (laut Code)
8 DC / RS Data / Command (laut Code)
4 Button Pin 1 Bingo-Knopf (Eingang)
GND Button Pin 2 Zweiter Pol des Knopfes
3.3V / 5V LED / BL Hintergrundbeleuchtung

Wichtige Hinweise zum Aufbau:

  • SPI Pins: Falls du einen Arduino Mega statt eines Uno verwendest, liegen die SPI-Pins an anderen Stellen (MOSI ist 51, SCK ist 52). Die Pins 10, 9, 8 und 4 bleiben jedoch identisch, da sie im Code fest definiert sind.
  • Hintergrundbeleuchtung (BL/LED): Wenn dein Display eine separate LED-Pin-Belegung hat, verbinde diese mit 3,3V oder 5V (je nach Datenblatt), damit du auch etwas siehst. Manche Module benötigen hier einen kleinen Vorwiderstand (z. B. 100 Ohm).

2 DIY Bingo Generator Dein digitales Bingo System mit Arduino und 4 TFT

1. Der Fisher-Yates Shuffle (Echte Zufallslogik)

Dieser Teil sorgt dafür, dass die Zahlen 1 bis 75 in einer absolut zufälligen Reihenfolge erscheinen und keine Zahl doppelt vorkommt. Anstatt bei jedem Klick neu zu würfeln, "mischen" wir den Stapel einmal am Anfang komplett durch.

void mischeZahlen() {
// 1. Array mit den Zahlen 1 bis 75 füllen
for (int i = 0; i < 75; i++) zahlen[i] = i + 1;

// 2. Den Stapel "mischen" (Fisher-Yates Algorithmus)
for (int i = 74; i > 0; i--) {
int j = random(0, i + 1); // Wähle einen zufälligen Tauschpartner
int temp = zahlen[i]; // Plätze tauschen
zahlen[i] = zahlen[j];
zahlen[j] = temp;
}
}


  • Erklärung: Zuerst wird ein geordnetes Array (1, 2, 3...) erstellt. Dann geht der Code von hinten nach vorne durch und tauscht jede Zahl mit einer zufällig gewählten anderen Zahl im Array. Das Ergebnis ist eine perfekte, zufällige Kette von 75 Zahlen.

2. Dynamische Gitter-Positionierung

Damit die gezogene Zahl (z. B. die 42) immer genau in ihrem festen Kästchen im Gitter markiert wird, nutzen wir eine mathematische Umrechnung von der Zahl zur Pixel-Koordinate.

int zahl = zahlen[aktuellerIndex];
int pos = zahl - 1; // Index im Gitter (0 bis 74)
int s = pos % spalten; // Spalte berechnen (Modulo-Rechnung)
int r = pos / spalten; // Reihe berechnen (Ganzzahl-Division)

tft.setCursor(s * zellBreite + xOff, r * zellHoehe + 12);
tft.print(zahl);


  • Erklärung: Durch (Modulo) ermitteln wir, in welcher der 15 Spalten die Zahl steht. Durch wissen wir, in welcher der 5 Reihen sie hingehört. So findet das Programm blitzschnell das richtige Kästchen für jede gezogene Zahl, egal in welcher Reihenfolge sie kommt.

3. Die Zeit-basierte Button-Abfrage (Multi-Funktion)

Damit du keinen extra Reset-Knopf brauchst, unterscheidet dieser Teil zwischen einem kurzen Tippen und einem langen Festhalten des Buttons an Pin 4.

if (digitalRead(ENC_BTN) == LOW) {
unsigned long startZeit = millis(); // Zeit beim Drücken merken

while (digitalRead(ENC_BTN) == LOW) {
if (millis() - startZeit > 2000) { // Länger als 2 Sek?
neuesSpielStarten(); // RESET auslösen
while(digitalRead(ENC_BTN) == LOW); // Warten auf Loslassen
return;
}
}
zeigeNaechsteZahl(); // Wenn kurz losgelassen -> Nächste Zahl
}

  • Erklärung: Wenn der Pin auf geht, startet eine Stoppuhr (). Lässt du innerhalb von 2 Sekunden los, wird die nächste Zahl gezogen. Bleibst du drauf, erkennt das Programm nach 2000 Millisekunden den Reset-Wunsch und startet das Spiel neu.
  •  

Der gesamte Arduino Code

#include <SPI.h>
#include <ILI9486_SPI.h>

// Pins laut Vorgabe
#define TFT_CS 10
#define TFT_DC 8
#define TFT_RST 9
#define ENC_BTN 4

ILI9486_SPI tft(TFT_CS, TFT_DC, TFT_RST);

// Logik-Variablen
int zahlen[75];
int aktuellerIndex = 0;
const unsigned long RESET_ZEIT = 2000;

// Layout-Definitionen
const int spalten = 15;
const int reihen = 5;
const int zellBreite = 32;
const int zellHoehe = 40;
const int infoArea_Y = 210;

void setup() {
pinMode(ENC_BTN, INPUT_PULLUP);

tft.setSpiKludge(false);
tft.init();
tft.setRotation(3); // Querformat (480x320)

randomSeed(analogRead(0));
neuesSpielStarten();
}

void mischeZahlen() {
for (int i = 0; i < 75; i++) zahlen[i] = i + 1;
for (int i = 74; i > 0; i--) {
int j = random(0, i + 1);
int temp = zahlen[i];
zahlen[i] = zahlen[j];
zahlen[j] = temp;
}
}

void zeichneGitter() {
tft.fillScreen(0x0000);

// Gitter für 1-75 zeichnen
for (int r = 0; r < reihen; r++) {
for (int s = 0; s < spalten; s++) {
tft.drawRect(s * zellBreite, r * zellHoehe, zellBreite, zellHoehe, 0x7BEF); // Grau
}
}

// Untere Info-Fläche statische Texte
tft.drawFastHLine(0, infoArea_Y - 5, 480, 0xFFFF);
tft.setTextColor(0xFFFF);
tft.setTextSize(2);
tft.setCursor(10, infoArea_Y + 40);
tft.print("LETZTE:");

// Die feste 75 für den Counter rechts
tft.setTextSize(3);
tft.setCursor(410, infoArea_Y + 10);
tft.print("75");
tft.drawFastHLine(405, infoArea_Y + 40, 50, 0xFFFF); // Kleiner Trennstrich

aktualisiereCounter();
}

void aktualisiereCounter() {
// Bereich für den unteren Counter-Wert löschen
tft.fillRect(405, infoArea_Y + 50, 70, 40, 0x0000);
tft.setTextColor(0x07E0); // Grün für den Fortschritt
tft.setTextSize(3);
tft.setCursor(410, infoArea_Y + 50);
tft.print(aktuellerIndex);
}

void neuesSpielStarten() {
aktuellerIndex = 0;
mischeZahlen();
zeichneGitter();
}

void zeigeNaechsteZahl() {
if (aktuellerIndex < 75) {
int zahl = zahlen[aktuellerIndex];

// 1. Zahl im Gitter markieren
int pos = zahl - 1;
int s = pos % spalten;
int r = pos / spalten;

tft.setTextColor(0x07E0);
tft.setTextSize(2);
int xOff = (zahl < 10) ? 10 : 4;
tft.setCursor(s * zellBreite + xOff, r * zellHoehe + 12);
tft.print(zahl);

// 2. Große Anzeige in der Mitte
tft.fillRect(110, infoArea_Y, 280, 110, 0x0000);
tft.setTextColor(0xFFE0); // Gelb
tft.setTextSize(12);
int xPosBig = (zahl < 10) ? 190 : 140; // Zentrierung leicht anpassen
tft.setCursor(xPosBig, infoArea_Y + 10);
tft.print(zahl);

// 3. Counter erhöhen und anzeigen
aktuellerIndex++;
aktualisiereCounter();
} else {
// Alles voll
tft.fillRect(0, infoArea_Y, 480, 110, 0xF800);
tft.setTextColor(0xFFFF);
tft.setTextSize(4);
tft.setCursor(110, infoArea_Y + 35);
tft.print("BINGO VOLL!");
}
}

void loop() {
if (digitalRead(ENC_BTN) == LOW) {
unsigned long startZeit = millis();
bool istReset = false;

while (digitalRead(ENC_BTN) == LOW) {
if (millis() - startZeit > RESET_ZEIT) {
tft.fillScreen(0xF800);
delay(200);
neuesSpielStarten();
istReset = true;
while(digitalRead(ENC_BTN) == LOW);
}
}

if (!istReset && (millis() - startZeit > 50)) {
zeigeNaechsteZahl();
}
}
}

Ronnie

schwäbischer tüftler und bastler, kraftsportler, neurodivers, 45 Jahre, 1 Frau, 5 Kinder und 1003 Ideen. 

1.2 ronnie berzins

Kontakt

visitenkarte