1stMARIO KART KI
RUNDE 4/4
×12
0:00.035
BAUTAGEBUCH

Zum Nachbauen

Was fertig ist, welche Dateien man braucht und wie das erste Koppeln abläuft. Der Download folgt als ZIP.

ZUM NACHBAUEN

Was fertig ist

Der komplette Quellcode liegt auf GitHub: github.com/ichrocke/arduino-mariokart (Firmware, Mac-Programm, Notizen, diese Seite). Hier die Übersicht, damit klar ist, was einen erwartet. Man braucht: einen ESP32 mit Bluetooth Classic (WROVER oder WROOM, ein paar Euro), ein USB-Kabel, einen Mac oder PC mit Python, eine Switch mit Mario Kart 8 Deluxe und für die KI-Teile eine HDMI-Capture-Karte (UVC-Stick mit MS2109-Chip, etwa 15 Euro; sie sitzt zwischen Dock und Fernseher) sowie ein Gamepad am Rechner für die Trainingsfahrten.

Hinweis zum Repository

Das GitHub-Repository ist im Moment noch privat. Ich räume Code und Notizen noch auf, bevor ich es freigebe; das dauert noch etwas. Die Links auf dieser Seite führen bis dahin ins Leere. Sobald es offen ist, steht es hier.

Firmware für den ESP32

Basiert auf JereDev-Source/esp32-switch-controller (GPL-3.0). Eigene Ergänzungen: Auto-Reconnect zur gespeicherten Konsole, Befehle reconnect und unpair, kompakte Antworten mit Latenzwert, schnellere Abfrage der seriellen Schnittstelle. Gebaut wird mit PlatformIO und ESP-IDF 5.5.

  • platformio.ini – Board, Umgebung wrover, 16 MB Flash
  • sdkconfig.wrover – Bluetooth-Konfiguration: nur Controller, kein Bluedroid
  • btstack_hid.c / btstack_hid.h – Bluetooth-Teil: Pro-Controller-Profil, Reconnect, Report-Takt
  • switch_proto.c – das Frage-Antwort-Spiel mit der Switch (Subcommands)
  • pc_control.c – JSON-Protokoll zum Mac, Watchdog
  • main.c, CMakeLists.txt – Einstieg und Build
  • BTstack als Komponente (mitgeliefert, inklusive micro-ecc)
pio run -e wrover -t upload

Steuerzentrale am Mac (Python)

  • gui.py – die GUI mit drei Tabs: Controller, Capture (Vorschau, Latenz, Aufnahme) und KI (fahren lassen, Shadow-Modus)
  • action.py – das Aktionsformat (siehe unten), gemeinsam für Tastatur, Gamepad und KI
  • link_json.py – Adapter zum JSON-Protokoll der Firmware, 50 Zustände pro Sekunde, Latenzstatistik
  • link.py, protocol.py – Port-Suche, Reset, altes Binärprotokoll
  • latency_test.py – Messung Mac → ESP32 → Funkpaket
  • device.py, latency.py, recorder.py – Capture-Karte, Ende-zu-Ende-Latenz, Aufnahme (JPEG 160×90 mit Aktionen, 30 Hz)
  • dataset.py, model.py, train.py – Trainingsdaten zuschneiden und stapeln, das Netz (KartNet), das Training
  • policy.py – der Echtzeit-Fahrer: Bild rein, Aktion raus, 15-mal pro Sekunde
  • env.py – die Schnittstelle, hinter der die KI Bild und Eingabe sieht
  • requirements.txt – pyserial, pygame-ce, opencv-python, numpy, torch
  • Controller starten.command – Doppelklick-Starter für macOS
python3 -m venv .venv
.venv/bin/pip install -r requirements.txt
.venv/bin/python gui.py

Erstes Koppeln

  1. ESP32 per USB an den Mac, GUI starten, warten bis der Chip „Seriell“ grün ist.
  2. Switch 2: Home → Controller → Griff/Reihenfolge ändern.
  3. Nach wenigen Sekunden erscheint „Pro Controller“. Fenster anklicken, Leertaste ist A.
  4. Ab jetzt verbindet sich die Firmware nach jedem Neustart von selbst wieder.

Die KI fahren lassen

  1. Capture-Karte zwischen Dock und Fernseher, Webcam abziehen. Im Capture-Tab „Geräte suchen“, dann „Capture“ (F4).
  2. Zeitfahren starten, Aufnahme an (F6) und selbst fahren. 20 Minuten reichen für ein erstes Modell.
  3. Training starten: python -m train.train --shift 2 --val none, etwa vier Minuten auf einem Apple-Silicon-Mac.
  4. Im KI-Tab „Modell laden“, Rennen starten, F7. Die KI lenkt und driftet, A hält sie selbst. Greift man am Gamepad ein, fährt man sofort selbst; loslassen, und sie übernimmt wieder.
  5. Läuft dabei die Aufnahme, zählen nur die eigenen Eingriffe als Lernziel. Nachtrainieren, Modell laden, wiederholen.

Das Protokoll zwischen Mac und ESP32

JSON-Zeilen über die serielle Schnittstelle mit 115 200 Baud. Der Mac schickt den vollständigen Zustand, die Firmware antwortet kurz:

Mac → ESP32:  {"id":412,"cmd":"state","r":8,"s":0,"l":0,"lx":2048,"ly":2048,"rx":2048,"ry":2048}
ESP32 → Mac:  @PC {"id":412,"ok":true,"connected":true,"lag":11}

r, s und l sind die drei Tastenbytes wie im echten Controller-Report (hier: A gedrückt). Sticks haben 12 Bit, 2048 ist die Mitte. Kommt 500 ms kein Zustand, lässt die Firmware alle Tasten los.

Aktionsformat

@dataclass
class Action:
    steer: float   # -1.0 links … +1.0 rechts (linker Stick X)
    ly: float      # linker Stick Y
    rx: float      # rechter Stick X
    ry: float      # rechter Stick Y
    accel: bool    # A
    brake: bool    # B
    drift: bool    # R
    item: bool     # L
    buttons: Button  # weitere Tasten als Bitmaske
    hat: Hat         # Steuerkreuz

Dieses Format ist die Schnittstelle zwischen allem, was fährt (Tastatur, Gamepad, KI) und allem, was sendet (Firmware). Die KI muss später nur eine Action pro Bild liefern.

Lizenzen und Marken

Die Firmware steht unter GPL-3.0 (Urheber JereDev-Source, Anpassungen aus diesem Projekt), der Python-Teil wird mit dem ZIP ebenfalls quelloffen. Nintendo, Switch, Mario Kart und Pro Controller sind Marken von Nintendo. Dieses Projekt ist ein privates Hobby ohne Verbindung zu Nintendo.