COCKPIT SUITELIVE HUB /

Werkstatt / KI und Programmierung

Mit KI zum ersten eigenen Cockpitmodul: vier LEDs und ein OLED

Du musst noch nicht programmieren können, um mit einem kleinen Cockpitprojekt anzufangen. Ein klar beschriebenes Ziel, bekannte Bauteile und kurze Tests helfen dir, KI sinnvoll einzusetzen. Hier entsteht Schritt für Schritt eine Anzeige, deren Verhalten du selbst bestimmen und überprüfen kannst.

Dein ErgebnisEin nachvollziehbares Arduino-Uno-R3-Lernprojekt: vier einzeln steuerbare LEDs, drei OLED-Werte, ein vollständiger Sketch und ein Prompt für eigene Erweiterungen.

Redaktionsstand: 18. Oktober 2026

Ein überschaubares Ziel macht den Anfang leichter

Stell dir ein kleines Statuspanel neben deinem Lenkrad oder deiner Flugkonsole vor. Vier Leuchten zeigen Zustände, ein OLED zeigt Geschwindigkeit, Drehzahl und einen Tankwert. Für den ersten Aufbau kommen diese Werte bewusst aus dem seriellen Monitor der Arduino IDE. Du brauchst deshalb keinen laufenden Simulator und kannst jede Reaktion selbst auslösen.

Die Anforderung lautet: Vier LEDs sollen unabhängig schalten; das Display soll dieselben empfangenen Werte lesbar darstellen. Die Aufgabe des Programms ist, vollständige Nachrichten zu prüfen, gültige Daten gemeinsam zu übernehmen und veraltete Daten kenntlich zu machen. Das erwartete Resultat ist kein automatisch fertiges Simulatorgerät, sondern ein funktionierender, verständlicher Baustein.

KI kann dir Anschlüsse erklären, Code entwerfen und Fehlermeldungen einordnen. Du gibst die Richtung vor: Was soll passieren, wann soll es passieren und woran erkennst du Erfolg? Diese Fragen kannst du beantworten, auch wenn Begriffe wie Variable oder Funktion noch neu sind. Lass dir unbekannte Begriffe jeweils am konkreten Beispiel erklären.

Diese Bauteile gehören zu genau diesem Beispiel

Bereitlegen: ein Arduino Uno R3, USB-Datenkabel, Steckbrett, Verbindungsleitungen, vier gewöhnliche rote Anzeige-LEDs und vier Widerstände mit jeweils 1 kΩ, mindestens 0,125 W. Das OLED ist ausdrücklich das Adafruit-Modul 4440: SSD1306, 128 × 32 Pixel, I²C, Adresse 0x3C und automatische Rücksetzung. Ein passendes STEMMA-QT-zu-Einzelader-Kabel oder bereits korrekt angelötete Anschlussstifte verbinden es mit dem Steckbrett.

Dieses konkrete Modul unterstützt laut Hersteller 5-V-Logik. Daraus folgt keine Freigabe für ein beliebiges günstiges OLED mit ähnlichem Aussehen: Controller, Pinreihenfolge, Versorgung und Pegel müssen zu dessen eigener Dokumentation passen. Ein SH1106-Display oder eine ältere Platine mit separater Resetleitung benötigt Anpassungen. Prüfe die Produktkennung vor dem Einschalten.

Der Uno R3 ist für diesen kleinen Versuch ausreichend. Sein begrenzter Arbeitsspeicher ist ein guter Grund, zunächst bei einer kleinen Textanzeige zu bleiben. Im Mikrocontrollervergleich findest du anschließend die passenden Kriterien für größere Anzeigen, mehr Geräte und leistungsfähigere Boards.

Vier LEDs und das OLED richtig anschließen

Ziehe das USB-Kabel ab, bevor du die Schaltung aufbaust oder Leitungen umsteckst. Verbinde zuerst die gemeinsame Masse und dann jede Funktion einzeln. Jede LED erhält einen eigenen Vorwiderstand; ein gemeinsamer Widerstand für alle vier wäre ungeeignet. Die Anode ist gewöhnlich das längere Bein, die Kathode die Seite mit der abgeflachten Gehäusekante. Bei gekürzten Beinen die Kennzeichnung oder das Datenblatt prüfen.

Bei etwa 2 V LED-Flussspannung ergeben 5 V und 1 kΩ ungefähr 3 mA je roter LED. Diese bewusst moderate Helligkeit reicht für den Tischversuch. Das ist kein Anschlussplan für LED-Streifen, leistungsstarke Beleuchtung oder fremde Spannungsquellen. Mehr dazu steht unter LED-Beleuchtung.

Feste Verdrahtung für Uno R3 und Adafruit 4440
Bauteil / SignalVerbindungWorauf achten?
LED 1D2 → 1 kΩ → Anode; Kathode → GNDJede LED eigener Widerstand
LED 2D3 → 1 kΩ → Anode; Kathode → GNDKeine direkte LED-Verbindung zu D3
LED 3D4 → 1 kΩ → Anode; Kathode → GNDPolung prüfen
LED 4D5 → 1 kΩ → Anode; Kathode → GNDPolung prüfen
OLED VINUno 5VNur das hier festgelegte Modul
OLED GNDUno GNDGemeinsame Masse
OLED SDAUno A4 / SDADieselbe Signalleitung
OLED SCLUno A5 / SCLDieselbe Signalleitung
OLED RSTNicht anschließen4440 besitzt Auto-Reset

Zuerst festlegen, was die Daten bedeuten

Wir definieren ein eigenes Lernformat: V1,Geschwindigkeit,Drehzahl,Tank,LED-Maske, abgeschlossen mit einem Zeilenumbruch LF. Die Verbindung läuft mit 115200 Baud. Zulässig sind ausschließlich ganze nichtnegative Zahlen: Geschwindigkeit 0–999, Drehzahl 0–20000, Tank 0–100 und Maske 0–15. Keine Leerzeichen, Einheiten oder Dezimalkommas mitsenden. Bis zu fünf vollständige Nachrichten pro Sekunde reichen für diesen Versuch.

Die Maske ist eine Summe: LED 1 hat den Wert 1, LED 2 den Wert 2, LED 3 den Wert 4 und LED 4 den Wert 8. Somit bedeutet 5 die Kombination LED 1 und 3, 15 alle vier und 0 keine. Das Display zeigt die LED-Reihenfolge 1 bis 4 von links nach rechts. Die Anzeige 1010 bedeutet hier also LED 1 und 3 an.

Beim Start steht WAIT auf dem OLED. Eine gültige Nachricht erzeugt OK im seriellen Monitor und DATA auf dem Display. Fehlerhafte Nachrichten liefern ERR und verändern die zuletzt gültigen Werte nicht. Nach drei Sekunden ohne gültige Nachricht gehen alle LEDs aus, das OLED zeigt STALE und behält die letzten Zahlen sichtbar als veraltet. Dieses Verhalten gehört zur Anforderung, nicht erst zur nachträglichen Fehlerbehandlung.

Für dieses Beispiel steht S für Geschwindigkeit in km/h, R für Umdrehungen pro Minute und F für den Tankfüllstand in Prozent. Der Sketch zeigt die Zahlen unverändert an; notwendige Einheitenumrechnung gehört später auf die Senderseite. Die vier LED-Bits haben zunächst nur Testbedeutung, keine fest zugesagte Simulatorfunktion.

Ein vollständiger Prompt statt „Schreib mir Code“

Ein guter Arduino-Prompt beschreibt Hardware, Daten und beobachtbares Verhalten. Gib der KI die Herstellerlinks und bestätigte Produktkennung mit. Bitte zunächst um eine Anschlussliste und die noch offenen Fragen. Falls du andere Teile besitzt, lass die Unterschiede klären, bevor du einen generierten Schaltplan übernimmst. Danach kann dieser Prompt als vollständige Arbeitsbeschreibung dienen:

Hilf mir als Anfänger beim Bau eines Cockpit-Lernmoduls. Erkläre die Schritte verständlich und erfinde keine Anschlüsse oder Simulator-Schnittstellen.
Hardware: Arduino Uno R3; vier rote LEDs an D2,D3,D4,D5, jeweils über 1 kOhm, Kathoden an GND. OLED: Adafruit 4440, SSD1306 128x32 I2C 0x3C, VIN=5V, GND=GND, SDA=A4, SCL=A5, Auto-Reset ohne Resetleitung.
Aufgabe: Vollständigen Arduino-Sketch mit Wire, Adafruit GFX und Adafruit SSD1306 schreiben. Eigene Testnachrichten per USB-Serial mit 115200 Baud, höchstens 5 Zeilen/s: V1,speed,rpm,fuel,flags plus LF; CRLF akzeptieren. Bereiche: speed 0..999, rpm 0..20000, fuel 0..100, flags 0..15. Bits 1,2,4,8 schalten LED1..4.
Ergebnis: Werte und LED-Zustände auf vier Textzeilen darstellen. Start WAIT, gültige Nachricht DATA/OK; ungültige Nachricht ERR ohne Teilübernahme. Nach 3000 ms ohne gültige Daten LEDs aus und STALE anzeigen, letzte Zahlen beibehalten.
Grenzen: fester 64-Byte-Empfangspuffer; Überlänge bis zum Zeilenende verwerfen; keine dynamischen String-Objekte und kein delay in loop; Anzeige höchstens alle 200 ms aktualisieren. SRAM inklusive 512-Byte-Displaypuffer beachten. Verbindungs-/Speicherfehler erklären.
Liefere Anschlussliste, vollständigen Code, Bibliotheken und Tests für Einzel-LEDs, alle LEDs, falsche Werte, Überlänge und Datenunterbrechung. Trenne Kompilierung von echter Hardwareprüfung.

Sketch vorbereiten, übertragen und verstehen

In der Arduino IDE das Board „Arduino Uno“ und den zugehörigen Port wählen. Über die Bibliotheksverwaltung Adafruit SSD1306 und Adafruit GFX Library einschließlich Adafruit BusIO installieren. Wire gehört zum AVR-Boardpaket. Den heruntergeladenen Sketch im gleichnamigen Ordner uno-led-oled öffnen, zuerst überprüfen und erst danach auf das eigene Board hochladen.

Der vollständige Beispielcode steht unten und als Datei bereit. Die eigene Ablaufsteuerung wartet nicht mit delay(); sie liest den Empfang schrittweise und erneuert die Anzeige höchstens fünfmal pro Sekunde. Die I²C-Übertragung selbst braucht dennoch Zeit. Das ist keine harte Echtzeitgarantie. Für lange Leitungen oder weitere Busgeräte brauchst du einen gesonderten Test.

Der Displaypuffer benötigt 512 Byte zusätzlich zu Variablen, Bibliothekspuffern und Stack. Diese dynamische Bibliotheksreservierung erscheint nicht vollständig in der statischen RAM-Zahl der IDE. Große Zeichenketten bleiben mit F() im Flash. Der Sketch verwendet feste Empfangsgrenzen und keine Arduino-String-Objekte. Eine erfolgreiche Kompilierung allein beweist weder die Verkabelung noch ein laufendes Display.

Dieser Sketch wurde lokal für arduino:avr:uno mit AVR-Core 1.8.7, Adafruit SSD1306 2.5.9, GFX 1.11.9 und BusIO 1.15.0 kompiliert: 15.168 Byte Flash und 614 Byte statischer RAM. Die zusätzlichen 512 Byte Bildpuffer sind weiterhin einzuplanen. Ein physischer Aufbau wurde hier nicht getestet.

Vollständigen Arduino-Sketch herunterladen

Vollständigen Beispielcode anzeigen
// Cockpit Suite workshop learning example. This is not a simulator protocol.
// Board: Arduino Uno R3. OLED: Adafruit 4440, SSD1306 128x32, I2C 0x3C.
// OLED VIN=5V, GND=GND, SDA=A4, SCL=A5; auto-reset, no reset wire.
// LEDs: D2/D3/D4/D5 -> individual 1k resistor -> anode; cathodes -> GND.
// Send at most 5 lines/second: V1,speed,rpm,fuel,flags followed by LF.
// Example: V1,120,3500,65,5 (LED1 and LED3 on). CR before LF is accepted.
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <string.h>

const uint8_t LED_PINS[4] = {2, 3, 4, 5};
const uint8_t OLED_ADDRESS = 0x3C;
const uint32_t DATA_TIMEOUT_MS = 3000;
const uint32_t SCREEN_INTERVAL_MS = 200;
Adafruit_SSD1306 display(128, 32, &Wire, -1);
char lineBuffer[64];
uint8_t lineLength = 0;
bool discardLine = false;
bool haveData = false;
bool oledReady = false;
uint16_t speedValue = 0, rpmValue = 0, fuelValue = 0, flagValue = 0;
uint32_t lastDataMs = 0, lastScreenMs = 0;

bool parseNumber(const char *&cursor, uint16_t limit, char separator,
                 uint16_t &result) {
  if (*cursor < '0' || *cursor > '9') return false;
  uint16_t value = 0;
  while (*cursor >= '0' && *cursor <= '9') {
    uint8_t digit = *cursor++ - '0';
    if (value > limit / 10 ||
        (value == limit / 10 && digit > limit % 10)) return false;
    value = value * 10 + digit;
  }
  if (*cursor != separator) return false;
  if (separator != '\0') ++cursor;
  result = value;
  return true;
}

bool parseLine(const char *line) {
  if (strncmp(line, "V1,", 3) != 0) return false;
  const char *cursor = line + 3;
  uint16_t speed, rpm, fuel, flags;
  if (!parseNumber(cursor, 999, ',', speed) ||
      !parseNumber(cursor, 20000, ',', rpm) ||
      !parseNumber(cursor, 100, ',', fuel) ||
      !parseNumber(cursor, 15, '\0', flags)) return false;
  speedValue = speed;
  rpmValue = rpm;
  fuelValue = fuel;
  flagValue = flags;
  lastDataMs = millis();
  haveData = true;
  return true;
}

void readSerial() {
  // Bound each pass so a continuous stream cannot starve the outputs.
  for (uint8_t count = 0; count < 32 && Serial.available(); ++count) {
    char character = (char)Serial.read();
    if (character == '\r') continue;
    if (character == '\n') {
      lineBuffer[lineLength] = '\0';
      if (!discardLine && parseLine(lineBuffer)) Serial.println(F("OK"));
      else Serial.println(F("ERR"));
      lineLength = 0;
      discardLine = false;
    } else if (!discardLine) {
      // NUL and non-printable input are not part of this text protocol.
      if (character < 32 || character > 126 ||
          lineLength >= sizeof(lineBuffer) - 1) {
        discardLine = true;
      } else {
        lineBuffer[lineLength++] = character;
      }
    }
  }
}

void renderScreen(bool fresh) {
  display.clearDisplay();
  display.setCursor(0, 0);
  display.print(F("S:")); display.print(speedValue);
  display.print(F(" R:")); display.println(rpmValue);
  display.print(F("F:")); display.print(fuelValue);
  display.print(F("% LED:"));
  for (uint8_t index = 0; index < 4; ++index)
    display.print(fresh && (flagValue & (1U << index)) ? '1' : '0');
  display.println();
  display.println(!haveData ? F("WAIT") : (fresh ? F("DATA") : F("STALE")));
  display.print(F("DEMO SERIAL"));
  display.display();
}

void setup() {
  for (uint8_t index = 0; index < 4; ++index) {
    digitalWrite(LED_PINS[index], LOW);
    pinMode(LED_PINS[index], OUTPUT);
  }
  Serial.begin(115200);
  Wire.begin();
#if defined(WIRE_HAS_TIMEOUT)
  Wire.setWireTimeout(25000, true);
#endif
  Wire.beginTransmission(OLED_ADDRESS);
  bool addressResponds = (Wire.endTransmission() == 0);
  oledReady = addressResponds &&
      display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDRESS, false, false);
  if (oledReady) {
    display.setTextSize(1);
    display.setTextColor(SSD1306_WHITE);
    display.setTextWrap(false);
    renderScreen(false);
  } else {
    Serial.println(F("OLED ERROR: check model, wiring, address, RAM"));
  }
  Serial.println(F("READY: V1,speed,rpm,fuel,flags"));
}

void loop() {
  readSerial();
  uint32_t now = millis();
  bool fresh = haveData && (uint32_t)(now - lastDataMs) < DATA_TIMEOUT_MS;
  for (uint8_t index = 0; index < 4; ++index)
    digitalWrite(LED_PINS[index],
                 fresh && (flagValue & (1U << index)) ? HIGH : LOW);
  if (oledReady && (uint32_t)(now - lastScreenMs) >= SCREEN_INTERVAL_MS) {
    lastScreenMs = now;
    renderScreen(fresh);
  }
}

Mit konkreten Eingaben das Ergebnis prüfen

Nach dem Übertragen den seriellen Monitor auf 115200 Baud und „Neue Zeile“ beziehungsweise „NL & CR“ stellen. Ein erneutes Öffnen des Ports kann den Uno zurücksetzen: zunächst auf READY warten. Beim allerersten Start muss das OLED WAIT anzeigen; die vier LEDs bleiben aus.

Sende V1,120,3500,65,1: nur LED 1 leuchtet. Ersetze die letzte Zahl nacheinander durch 2, 4 und 8, um jede Leitung einzeln zu prüfen. Mit V1,120,3500,65,15 leuchten alle vier; mit 0 gehen alle aus. Vergleiche die drei OLED-Zahlen mit der gesendeten Zeile. Teste außerdem die Grenzen V1,999,20000,100,15 und V1,0,0,0,0.

Sende absichtlich V1,120,3500,101,5 oder eine Zeile mit fehlendem Feld: erwartet wird ERR, ohne teilweise geänderte Anzeige. Eine Zeile mit mehr als 63 Zeichen muss bis zum Zeilenende verworfen werden; eine danach gesendete korrekte Zeile muss wieder funktionieren. Warte anschließend über drei Sekunden: LEDs aus und STALE. Eine neue gültige Zeile muss den normalen Betrieb wiederherstellen. Notiere erwartet und beobachtet getrennt.

Zum direkten Vergleich: V1,120,3500,65,15 schaltet alle vier LEDs ein, V1,120,3500,65,0 alle aus und V1,120,3500,65,5 nur LED 1 und 3 ein.

Wenn etwas fehlt: gezielt nachfragen und eingrenzen

Eine dunkle LED führt zuerst zur Polung, zum individuellen Widerstand und zur Verbindung am richtigen Pin. Ein komplett dunkles OLED führt zuerst zu Produktkennung, Versorgung, Masse, SDA/SCL und Adresse. OLED ERROR kann auf einen nicht antwortenden Bus oder eine fehlgeschlagene Speicherreservierung hinweisen. Ein erfolgreicher Adresskontakt beweist noch keine korrekte Bildausgabe.

Frage die KI mit einem konkreten Befund: „Uno R3, Modul 4440, Sketch unverändert. READY erscheint, V1,120,3500,65,1 liefert OK, LED1 leuchtet, OLED bleibt dunkel. Welche spannungsfreien Anschlussprüfungen kommen zuerst?“ Ergänze Bibliotheksversionen und die vollständige Fehlermeldung bei Compilerproblemen. Bitte um jeweils eine Änderung mit Begründung. So vermeidest du fünf gleichzeitige Umbauten, deren Wirkung niemand mehr zuordnen kann.

Speichere den funktionierenden Sketch, bevor du ihn erweitern lässt. Fordere bei Änderungen eine Erklärung der betroffenen Stellen und wiederhole die Tests. Für einen systematischen Ablauf nutze die Fehlersuche. Persönliche Zugangsdaten, private Konfigurationen und ganze unbeteiligte Projektverzeichnisse gehören nicht in einen Hilfeprompt.

Vom Lernversuch zur eigenen Simulatoranzeige

Für echte Simulatorwerte braucht der PC anschließend einen dokumentierten Datenweg: Quelle lesen, Einheiten umrechnen, Werte prüfen und die vereinbarte Nachricht senden. Unser V1-Format ist ausschließlich dieses Lernbeispiel und keine zugesagte Cockpit-Suite-Schnittstelle. Kläre die unterstützte Geräteanbindung, bevor du eine automatische Brücke planst. Der serielle Monitor und ein anderes Programm können denselben Port in der Regel nicht gleichzeitig benutzen.

Überlege bei jeder Rückmeldung, was sie wirklich aussagt: Soll eine LED einen Schalterwunsch oder den bestätigten Simulatorzustand zeigen? Wie wird „Daten fehlen“ von „Zustand aus“ unterschieden? Unter Datenzuordnung und Displays und Instrumente bauen wir diese Fragen weiter aus.

Möchtest du hauptsächlich Taster und Achsen als USB-Joystick nutzen, ist FreeJoy ein anderer Einstieg auf passender Hardware. Dieser Uno-Sketch meldet sich über den seriellen USB-Weg; er wird dadurch nicht zu einem nativen Joystick. Wähle die Lösung nach deiner Aufgabe und erweitere das Panel erst, wenn ein vollständiger Datenweg zuverlässig funktioniert.

Dein nächster Schritt muss nicht allein entstehen

Cockpit Suite bringt unterstützte Simulatoren und Geräte in einer gemeinsamen Software zusammen. Das Projekt ist jung, aber verfügbare Software und reale Aufbauten sind bereits die Grundlage. Wo passende Komponenten vorbereitet sind, wird der Einstieg einfacher; ein eigenes Arduino-Modul bleibt ein Lern- und Integrationsprojekt. Deine nachvollziehbaren Erfahrungen helfen, diese Wege weiter zu verbessern.

Zeige im Cockpit-Suite-Forum dein Ziel, die Teileliste und den letzten funktionierenden Test. Wir wollen dich bei offenen Fragen nicht allein lassen und versuchen, möglichst am selben Tag zu helfen; spät eingehende Fragen können später beantwortet werden. Auch 3D-Druck, CNC-Portalfräsen und Laserarbeiten mit LightBurn gehören zu unseren Werkstattthemen. Gerade eine aktive Community in Europa hilft uns, aus einzelnen gelungenen Versuchen verständliche Lösungen für mehr Cockpitbauer zu machen.

Quellen und technische Grundlagen

Geprüft am 18. Oktober 2026. Der Ablauf, das Datenformat und der Sketch sind ein eigenes Lernbeispiel. Herstellerangaben ersetzen keinen Test am konkreten Aufbau.

Mit dem nächsten Baustein weitermachen