Skip to content

Technik Blog

Programmieren | Arduino | ESP32 | MicroPython | Python | Raspberry Pi | Raspberry Pi Pico

Menu
  • Smarthome
  • Gartenautomation
  • Mikrocontroller
    • Arduino
    • ESP32 & Co.
    • Calliope Mini
    • Raspberry Pi & Pico
  • Solo Mining
  • Deutsch
  • English
Menu

Glücksspiel im Mini-Format: Slotmaschine mit Arduino & OLED bauen

Veröffentlicht am 7. September 20254. September 2025 von Stefan Draeger

In diesem Beitrag zeige ich dir, wie du mit wenig Hardware eine kleine Arduino Slotmaschine programmierst, die auf einem 1,3″ OLED-Display läuft. Gesteuert wird das Ganze per Tastendruck: drei Symbole rotieren unabhängig voneinander und bleiben nach kurzer Zeit stehen – fast wie bei einer echten Slotmaschine.

Glücksspiel im Mini-Format: Slotmaschine mit Arduino & OLED bauen
Dieses Video auf YouTube ansehen.

Als Mikrocontroller verwende ich hier den neuen Arduino Nano R4, da er bei mir ohnehin im Einsatz ist. Du kannst das Projekt aber genauso gut mit jedem anderen Arduino Nano umsetzen – egal ob Nano V3, Nano IoT, einem ESP32 im Nano-Format oder einem vergleichbaren Board.

Das Projekt ist einfach nachzubauen, macht Spaß und eignet sich perfekt, um erste Erfahrungen mit Displaysteuerung und kleinen Animationen auf dem Arduino zu sammeln.

Arduino Slotmachine - Mini-Spiel am OLED Display 003
Arduino Slotmachine - Mini-Spiel am OLED Display 001
Arduino Slotmachine - Mini-Spiel am OLED Display 002

🔔 Hinweis: Dieses Projekt zeigt eine kleine Slotmaschine auf dem Arduino – ganz ohne Einsatz von Geld, nur zum Spaß und Lernen.
Glücksspiel ist keine gute Sache und birgt ernsthafte Risiken.
Wenn du von Glücksspielsucht betroffen bist oder dir Sorgen machst, findest du unter der kostenfreien Hotline des Bundesinstituts für öffentliche Gesundheit Unterstützung: 📞 0800 – 137 27 00

Inhaltsverzeichnis

  • Benötigte Bauteile
  • Aufbau der Schaltung auf einem Breadboard
    • Verdrahtung
    • Hinweis
  • Symbole für die Slotmachine
  • Programmieren einer Slotmachine am Arduino
    • Bibliothek installieren
    • Bibliothek einbinden
  • Snipets aus dem Code
    • Taster per Interrupt
    • Zeichnen der Walzen
    • Zufallszahl für Symbole
    • Quellcode

Benötigte Bauteile

Für den Nachbau der kleinen Arduino-Slotmaschine brauchst du nur wenige Standardkomponenten:

  • Mikrocontroller: z. B. Arduino Nano R4* (funktioniert aber auch mit Nano V3*, Nano IoT* etc.)
  • OLED Display 1,3″* (I²C-Anschluss)
  • Breadboardkabel / Jumperkabel*, männlich-männlich, 10 cm – 4 Stück in den Farben rot, schwarz, gelb, grün (für die Display-Verbindung)
  • Taster* (z. B. Printmontage 6×6 mm oder 12×12 mm)
  • Breadboardkabel / Jumperkabel*, männlich-männlich – 2 Stück in schwarz und blau (für den Taster)

Hinweis für Arduino Nano R4 Nutzer: Wenn du – wie ich – den Arduino Nano R4 verwenden möchtest, benötigst du zusätzlich zwei 4,7 kΩ Widerstände.
Diese dienen als I²C Pull-Ups und verbinden die Leitungen SDA und SCL mit VCC, damit die Kommunikation mit dem OLED-Display zuverlässig funktioniert. (siehe NEU! Arduino Nano R4: Der I2C-Fix, den dir keiner sagt (Pull-Ups!))

Hinweis von mir: Die mit einem Sternchen (*) markierten Links sind Affiliate-Links. Wenn du über diese Links einkaufst, erhalte ich eine kleine Provision, die dazu beiträgt, diesen Blog zu unterstützen. Der Preis für dich bleibt dabei unverändert. Vielen Dank für deine Unterstützung!

👉 Ich baue die Schaltung zunächst auf dem Breadboard auf. Sobald alles funktioniert, nutze ich das FlexCase von makers-gonna-make.de, für das ich mir ein eigenes Plate entworfen habe, auf dem sowohl das Display als auch der Taster Platz finden.

Arduino Slotmachine im FlexCase von makersgonnamake
Arduino Slotmachine im FlexCase von makersgonnamake

Aufbau der Schaltung auf einem Breadboard

Für den ersten Testaufbau wird die Slotmachine-Schaltung ganz einfach auf einem Breadboard realisiert. So kannst du schnell prüfen, ob Display, Taster und Buzzer wie gewünscht funktionieren, bevor du später vielleicht ein Gehäuse oder ein FlexCase verwendest.

Schaltung - Arduino Nano R4 mit OLED-Display - Taster und Piezo Buzzer
Schaltung – Arduino Nano R4 mit OLED-Display – Taster und Piezo Buzzer

Verdrahtung

  • OLED-Display (SH1106, I²C)
    • VCC → 5V am Arduino Nano R4
    • GND → GND
    • SDA → A4 (I²C-Datenleitung)
    • SCL → A5 (I²C-Taktleitung)
    • Pull-Up-Widerstände (nur beim Nano R4 nötig)
      • 4,7 kΩ von SDA nach VCC
      • 4,7 kΩ von SCL nach VCC
  • Taster
    • ein Pin → D2 am Arduino (mit INPUT_PULLUP im Code)
    • anderer Pin → GND
  • Buzzer
    • ein Pin → D3 am Arduino
    • anderer Pin → GND

Hinweis

Der Taster wird hier gegen GND geschaltet und im Sketch mit INPUT_PULLUP konfiguriert. Dadurch sparst du dir einen externen Widerstand.

Symbole für die Slotmachine

Für unsere Slotmachine benötigen wir Icons – jeweils ein 🍀 Kleeblatt, ein ❤️ Herz, 🍒 Kirschen und eine Sieben.
Diese Symbole werden als XBM-Bitmaps im Arduino-Sketch eingebunden und anschließend mit drawXBitmap() auf dem OLED-Display dargestellt.

Natürlich kannst du auch eigene Icons erstellen und verwenden – deiner Kreativität sind keine Grenzen gesetzt.
Wie du ein beliebiges PNG-Bild in das XBM-Format umwandelst, habe ich hier Schritt für Schritt erklärt:
👉 XBM Bitmaps für Arduino Displays: So geht’s Schritt für Schritt

XBM Bitmaps für Arduino Displays: So geht’s Schritt für Schritt
Dieses Video auf YouTube ansehen.

Programmieren einer Slotmachine am Arduino

Bevor wir mit der eigentlichen Slotmachine beginnen können, müssen wir zunächst das OLED-Display ansteuern. Dafür benötigen wir die passende Bibliothek.

Bibliothek installieren

Da ich ein 1,3″ OLED-Display mit SH1106G-Treiberchip verwende, nutze ich die Adafruit SH110X Library. Diese installierst du bequem über den Bibliotheksverwalter der Arduino IDE:

  1. links im Menü den Eintrag „Bibliotheksverwalter“ auswählen (drittes Icon von oben)
  2. Nach „Adafruit SH110X“ suchen
  3. Bibliothek installieren (die Adafruit GFX Library wird automatisch als Abhängigkeit mitinstalliert)
Bibliothek - Adafruit SH110X in der Arduino IDE
Bibliothek – Adafruit SH110X in der Arduino IDE
Bibliothek - Adafruit GFX in der Arduino IDE
Bibliothek – Adafruit GFX in der Arduino IDE

Solltest du jedoch ein OLED-Display mit SSD1306 Chip haben, so musst du nach Adafruit SSD1306 suchen.

Bibliothek einbinden

Nachdem die beiden Bibliotheken installiert wurden, können diese wiefolgt eingebunden und verwendet werden:

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SH110X.h>

#define i2c_Address 0x3c
Adafruit_SH1106G display = Adafruit_SH1106G(128, 64, &Wire, -1);

Damit ist dein Projekt vorbereitet, um Grafiken, Text und später auch die Slot-Symbole auf dem OLED-Display darzustellen.

Snipets aus dem Code

Nachfolgend möchte ich dir einige besondere Code-Snippets erläutern.
Im Grunde ist der Aufbau und Ablauf der Slotmachine recht einfach, dennoch gibt es ein paar spannende Stellen, die man sich genauer ansehen sollte.

Taster per Interrupt

Der Taster ist am Interrupt-Pin D2 angeschlossen.
Das ermöglicht, die Eingabe sofort zu registrieren – unabhängig davon, was im loop() gerade passiert.
So bleibt die Slotmachine reaktionsschnell und du musst den Taster nicht ständig in der Schleife abfragen.

// Pin für den Taster (gegen GND, wir nutzen INPUT_PULLUP)
#define taster 2

void setup(){
  ...
  // Interrupt auf den Taster legen:
  // CHANGE = löst bei Flanke (HIGH->LOW und LOW->HIGH) aus.
  // Wir schützen uns gegen Doppeltrigger mit TIME_BETWEEN_PRESS.
  attachInterrupt(digitalPinToInterrupt(taster), stoppSlotMachine, CHANGE);
}

// ISR (Interrupt Service Routine) für den Taster.
// Achtung: ISR sollte kurz sein – hier nur Status erhöhen
// und eine einfache Sperrzeit gegen Prellen/Mehrfachtrigger prüfen.
void stoppSlotMachine() {
  long currentMillis = millis();
  if (currentMillis > (lastButtonPress + TIME_BETWEEN_PRESS) && !endGame) {
    currentIndex++;               // nächste Walze wird „fixiert“
    lastButtonPress = currentMillis;
  }
}

Zeichnen der Walzen

Die drei Walzen (Slots) werden in einer eigenen Funktion gezeichnet.
Der Funktion wird die jeweilige Position (0, 1 oder 2) und der Index des Bildes aus dem Array epd_bitmap_allArray übergeben.
So kannst du an einer Stelle zentral steuern, welches Symbol wo auf dem Display landet.

// Pointer-Array auf alle Symbol-Bitmaps (in PROGMEM abgelegt)
// Reihenfolge: 0=Kleeblatt, 1=Herz, 2=Kirschen, 3=Sieben
const unsigned char* const epd_bitmap_allArray[] PROGMEM = {
  epd_bitmap_kleeblatt,
  epd_bitmap_herz,
  epd_bitmap_kirschen,
  epd_bitmap_seven
};

// Zeichnet einen Symbol-Rahmen + Bitmap an Position 0/1/2.
// 'bild' ist der Index im epd_bitmap_allArray (0..3)
void zeichneXBmp(int position, int bild) {
  // Layout-Offsets (Rahmen und Bild leicht eingerückt)
  int xOffsetRahmen = 4;
  int yOffsetRahmen = 20;
  int xOffsetBild   = 4;
  int yOffsetBild   = 22;

  // X-Positionen: drei Spalten im Abstand von 38 Pixeln
  int rahmenXPos = xOffsetRahmen + (position * 38);
  int bildXPos   = xOffsetBild   + (position * 38);

  // Rahmen zeichnen (35x35, mit Radius 5)
  display.drawRoundRect(rahmenXPos + 6, 20, 35, 35, 5, SH110X_WHITE);

  // Bitmap zeichnen
  // HINWEIS: Wenn dein Pointer-Array tatsächlich in PROGMEM liegt und
  // du Probleme bekommst, auf AVR-Boards besser so lesen:
  // const unsigned char* bmp = (const unsigned char*)pgm_read_ptr(&epd_bitmap_allArray[bild]);
  // display.drawBitmap(bildXPos + 6, 22, bmp, img_width, img_height, SH110X_WHITE);
  display.drawBitmap(bildXPos + 6, 22, epd_bitmap_allArray[bild], img_width, img_height, SH110X_WHITE);
}

Zufallszahl für Symbole

Das Bild, das beim Rotieren einer Walze angezeigt wird, wird per Zufallszahl ermittelt:

int randNumber = random(NUM_ELEMENTS);

In meinem Fall gibt es 4 Symbole (Kleeblatt, Kirsche, Herz und Sieben), also Zufallszahlen von 0–3.

Die Anzahl lässt sich beliebig erweitern – einfach weitere Bitmaps hinzufügen und NUM_ELEMENTS anpassen.
Da das XBM-Format sehr speicherschonend ist, kannst du problemlos auch 6, 8 oder noch mehr Symbole verwenden.

// Merker, welches Symbol auf welcher Walze zuletzt liegt
// slot[0] = linke Walze, slot[1] = mittlere, slot[2] = rechte
int slot[] = { -1, -1, -1 };

// Wie viele Walzen sind bereits per Tastendruck gestoppt?
// -1 = noch keine, 0 = erste gestoppt, 1 = zweite gestoppt, 2 = alle drei gestoppt
int currentIndex = -1;

void setup() {
  ...
  // Zufallszahlengenerator initialisieren
  randomSeed(analogRead(0));
  ...
}

// Dreht die noch nicht gestoppten Walzen „weiter“:
// Für jede nicht fixierte Walze: löschen, zufälliges Symbol wählen,
// merken und neu zeichnen. Aktualisiert die Anzeige und wartet kurz.
void rotiereBild() {
  for (int i = 0; i < 3; i++) {
    if (currentIndex >= i) {      // Walze i ist bereits gestoppt -> überspringen
      continue;
    }
    loescheBild(i);               // altes Symbol entfernen
    display.display();
    int randNumber = random(NUM_ELEMENTS); // 0..3
    slot[i] = randNumber;         // Symbol merken (für Ergebnisprüfung)
    zeichneXBmp(i, randNumber);   // neues Symbol zeichnen
  }
  display.display();              // alle Änderungen anzeigen
  delay(750);                     // Rotationsgeschwindigkeit (größer = langsamer)
}

Quellcode

Nachfolgend der Quellcode zum Download und zum kopieren.

Mini-Spiel: Arduino SlotmachineHerunterladen
Datei: arduino_slotmachine.ino
/*****************************************************
 * Titel: Arduino Slotmachine – Mini-Spiel auf dem OLED!
 *
 * Beschreibung:
 * Dieses Projekt zeigt eine kleine Slotmaschine auf
 * einem 1,3" I²C-OLED (SH1106). Drei Walzen rotieren
 * mit zufälligen Symbolen (Kleeblatt, Herz, Kirschen,
 * Sieben). Mit jedem Tastendruck stoppst du die nächste
 * Walze. Gewinn/Falsch-Ende wird auf dem Display
 * angezeigt und per Buzzer-Sound quittiert.
 *
 * Voller Projekt-Artikel:
 * https://draeger-it.blog/gluecksspiel-im-mini-format-slotmaschine-mit-arduino-oled-bauen/
 *
 * Hardware:
 * - Arduino Nano R4 (andere kompatible Boards möglich)
 * - 1,3" OLED (SH1106, I²C, Adresse 0x3C)
 * - Taster an D2 (gegen GND, INPUT_PULLUP)
 * - Buzzer an D3
 * - Beim Nano R4: 2x 4,7 kΩ Pullups für SDA/SCL auf VCC
 *
 * Bibliotheken (über Bibliotheksverwalter installieren):
 * - Adafruit_GFX
 * - Adafruit_SH110X
 *****************************************************/

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SH110X.h>

// --- eigene Assets (Bitmaps & Sounds) ---
#include "kleeblatt.h"
#include "herz.h"
#include "kirsche.h"
#include "sieben.h"
#include "winner_tone.h"
#include "fail_tone.h"

// I²C-Adresse des SH1106-Displays (typischerweise 0x3C)
#define i2c_Address 0x3c

// Pin für den Taster (gegen GND, wir nutzen INPUT_PULLUP)
#define taster 2

// Pin für den Buzzer (aktiv per HIGH)
#define BUZZER_PIN 3

// Größe der XBM-Symbole (alle 32x32 Pixel)
#define img_width  32
#define img_height 32

// Display-Objekt: 128x64 Pixel, I²C, kein Reset-Pin
Adafruit_SH1106G display = Adafruit_SH1106G(128, 64, &Wire, -1);

// Anzahl der Symbol-Bitmaps
const int NUM_ELEMENTS = 4;

// Pointer-Array auf alle Symbol-Bitmaps (in PROGMEM abgelegt)
// Reihenfolge: 0=Kleeblatt, 1=Herz, 2=Kirschen, 3=Sieben
const unsigned char* const epd_bitmap_allArray[] PROGMEM = {
  epd_bitmap_kleeblatt,
  epd_bitmap_herz,
  epd_bitmap_kirschen,
  epd_bitmap_seven
};

// Wie viele Walzen sind bereits per Tastendruck gestoppt?
// -1 = noch keine, 0 = erste gestoppt, 1 = zweite gestoppt, 2 = alle drei gestoppt
int currentIndex = -1;

// Zeitverwaltung für einfache Entprellung / Blockzeit zwischen Tastendrücken
long lastButtonPress = -1;
const long TIME_BETWEEN_PRESS = 500; // ms

// Merker, welches Symbol auf welcher Walze zuletzt liegt
// slot[0] = linke Walze, slot[1] = mittlere, slot[2] = rechte
int slot[] = { -1, -1, -1 };

// Signalisiert, dass eine Runde abgeschlossen ist
bool endGame = false;

void setup() {
  Serial.begin(9600);

  // Taster-Pin auf internen Pullup schalten
  pinMode(taster, INPUT_PULLUP);

  // Interrupt auf den Taster legen:
  // CHANGE = löst bei Flanke (HIGH->LOW und LOW->HIGH) aus.
  // Wir schützen uns gegen Doppeltrigger mit TIME_BETWEEN_PRESS.
  attachInterrupt(digitalPinToInterrupt(taster), stoppSlotMachine, CHANGE);

  // Buzzer-Pin als Ausgang
  pinMode(BUZZER_PIN, OUTPUT);

  // Zufallszahlengenerator initialisieren
  randomSeed(analogRead(0));

  // Display starten und kurzen Boot-Screen zeigen
  delay(250);
  display.begin(i2c_Address, true);
  display.display();
  delay(2000);

  // Erste Runde vorbereiten
  startGame();
}

// Setzt eine neue Runde auf: Anzeige leeren, Überschrift zeichnen,
// drei Rahmen/Symbole initial zeigen, Status zurücksetzen.
void startGame() {
  Serial.println("startGame");

  currentIndex = -1;
  slot[0] = slot[1] = slot[2] = -1;
  endGame = false;

  display.clearDisplay();
  display.setTextColor(SH110X_WHITE);
  display.setTextSize(1);
  display.setCursor(9, 8);
  display.println(F("Arduino Slotmachine"));

  // Anfangsanzeige: drei Symbole (0,1,2) ins Raster zeichnen
  zeichneXBmp(0, 0);
  zeichneXBmp(1, 1);
  zeichneXBmp(2, 2);

  display.display();
  endGame = false;
}

// ISR (Interrupt Service Routine) für den Taster.
// Achtung: ISR sollte kurz sein – hier nur Status erhöhen
// und eine einfache Sperrzeit gegen Prellen/Mehrfachtrigger prüfen.
void stoppSlotMachine() {
  long currentMillis = millis();
  if (currentMillis > (lastButtonPress + TIME_BETWEEN_PRESS) && !endGame) {
    currentIndex++;               // nächste Walze wird „fixiert“
    lastButtonPress = currentMillis;
  }
}

// Zeichnet einen Symbol-Rahmen + Bitmap an Position 0/1/2.
// 'bild' ist der Index im epd_bitmap_allArray (0..3)
void zeichneXBmp(int position, int bild) {
  // Layout-Offsets (Rahmen und Bild leicht eingerückt)
  int xOffsetRahmen = 4;
  int yOffsetRahmen = 20;
  int xOffsetBild   = 4;
  int yOffsetBild   = 22;

  // X-Positionen: drei Spalten im Abstand von 38 Pixeln
  int rahmenXPos = xOffsetRahmen + (position * 38);
  int bildXPos   = xOffsetBild   + (position * 38);

  // Rahmen zeichnen (35x35, mit Radius 5)
  display.drawRoundRect(rahmenXPos + 6, 20, 35, 35, 5, SH110X_WHITE);

  // Bitmap zeichnen
  // HINWEIS: Wenn dein Pointer-Array tatsächlich in PROGMEM liegt und
  // du Probleme bekommst, auf AVR-Boards besser so lesen:
  // const unsigned char* bmp = (const unsigned char*)pgm_read_ptr(&epd_bitmap_allArray[bild]);
  // display.drawBitmap(bildXPos + 6, 22, bmp, img_width, img_height, SH110X_WHITE);
  display.drawBitmap(bildXPos + 6, 22, epd_bitmap_allArray[bild], img_width, img_height, SH110X_WHITE);
}

// Löscht den Bereich einer Walze (füllt den Rahmen schwarz)
void loescheBild(int position) {
  int xOffsetRahmen = 4;
  int yOffsetRahmen = 20;
  int rahmenXPos = xOffsetRahmen + (position * 38);
  display.fillRoundRect(rahmenXPos + 6, 20, 35, 35, 5, SH110X_BLACK);
}

// Dreht die noch nicht gestoppten Walzen „weiter“:
// Für jede nicht fixierte Walze: löschen, zufälliges Symbol wählen,
// merken und neu zeichnen. Aktualisiert die Anzeige und wartet kurz.
void rotiereBild() {
  for (int i = 0; i < 3; i++) {
    if (currentIndex >= i) {      // Walze i ist bereits gestoppt -> überspringen
      continue;
    }
    loescheBild(i);               // altes Symbol entfernen
    display.display();
    int randNumber = random(NUM_ELEMENTS); // 0..3
    slot[i] = randNumber;         // Symbol merken (für Ergebnisprüfung)
    zeichneXBmp(i, randNumber);   // neues Symbol zeichnen
  }
  display.display();              // alle Änderungen anzeigen
  delay(750);                     // Rotationsgeschwindigkeit (größer = langsamer)
}

// Gewinnanzeige: Display-Bereiche leeren, „Gewonnen!“ zeigen, Sieg-Sound spielen
void gewonnen() {
  for (int i = 0; i < 3; i++) {
    loescheBild(i);
  }
  display.setTextColor(SH110X_WHITE);
  display.setTextSize(2);
  display.setCursor(15, 26);
  display.println(F("Gewonnen!"));
  display.display();
  playVictory(); // in winner_tone.h implementiert
}

// Verlustanzeige: Display-Bereiche leeren, „Verloren!“ zeigen, Game-Over-Sound spielen
void verloren() {
  for (int i = 0; i < 3; i++) {
    loescheBild(i);
  }
  display.setTextColor(SH110X_WHITE);
  display.setTextSize(2);
  display.setCursor(15, 26);
  display.println(F("Verloren!"));
  display.display();
  playGameOver(); // in fail_tone.h implementiert
}

void loop() {
  // Solange noch nicht alle drei Walzen gestoppt sind, weiter „rotieren“
  if (currentIndex != 2) {
    rotiereBild();
  } else {
    // Alle Walzen stehen: Ergebnis prüfen
    if (slot[0] == slot[1] && slot[0] == slot[2]) {
      gewonnen();
    } else {
      verloren();
    }
    // Runde beenden und nach kurzer Pause neu starten
    endGame = true;
    delay(1500);
    startGame();
  }
}
Datei: kleeblatt.h
const unsigned char epd_bitmap_kleeblatt [] PROGMEM = {
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x00, 0x00, 0x3e, 0x1f, 0x00, 
	0x00, 0x7f, 0x1f, 0x80, 0x00, 0xff, 0x3f, 0x80, 0x03, 0xff, 0x3f, 0xc0, 0x07, 0xff, 0x3f, 0xe0, 
	0x0f, 0xff, 0x7f, 0xf0, 0x0f, 0xff, 0xff, 0xf8, 0x07, 0xff, 0xff, 0xf8, 0x07, 0xff, 0xff, 0xf8, 
	0x01, 0xff, 0xff, 0xf8, 0x00, 0x3f, 0xff, 0xe0, 0x00, 0x1f, 0xfc, 0x00, 0x03, 0xff, 0xfe, 0x00, 
	0x0f, 0xff, 0xff, 0xc0, 0x0f, 0xff, 0xff, 0xf0, 0x0f, 0xff, 0xff, 0xf8, 0x0f, 0xfe, 0xff, 0xf8, 
	0x07, 0xfe, 0x7f, 0xf8, 0x03, 0xfe, 0x7f, 0xf0, 0x01, 0xfc, 0x7f, 0xe0, 0x01, 0xfc, 0x3f, 0x80, 
	0x00, 0xfd, 0x3f, 0x00, 0x00, 0xf8, 0x3e, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x02, 0x00, 0x00, 
	0x00, 0x04, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
Datei: herz.h
const unsigned char epd_bitmap_herz [] PROGMEM = {
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x01, 0xf0, 0x0f, 0x80, 0x07, 0xf8, 0x1f, 0xe0, 0x0f, 0xfc, 0x3f, 0xf0, 
	0x0f, 0xfe, 0x7f, 0xf0, 0x1f, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xf8, 
	0x3f, 0xff, 0xff, 0xfc, 0x1f, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xf8, 
	0x1f, 0xff, 0xff, 0xf8, 0x0f, 0xff, 0xff, 0xf0, 0x0f, 0xff, 0xff, 0xf0, 0x07, 0xff, 0xff, 0xe0, 
	0x03, 0xff, 0xff, 0xc0, 0x01, 0xff, 0xff, 0x80, 0x00, 0x7f, 0xfe, 0x00, 0x00, 0x3f, 0xfc, 0x00, 
	0x00, 0x1f, 0xf8, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x01, 0x80, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
Datei: kirsche.h
const unsigned char epd_bitmap_kirschen [] PROGMEM = {
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x7f, 0x00, 
	0x00, 0x00, 0xbf, 0x80, 0x00, 0x01, 0x2f, 0xe0, 0x00, 0x03, 0x2f, 0xe0, 0x00, 0x06, 0x27, 0xf0, 
	0x00, 0x04, 0x27, 0xf8, 0x00, 0x0c, 0x23, 0xf8, 0x00, 0x08, 0x20, 0xfc, 0x00, 0x08, 0x20, 0x00, 
	0x00, 0x18, 0x20, 0x00, 0x00, 0x10, 0x20, 0x00, 0x0f, 0x30, 0x20, 0x00, 0x1f, 0xe0, 0x30, 0x00, 
	0x13, 0xfc, 0x10, 0x00, 0x33, 0xfe, 0x13, 0xc0, 0x27, 0xfc, 0xd7, 0xe0, 0x27, 0xf9, 0xff, 0xf0, 
	0x33, 0xfb, 0x7f, 0xf0, 0x33, 0xf2, 0x7f, 0xf8, 0x1f, 0xf6, 0x7f, 0xf8, 0x1f, 0xf6, 0x7f, 0xf8, 
	0x0f, 0xf2, 0x7f, 0xf0, 0x0f, 0xf2, 0x3f, 0xf0, 0x07, 0xe3, 0x3f, 0xf0, 0x00, 0x01, 0xff, 0xe0, 
	0x00, 0x00, 0xff, 0xe0, 0x00, 0x00, 0x7f, 0xc0, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00
};
Datei: sieben.h
const unsigned char epd_bitmap_seven [] PROGMEM = {
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 
	0x00, 0xff, 0xc0, 0x00, 0x00, 0xff, 0xf8, 0x80, 0x00, 0xff, 0xff, 0xc0, 0x00, 0xff, 0xff, 0xc0, 
	0x01, 0xff, 0xff, 0xc0, 0x01, 0xff, 0xff, 0x80, 0x01, 0xfd, 0xff, 0x00, 0x01, 0xf0, 0x7e, 0x00, 
	0x01, 0xe0, 0xfe, 0x00, 0x00, 0x41, 0xfc, 0x00, 0x00, 0x03, 0xfc, 0x00, 0x00, 0x07, 0xf8, 0x00, 
	0x00, 0x07, 0xf8, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0x00, 0x1f, 0xf0, 0x00, 
	0x00, 0x1f, 0xf0, 0x00, 0x00, 0x1f, 0xf0, 0x00, 0x00, 0x1f, 0xf0, 0x00, 0x00, 0x1f, 0xf0, 0x00, 
	0x00, 0x1f, 0xf0, 0x00, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x3f, 0xf0, 0x00, 
	0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
Datei: winner_tone.h
#define BUZZER_PIN 3

// Frequenzen (Hz) für die Noten (C-Dur, mittlere bis hohe Lage)
#define C5  523
#define D5  587
#define E5  659
#define F5  698
#define G5  784
#define C6  1047
#define E6  1319

// Melodie: kurzer Fanfaren-Arpeggio + kleine Schluss-Kadenz
int melodyVictory[] = {
  C5, E5, G5, C6,   // Auftakt: C-Dur Arpeggio
  E5, G5, C6, E6,   // Steigerung
  G5, F5, E5, D5, C5 // Abstieg zur Auflösung
};

// Dauer je Note in Millisekunden (passend rhythmisch betont)
int durationsVictory[] = {
  160, 160, 160, 320,
  160, 160, 160, 320,
  180, 180, 180, 180, 420
};

void playVictory() {
  const float gapFactor = 0.25; // kurze Pause zwischen Noten (25% der Notenlänge)

  for (unsigned int i = 0; i < sizeof(melodyVictory) / sizeof(melodyVictory[0]); i++) {
    int note = melodyVictory[i];
    int dur  = durationsVictory[i];

    if (note > 0) {
      tone(BUZZER_PIN, note, dur);
    }
    // kleine Lücke nach jeder Note, macht es „fröhlicher“ und klarer
    delay(dur + (int)(dur * gapFactor));
    noTone(BUZZER_PIN);
  }
}
Datei: fail_tone.h
#define BUZZER_PIN 3

// Frequenzen (Hz) – untere Oktave für "düstereren" Klang
#define A4  440
#define F4  349
#define D4  294
#define C4  262

// Melodie: absteigendes Motiv -> wirkt traurig
int melodyFail[] = {
  A4, F4, D4, C4
};

// Dauern der Noten in Millisekunden
int durationsFail[] = {
  400, 400, 500, 800
};

void playGameOver() {
  const float gapFactor = 0.3; // etwas längere Pausen -> wirkt „schwerer“

  for (unsigned int i = 0; i < sizeof(melodyFail) / sizeof(melodyFail[0]); i++) {
    int note = melodyFail[i];
    int dur  = durationsFail[i];

    if (note > 0) {
      tone(BUZZER_PIN, note, dur);
    }
    delay(dur + (int)(dur * gapFactor));
    noTone(BUZZER_PIN);
  }
}

Letzte Aktualisierung am: 04. September 2025

Foto von Stefan Draeger
Über den Autor

Stefan Draeger — Entwickler & Tech-Blogger

Ich zeige praxisnah, wie du Projekte mit Arduino, ESP32 und Smarthome-Komponenten umsetzt – Schritt für Schritt, mit Code und Schaltplänen.

Mehr Artikel von Stefan →

1 thought on “Glücksspiel im Mini-Format: Slotmaschine mit Arduino & OLED bauen”

  1. grow a garden calculator sagt:
    11. September 2025 um 04:32 Uhr

    Das Projekt ist super! Die Schritt-für-Schritt-Anleitung und die Code-Snippets sind super verständlich. Besonders gut finde ich die Erklärung zum Interrupt-Handling – das hat mir bei meinen eigenen Projekten schon mal geholfen. Die OLED-Anbindung mit den Bitmaps ist auch ein kluger Trick. Ein bisschen unklar war mir erst der Pointer-Array im PROGMEM, aber danke für den Hinweis. Das mit dem Buzzer-Sound zum Abschluss ist auch nett! Ein tolles, klares Tutorial für alle, die eine Slotmachine bauen wollen.

    Antworten

Schreibe einen Kommentar Antwort abbrechen

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Fragen oder Feedback?

Du hast eine Idee, brauchst Hilfe oder möchtest Feedback loswerden?
Support-Ticket erstellen

Newsletter abonnieren

Bleib auf dem Laufenden: Erhalte regelmäßig Updates zu neuen Projekten, Tutorials und Tipps rund um Arduino, ESP32 und mehr – direkt in dein Postfach.

Jetzt Newsletter abonnieren

Unterstütze meinen Blog

Wenn dir meine Inhalte gefallen, freue ich mich über deine Unterstützung auf Tipeee.
So hilfst du mit, den Blog am Leben zu halten und neue Beiträge zu ermöglichen.

draeger-it.blog auf Tipeee unterstützen

Vielen Dank für deinen Support!
– Stefan Draeger

Kategorien

Tools

  • Unix-Zeitstempel-Rechner
  • ASCII Tabelle
  • Spannung, Strom, Widerstand und Leistung berechnen
  • Widerstandsrechner
  • 8×8 LED Matrix Tool
  • 8×16 LED Matrix Modul von Keyestudio
  • 16×16 LED Matrix – Generator

Links

Blogverzeichnis Bloggerei.de TopBlogs.de das Original - Blogverzeichnis | Blog Top Liste Blogverzeichnis trusted-blogs.com

Stefan Draeger
Königsberger Str. 13
38364 Schöningen
Tel.: 015565432686
E-Mail: info@draeger-it.blog

Folge mir auf

link zu Fabook
link zu LinkedIn
link zu YouTube
link zu TikTok
link zu Pinterest
link zu Instagram
  • Impressum
  • Datenschutzerklärung
  • Disclaimer
  • Cookie-Richtlinie (EU)
©2025 Technik Blog | Built using WordPress and Responsive Blogily theme by Superb
Cookie-Zustimmung verwalten
Wir verwenden Technologien wie Cookies, um Geräteinformationen zu speichern und/oder darauf zuzugreifen. Wir tun dies, um das Surferlebnis zu verbessern und um personalisierte Werbung anzuzeigen. Wenn Sie diesen Technologien zustimmen, können wir Daten wie das Surfverhalten oder eindeutige IDs auf dieser Website verarbeiten. Wenn Sie Ihre Zustimmung nicht erteilen oder zurückziehen, können bestimmte Funktionen beeinträchtigt werden.
Funktional Immer aktiv
Die technische Speicherung oder der Zugang ist unbedingt erforderlich für den rechtmäßigen Zweck, die Nutzung eines bestimmten Dienstes zu ermöglichen, der vom Teilnehmer oder Nutzer ausdrücklich gewünscht wird, oder für den alleinigen Zweck, die Übertragung einer Nachricht über ein elektronisches Kommunikationsnetz durchzuführen.
Vorlieben
Die technische Speicherung oder der Zugriff ist für den rechtmäßigen Zweck der Speicherung von Präferenzen erforderlich, die nicht vom Abonnenten oder Benutzer angefordert wurden.
Statistiken
Die technische Speicherung oder der Zugriff, der ausschließlich zu statistischen Zwecken erfolgt. Die technische Speicherung oder der Zugriff, der ausschließlich zu anonymen statistischen Zwecken verwendet wird. Ohne eine Vorladung, die freiwillige Zustimmung deines Internetdienstanbieters oder zusätzliche Aufzeichnungen von Dritten können die zu diesem Zweck gespeicherten oder abgerufenen Informationen allein in der Regel nicht dazu verwendet werden, dich zu identifizieren.
Marketing
Die technische Speicherung oder der Zugriff ist erforderlich, um Nutzerprofile zu erstellen, um Werbung zu versenden oder um den Nutzer auf einer Website oder über mehrere Websites hinweg zu ähnlichen Marketingzwecken zu verfolgen.
Optionen verwalten Dienste verwalten Verwalten von {vendor_count}-Lieferanten Lese mehr über diese Zwecke
Einstellungen anzeigen
{title} {title} {title}