Files
appRobotRoom/firmware/info.md
2026-06-16 10:06:05 +02:00

196 lines
12 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
> ⚠️ **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://<ip>: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://<ip>/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://<ip>:81/` angepasst werden, oder die Firmware auf Port 80 + Pfad `/ws`
+ CSV-Format umgestellt werden — sag Bescheid, falls das gewünscht ist.