> ⚠️ **Funktioniert nicht. Konflikt zwischen mehreren SPI nicht von Claude in > angemessener Zeit lösbar.** # VL53L5CX an ESP32-C3 (0.42" OLED Board) anschließen Diese Anleitung beschreibt die Verkabelung des VL53L5CX (8×8 Time-of-Flight Multizonen-Sensor) an das **ESP32-C3 0,42-Zoll OLED Development Board** (Type-C, Keramikantenne — verschiedene Hersteller/AliExpress-Listings, häufig unter "01Space ESP32-C3 0.42 OLED" geführt) für die [firmware.ino](firmware.ino) in diesem Verzeichnis. ## Wichtig: dieses Board hat nur EINEN I2C-Bus Das eingebaute 0,42″-OLED (72×40 Pixel sichtbar, SSD1306-Controller, I2C-Adresse `0x3C`) ist auf diesem Exemplar intern fest auf **GPIO5 (SDA) / GPIO6 (SCL)** verdrahtet (so verlötet, OLED läuft damit). Der ESP32-C3 hat aber nur eine I2C-Hardware-Peripherie — es gibt **keinen zweiten, freien I2C-Bus** für den externen Sensor. **Lösung (Versuch):** Der VL53L5CX wurde an die **gleichen** Pins (GPIO5/GPIO6) gehängt wie das OLED. Das sollte funktionieren, weil beide Geräte unterschiedliche I2C-Adressen haben (OLED `0x3C`, VL53L5CX `0x29`) — mehrere Geräte am selben I2C-Bus sind Standard, kein Konflikt. **In der Praxis bisher ohne Erfolg** — der Sensor wird über `/i2c` (Adresse `0x29`) nicht gefunden, trotz korrekt verlötetem LPN (3.3V) und geprüften Lötstellen. ## Benötigte Hardware - ESP32-C3 0.42" OLED Development Board (Type-C, wie oben beschrieben) - VL53L5CX Breakout-Board mit I2C/Qwiic-Anschluss (z.B. SparkFun SEN-18642 oder vergleichbar). **Wichtig:** ein Breakout-Board verwenden, kein nacktes VL53L5CX-Die — das Breakout enthält den nötigen 3.3V-Spannungsregler. ## Pin-Belegung | VL53L5CX Pin | ESP32-C3 Pin | Beschreibung | |----------------|----------------|------------------------------------------------------------| | `VIN` / `3V3` | `3V3` | Versorgungsspannung (3.3 V) | | `GND` | `GND` | Masse | | `SDA` | `GPIO5` | I2C Datenleitung — **gleicher Pin wie das eingebaute OLED** | | `SCL` | `GPIO6` | I2C Taktleitung — **gleicher Pin wie das eingebaute OLED** | | `LPN` | `3V3` | Enable, **active-LOW** (LOW = I2C deaktiviert). Viele Breakouts haben hier schon einen 47kΩ-Pull-up; feste 3.3V-Verbindung ist trotzdem robuster | | `INT` | *offen / nicht verbunden* | Interrupt-Pin — wird in dieser Firmware nicht benötigt (Polling per `isDataReady()`) | > **Anderes Board?** Falls du statt des 0.42"-OLED-Boards ein anderes > ESP32-C3-Devboard verwendest (ohne eingebautes Display), prüfe dessen > Pinout-Diagramm und passe `SDA_PIN`/`SCL_PIN` ganz oben in > [firmware.ino](firmware.ino) entsprechend an. > **Pull-up-Widerstände:** Die meisten VL53L5CX-Breakout-Boards haben bereits > Pull-up-Widerstände (4.7 kΩ) für SDA/SCL integriert. Bei kurzen Kabeln > (< 20 cm) sind keine zusätzlichen Widerstände nötig. ## ASCII-Schaubild ``` ESP32-C3 0.42" OLED Board VL53L5CX Breakout (I2C / Qwiic) ┌─────────────────────────┐ ┌───────────────────────────┐ │ ┌─────────┐ │ │ │ │ │ 0.42" │ │ │ │ │ │ OLED │◄── intern ─┼─ GPIO5 (SDA) │ │ │ │ 0x3C │◄── intern ─┼─ GPIO6 (SCL) │ │ │ └─────────┘ │ │ │ │ │ │ │ │ 3V3 ●────────────────┼───────────────► VIN / 3V3 │ │ GND ●────────────────┼───────────────► GND │ │ GPIO5 ● ┼─── (selber Pin wie OLED-SDA) ──► SDA (Adresse 0x29) │ │ GPIO6 ● ┼─── (selber Pin wie OLED-SCL) ──► SCL │ │ │ │ │ │ │ 3V3 ──────► LPN (Enable, high) │ │ │ offen ────► INT (nicht verwendet) │ └─────────────────────────┘ └───────────────────────────┘ ▲ USB-C (5V, 3.3V wird onboard erzeugt) ``` I2C-Bus mit zwei Teilnehmern an denselben Leitungen (GPIO5/GPIO6), unterschieden durch ihre Adresse: ``` GPIO5/SDA ───┬─────────────────┬──────────────► OLED (0x3C) GPIO6/SCL ───┤ │ └─────────────────┴──────────────► VL53L5CX (0x29) ``` ### Draufsicht / Übersicht des Aufbaus ``` ┌────────────┐ I2C-Bus (GPIO5/6 + 3V3/GND) ┌──────────────┐ │ ESP32-C3 │ ════════════════════════════════════════ │ VL53L5CX │ │ + 0.42" │ ════════════════════════════════════════ │ (8x8 ToF) │ │ OLED │ └──────┬───────┘ └─────┬──────┘ │ │ │ │ WLAN (STA → vorhandenes Netz, oder AP → eigenes Netz) │ Sichtfeld ▼ ▼ ┌────────────┐ ░░░░░░░░░░░░░░ │ Browser │ <─ WS Push (Port 81, sofort) ──────────── 64 (od. 16) │ (Landing- │ <─ HTTP Fallback ──────────────────────── Distanzwerte │ Page) │ GET /api/points (JSON-Array) (mm), 8x8/4x4 └────────────┘ ``` ## Software / Bibliotheken (Arduino IDE) 1. **Boardverwalter:** „esp32“ von Espressif Systems installieren, Board **„ESP32C3 Dev Module“** auswählen. 2. **Bibliotheksverwalter:** folgende Bibliotheken installieren: - „**SparkFun VL53L5CX**“ von SparkFun Electronics - „**WebSockets**“ von Markus Sattler (Links2004) — für den Push-Kanal auf Port 81 - „**U8g2**“ von oliver (olikraus) — für das eingebaute 0.42"-OLED 3. In [firmware.ino](firmware.ino) ganz oben anpassen (nur als Erst-Boot-Default, siehe „Inbetriebnahme“ unten — danach alles über `/config` änderbar): - `DEFAULT_WIFI_SSID` / `DEFAULT_WIFI_PASSWORD` — das WLAN, das zuerst versucht wird - `AP_SSID` / `AP_PASSWORD` — Name/Passwort des Fallback-Access-Points - `SDA_PIN` / `SCL_PIN` — auf `5`/`6` voreingestellt (passend zum 0.42"-OLED-Board); nur ändern, wenn ein anderes Board ohne eingebautes Display verwendet wird ## Inbetriebnahme (Provisioning) ohne erneutes Flashen WLAN-Zugangsdaten, Sensor-Frequenz und Sensor-Auflösung sind **nicht mehr nur Compile-Konstanten**, sondern werden persistent im Flash (Preferences/NVS) gespeichert und über die Konfigurationsseite geändert: 1. Erstes Flashen mit den `DEFAULT_*`-Werten (oder einfach Default lassen). 2. Findet der ESP32 das hinterlegte WLAN nicht, startet er den Access Point `VL53L5CX-ESP32` (Passwort `tofsensor`). 3. Mit diesem AP verbinden, Browser öffnen: `http://192.168.4.1/config` 4. Dort echtes WLAN, Sensor-Auflösung (8×8/4×4) und Frequenz eintragen, **Speichern & Neustart** klicken — der ESP32 bootet neu und verbindet sich mit dem eingetragenen WLAN. 5. Ab da ist die Seite jederzeit über `/config` (im STA-Modus z.B. `http://vl53l5cx.local/config`) erreichbar, um Werte zu ändern. > Die Konfigurationsseite läuft über **unverschlüsseltes HTTP ohne > Login** — nur fürs lokale (Heim-)Netz gedacht, nicht ins Internet exponieren. ## Verhalten der Firmware (Kurzfassung) - **Boot-Log:** Über die serielle Schnittstelle (115200 Baud) wird beim Start ausführlich geloggt: Chip-Infos, geladene Konfiguration, alle gefundenen WLAN-Netze inkl. RSSI/Kanal (mit Markierung `[ZIEL]` falls das konfigurierte Netz dabei ist), gewählter Modus (STA/AP) mit IP/MAC, sowie der Sensor-Initialisierungsstatus. - Der VL53L5CX wird **nur dann aktiv ausgelesen**, wenn in den letzten 5 Sekunden jemand die Landing-Page (`/`) oder die API (`/api/points`) aufgerufen hat, **oder** mindestens ein WebSocket-Client verbunden ist. Ist niemand da, wird das Ranging gestoppt. - **WebSocket-Push (Port 81):** Jeder verbundene Client (`ws://:81/`) bekommt jeden neu ausgelesenen Frame **sofort** nach dem Lesen als JSON gepusht — kein Polling-Delay. Die Landing-Page nutzt diesen Kanal automatisch und fällt nur bei Verbindungsabbruch auf HTTP-Polling (`/api/points`) zurück. - Die Landing-Page zeigt die Distanzwerte als farbiges Grid (Größe passt sich automatisch an 8×8 oder 4×4 an) sowie als rohes JSON-Array an. - **Eingebautes OLED:** zeigt durchgehend WLAN-Modus (`STA`/`AP`), die aktuelle IP-Adresse und den Sensor-Status (`aktiv` / `idle` / `---` falls nicht gefunden) an. Wird einmal direkt nach WLAN-Verbindung/Sensor-Init aktualisiert und danach jede Sekunde aufgefrischt, damit "aktiv"/"idle" live mitgeht. - **I2C-Übersicht (`/i2c`):** Debug-Seite, scannt beim Aufruf den gesamten I2C-Bus (Adressen `0x01`–`0x7E`) und listet alle antwortenden Geräte auf (bekannte Adressen wie `0x3C` = OLED, `0x29` = VL53L5CX werden benannt). Zeigt zusätzlich den aktuellen `sensorFound`-Status und bietet einen Button „Sensor erneut initialisieren“, der `myImager.begin()` neu auslöst — ohne dass das Gerät neu starten muss. Aktueller Befund: hier erscheint nur `0x3C` (OLED), `0x29` (VL53L5CX) fehlt. - API-Antwort von `GET /api/points` bzw. WebSocket-Push (Beispiel, 8×8): ```json { "active": true, "ranging": true, "sensorFound": true, "hz": 10, "resolution": 64, "rows": 8, "cols": 8, "wsClients": 1, "timestampMs": 123456, "wifiMode": "STA (ZyXEL7A9E80)", "ip": "10.0.0.54", "distanceMm": [1200, 1185, ...], "status": [5, 5, ...] } ``` ### Hinweis zur bestehenden Node.js-Bridge (`room.config`) Das übergeordnete Projekt (`server.js` / `room.config`) erwartet aktuell einen ESP32-WebSocket unter `ws:///ws` (Port 80, Pfad `/ws`, CSV-Frames). Diese Firmware nutzt bewusst einen **eigenständigen** WebSocket auf **Port 81** (Pfad `/`, JSON statt CSV), da das die einfachste/stabilste Bibliothek auf dem ESP32-C3 ist. Falls die bestehende Node-Bridge direkt mit dieser Firmware sprechen soll, müsste entweder `room.config` (`esp.wsUrl`) auf `ws://:81/` angepasst werden, oder die Firmware auf Port 80 + Pfad `/ws` + CSV-Format umgestellt werden — sag Bescheid, falls das gewünscht ist.