Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
| Nächste Überarbeitung | Vorhergehende Überarbeitung | ||
| weitere_hardware:nesso_n1 [18.04.2026 18:06] – angelegt mellinux | weitere_hardware:nesso_n1 [18.04.2026 19:24] (aktuell) – mellinux | ||
|---|---|---|---|
| Zeile 1: | Zeile 1: | ||
| **HINWEIS: | **HINWEIS: | ||
| - | # MeshCore — Arduino Nesso N1 (ESP32-C6) | + | ====== |
| **Author:** team-nessoN1-meshcore — team-nessoN1-meshcore@posteo.de | **Author:** team-nessoN1-meshcore — team-nessoN1-meshcore@posteo.de | ||
| Zeile 12: | Zeile 12: | ||
| einem 1, | einem 1, | ||
| - | ## Aktueller Status April 2026: | + | ===== Aktueller Status April 2026: ===== |
| Die Migration läuft (Repeater, Companion). Umfangreiche Tests stehen an. Das | Die Migration läuft (Repeater, Companion). Umfangreiche Tests stehen an. Das | ||
| Zeile 18: | Zeile 18: | ||
| Der Source wurden noch nicht veröffentlicht, | Der Source wurden noch nicht veröffentlicht, | ||
| + | ---- | ||
| - | --- | + | ===== Hardware-Überblick |
| - | + | ||
| - | ## Hardware-Überblick | + | |
| | Komponente | Details | | | Komponente | Details | | ||
| Zeile 36: | Zeile 35: | ||
| | Konnektivität | Wi-Fi 6, BT 5.3, Thread/ | | Konnektivität | Wi-Fi 6, BT 5.3, Thread/ | ||
| - | --- | + | ---- |
| - | ## Besonderheiten dieser Portierung | + | ===== Besonderheiten dieser Portierung |
| - | ### SX1262 Reset und RF-Switch über I²C-Expander | + | ==== SX1262 Reset und RF-Switch über I²C-Expander |
| Anders als bei den meisten anderen MeshCore-Zielplattformen sind beim Nesso N1 | Anders als bei den meisten anderen MeshCore-Zielplattformen sind beim Nesso N1 | ||
| Zeile 54: | Zeile 53: | ||
| | KEY2 | P1 | Taste B (Input) | | | KEY2 | P1 | Taste B (Input) | | ||
| - | Konsequenz: RadioLib' | + | Konsequenz: RadioLib' |
| - | `NessoN1Board` implementiert stattdessen das `RfSwitchCallback`-Interface, | + | '' |
| - | das `CustomSX1262Wrapper` bei jedem TX/ | + | das '' |
| - | ### Geteilter SPI-Bus (SX1262 + ST7789) | + | ==== Geteilter SPI-Bus (SX1262 + ST7789) |
| | Signal | GPIO | | | Signal | GPIO | | ||
| Zeile 69: | Zeile 68: | ||
| | LCD DC | G16 | | | LCD DC | G16 | | ||
| - | `lora_spi.begin()` wird **ohne NSS-Argument** aufgerufen. Mit NSS würde | + | '' |
| Arduino einen APB-Hardware-CS-Callback für GPIO23 registrieren; | Arduino einen APB-Hardware-CS-Callback für GPIO23 registrieren; | ||
| dasselbe für GPIO17 — zwei Callbacks auf demselben Bus führen zu | dasselbe für GPIO17 — zwei Callbacks auf demselben Bus führen zu | ||
| - | `addApbChangeCallback: | + | '' |
| - | ### FSPI statt Default-SPI | + | ==== FSPI statt Default-SPI |
| - | Der ESP32-C6 hat keinen VSPI-Bus: | + | Der ESP32-C6 hat keinen VSPI-Bus: |
| - | ### USB-CDC und BLE schließen sich aus | + | ==== USB-CDC und BLE schließen sich aus ==== |
| - | | Firmware | `ARDUINO_USB_CDC_ON_BOOT` | Debug-Output | | + | | Firmware | '' |
| |---|---|---| | |---|---|---| | ||
| - | | Repeater | `1` | USB-Serial aktiv | | + | | Repeater | '' |
| - | | Companion BLE | `0` | kein USB-Serial | | + | | Companion BLE | '' |
| - | | Companion WiFi | `0` | kein USB-Serial | | + | | Companion WiFi | '' |
| - | --- | + | ---- |
| - | ## Display-Architektur | + | ===== Display-Architektur |
| - | ### Auflösung und UITask-Layoutprüfung | + | ==== Auflösung und UITask-Layoutprüfung |
| - | Das ST7789P3 hat **240×135 Pixel** (Landscape, | + | Das ST7789P3 hat **240×135 Pixel** (Landscape, |
| Alle UITask-Standardlayouts passen ohne Überlauf: | Alle UITask-Standardlayouts passen ohne Überlauf: | ||
| Zeile 104: | Zeile 103: | ||
| Alle vier Elemente belegen zusammen ~100 px von 135 px Höhe — kein vertikaler Überlauf. | Alle vier Elemente belegen zusammen ~100 px von 135 px Höhe — kein vertikaler Überlauf. | ||
| - | ### Pflichtsequenz der Initialisierung | + | ==== Pflichtsequenz der Initialisierung |
| - | ``` | + | < |
| radio_init() in target.cpp: | radio_init() in target.cpp: | ||
| 1. board.begin() | 1. board.begin() | ||
| Zeile 112: | Zeile 111: | ||
| 3. radio.std_init(nullptr) RadioLib — nullptr: kein zweites spi-> | 3. radio.std_init(nullptr) RadioLib — nullptr: kein zweites spi-> | ||
| 4. display.begin() | 4. display.begin() | ||
| - | ``` | + | </ |
| - | --- | + | ---- |
| - | ## Bekannte Probleme und ihre Fixes | + | ===== Bekannte Probleme und ihre Fixes ===== |
| - | --- | + | ==== Fix 1 — Display schwarz nach wenigen Sekunden |
| - | + | ||
| - | ### Fix 1 — Display schwarz nach wenigen Sekunden | + | |
| **Datum:** April 2026 | **Datum:** April 2026 | ||
| - | **Betroffene Datei: | + | **Betroffene Datei: |
| **Symptom: | **Symptom: | ||
| Zeile 129: | Zeile 126: | ||
| **Ursache — präzise:** | **Ursache — präzise:** | ||
| - | `UITask.h` (MeshCore, | + | '' |
| - | Makro `SCREEN_TIMEOUT` (Standardwert: | + | Makro '' |
| - | `display.turnOff()` aufgerufen. Der Wakeup-Pfad in UITask prüft | + | '' |
| — einen direkten GPIO-Pin der bei einem Tastendruck HIGH wird. Auf dem Nesso N1 | — einen direkten GPIO-Pin der bei einem Tastendruck HIGH wird. Auf dem Nesso N1 | ||
| hängen KEY1 und KEY2 **über I²C-Expander 0** (Adresse 0x43, Pins P0/P1). | hängen KEY1 und KEY2 **über I²C-Expander 0** (Adresse 0x43, Pins P0/P1). | ||
| - | Ein direkter GPIO als `PIN_USER_BTN` steht nicht zur Verfügung. UITask hat | + | Ein direkter GPIO als '' |
| damit **keinen Wakeup-Mechanismus** — das Display bleibt nach Timeout-Ablauf | damit **keinen Wakeup-Mechanismus** — das Display bleibt nach Timeout-Ablauf | ||
| permanent schwarz. | permanent schwarz. | ||
| **Fix:** | **Fix:** | ||
| - | ```ini | + | < |
| ; platformio.ini — [env: | ; platformio.ini — [env: | ||
| -D SCREEN_TIMEOUT=0 | -D SCREEN_TIMEOUT=0 | ||
| -D DISPLAY_TIMEOUT=0 | -D DISPLAY_TIMEOUT=0 | ||
| - | ``` | + | </ |
| - | Beide Flags auf 0 deaktivieren den Timeout vollständig. | + | Beide Flags auf 0 deaktivieren den Timeout vollständig. |
| wird zusätzlich gesetzt weil verschiedene UITask-Versionen im MeshCore-Repository | wird zusätzlich gesetzt weil verschiedene UITask-Versionen im MeshCore-Repository | ||
| unterschiedliche Makronamen verwenden. | unterschiedliche Makronamen verwenden. | ||
| - | **Hinweis Akku-Betrieb: | + | **Hinweis Akku-Betrieb: |
| - | Der Button-Wakeup ist über `nesso_ui_tick()` bereits integriert (siehe Fix 7). | + | Der Button-Wakeup ist über '' |
| - | --- | + | ---- |
| - | ### Fix 7 — Tasten ohne Funktion im Repeater-Display-Modus | + | ==== Fix 7 — Tasten ohne Funktion im Repeater-Display-Modus |
| **Datum:** April 2026 | **Datum:** April 2026 | ||
| - | **Betroffene Dateien: | + | **Betroffene Dateien: |
| - | `simple_repeater/ | + | '' |
| **Symptom: | **Symptom: | ||
| - | `[ui] KEY1 erkannt` — die Taste wird erkannt, aber es passiert nichts am Display. | + | '' |
| **Ursache — präzise: | **Ursache — präzise: | ||
| - | `nesso_ui_tick()` gibt bei erkannter Taste `-1` (KEY1) oder `-2` (KEY2) zurück, | + | '' |
| - | wenn das Display bereits an ist. In `main.cpp` war die Auswertung dieser Werte | + | wenn das Display bereits an ist. In '' |
| - | vollständig **auskommentiert**. Zusätzlich hatte `UITask` keine navigierbaren | + | vollständig **auskommentiert**. Zusätzlich hatte '' |
| - | Screens und keine Verbindung zu `MyMesh`, um Nachbardaten oder einen | + | Screens und keine Verbindung zu '' |
| Discover-Request abrufen zu können. | Discover-Request abrufen zu können. | ||
| **Fix — drei Ebenen:** | **Fix — drei Ebenen:** | ||
| - | 1. **Neues Interface | + | 1. **Neues Interface |
| - | ```cpp | + | < |
| class UIActions { | class UIActions { | ||
| public: | public: | ||
| Zeile 178: | Zeile 175: | ||
| virtual void uiSendDiscover() = 0; | virtual void uiSendDiscover() = 0; | ||
| }; | }; | ||
| - | ``` | + | </ |
| - | 2. **`MyMesh` implementiert | + | 2. **'' |
| - | ```cpp | + | < |
| class MyMesh : public mesh::Mesh, public CommonCLICallbacks, | class MyMesh : public mesh::Mesh, public CommonCLICallbacks, | ||
| ... | ... | ||
| Zeile 187: | Zeile 184: | ||
| void uiSendDiscover() override { sendNodeDiscoverReq(); | void uiSendDiscover() override { sendNodeDiscoverReq(); | ||
| }; | }; | ||
| - | ``` | + | </ |
| - | 3. **`UITask` bekommt 3 Screens + Navigation**, | + | 3. **'' |
| - | ``` | + | < |
| SCREEN_HOME | SCREEN_HOME | ||
| SCREEN_NEIGHBOURS — Nachbarliste (HEX-ID, Alter, SNR) | SCREEN_NEIGHBOURS — Nachbarliste (HEX-ID, Alter, SNR) | ||
| SCREEN_POLL_SENT | SCREEN_POLL_SENT | ||
| - | ``` | + | </ |
| - | 4. **`main.cpp` wertet | + | 4. **'' |
| - | ```cpp | + | < |
| if (btn == -1) ui_task.nextScreen(); | if (btn == -1) ui_task.nextScreen(); | ||
| if (btn == -2) ui_task.prevScreen(); | if (btn == -2) ui_task.prevScreen(); | ||
| - | ``` | + | </ |
| **Bedienung nach dem Patch:** | **Bedienung nach dem Patch:** | ||
| Zeile 212: | Zeile 209: | ||
| dann wechselt er automatisch zurück zur (aktualisierten) Nachbarliste. | dann wechselt er automatisch zurück zur (aktualisierten) Nachbarliste. | ||
| - | --- | + | ---- |
| - | --- | + | ==== Fix 8 — Tasten nicht erkannt: Wire-Konflikt zwischen M5GFX und Expander-Treiber |
| - | + | ||
| - | ### Fix 8 — Tasten nicht erkannt: Wire-Konflikt zwischen M5GFX und Expander-Treiber | + | |
| **Datum:** April 2026 | **Datum:** April 2026 | ||
| - | **Betroffene Dateien: | + | **Betroffene Dateien: |
| **Symptom: | **Symptom: | ||
| nicht oder unzuverlässig registriert. Im Serial-Log erscheinen: | nicht oder unzuverlässig registriert. Im Serial-Log erscheinen: | ||
| - | ``` | + | < |
| [E][Wire.cpp: | [E][Wire.cpp: | ||
| [E][esp32-hal-cpu.c: | [E][esp32-hal-cpu.c: | ||
| - | ``` | + | </ |
| **Ursache — präzise: | **Ursache — präzise: | ||
| - | M5GFX initialisiert den I²C-Bus intern über `WireInternal.begin(SDA, | + | M5GFX initialisiert den I²C-Bus intern über '' |
| - | Der eigene | + | Der eigene |
| direkt. Beide greifen auf **denselben Bus** (SDA=GPIO10, | direkt. Beide greifen auf **denselben Bus** (SDA=GPIO10, | ||
| - | mit unterschiedlichen | + | mit unterschiedlichen |
| instabilen Expander-Reads. Dokumentiert im Arduino-Forum (November 2025): | instabilen Expander-Reads. Dokumentiert im Arduino-Forum (November 2025): | ||
| https:// | https:// | ||
| **Fix: | **Fix: | ||
| - | `M5Unified` übernimmt Button-Handling und Display-Init koordiniert. | + | '' |
| - | `M5.begin()` initialisiert Wire, M5GFX und GPIO-Expander in der richtigen | + | '' |
| Reihenfolge — kein Wire-Konflikt mehr. | Reihenfolge — kein Wire-Konflikt mehr. | ||
| - | ```cpp | + | < |
| // NessoDisplayDriver.cpp — begin(): | // NessoDisplayDriver.cpp — begin(): | ||
| M5.begin(cfg); | M5.begin(cfg); | ||
| Zeile 250: | Zeile 245: | ||
| if (M5.BtnA.wasPressed()) return 1; // KEY1 | if (M5.BtnA.wasPressed()) return 1; // KEY1 | ||
| if (M5.BtnB.wasPressed()) return 2; // KEY2 | if (M5.BtnB.wasPressed()) return 2; // KEY2 | ||
| - | ``` | + | </ |
| - | ```ini | + | < |
| ; platformio.ini — nesso_n1_base: | ; platformio.ini — nesso_n1_base: | ||
| lib_deps = | lib_deps = | ||
| m5stack/ | m5stack/ | ||
| m5stack/ | m5stack/ | ||
| - | ``` | + | </ |
| - | Entfernt: | + | Entfernt: |
| Debounce entfällt — M5Unified macht Flanken-Erkennung intern). | Debounce entfällt — M5Unified macht Flanken-Erkennung intern). | ||
| - | ### Fix 2 — Display im Portrait-Modus (135×240 statt 240×135) | + | ==== Fix 2 — Display im Portrait-Modus (135×240 statt 240×135) |
| **Datum:** April 2026 | **Datum:** April 2026 | ||
| - | **Betroffene Datei: | + | **Betroffene Datei: |
| - | **Symptom: | + | **Symptom: |
| UITask-Texte werden mit negativem x-Offset abgeschnitten und sind nicht | UITask-Texte werden mit negativem x-Offset abgeschnitten und sind nicht | ||
| lesbar (Versionszeile bei x=−11, Node-Name bei x=−29). | lesbar (Versionszeile bei x=−11, Node-Name bei x=−29). | ||
| **Ursache — präzise:** | **Ursache — präzise:** | ||
| - | `setRotation(1)` wurde in `begin()` **nach** | + | '' |
| - | aufgerufen. M5GFX tauscht die Dimensionen erst nach `setRotation()` intern um. | + | aufgerufen. M5GFX tauscht die Dimensionen erst nach '' |
| - | Die Abfrage vor `setRotation()` lieferte daher immer die Portrait-Werte 135×240. | + | Die Abfrage vor '' |
| - | Zusätzlich trat das Problem auf wenn `display.begin()` in `main.cpp` vor | + | Zusätzlich trat das Problem auf wenn '' |
| - | `radio_init()` aufgerufen wurde: Der idempotente Guard beim zweiten | + | '' |
| - | aus `radio_init()` hat `setRotation(1)` dann gar nicht mehr ausgeführt — der | + | aus '' |
| - | Controller lief weiter im Portrait-Modus obwohl | + | Controller lief weiter im Portrait-Modus obwohl |
| im Konstruktor richtig gesetzt war. | im Konstruktor richtig gesetzt war. | ||
| - | **Fix in `NessoDisplayDriver.cpp`:** | + | **Fix in '' |
| - | ```cpp | + | < |
| // setRotation ZUERST — M5GFX tauscht Dimensionen erst danach: | // setRotation ZUERST — M5GFX tauscht Dimensionen erst danach: | ||
| _gfx-> | _gfx-> | ||
| Zeile 288: | Zeile 283: | ||
| Serial.printf(" | Serial.printf(" | ||
| // Ausgabe: 240 x 135 px ✓ | // Ausgabe: 240 x 135 px ✓ | ||
| - | ``` | + | </ |
| - | --- | + | ---- |
| - | ### Fix 3 — `radio init failed: -2` durch doppelten board.begin()-Aufruf | + | ==== Fix 3 — '' |
| **Datum:** April 2026 | **Datum:** April 2026 | ||
| - | **Betroffene Datei: | + | **Betroffene Datei: |
| - | **Symptom: | + | **Symptom: |
| **Ursache — präzise:** | **Ursache — präzise:** | ||
| - | `examples/ | + | '' |
| - | `#ifdef DISPLAY_CLASS` in `setup()` explizit | + | '' |
| - | `radio_init()`. Das generische MeshCore-Muster funktioniert auf anderen Boards | + | '' |
| problemlos, weil dort Board-Init und Radio-Init unabhängig sind. Auf dem Nesso N1 | problemlos, weil dort Board-Init und Radio-Init unabhängig sind. Auf dem Nesso N1 | ||
| - | führt | + | führt |
| - | Anschließend ruft `radio_init()` erneut | + | Anschließend ruft '' |
| - | SX1262 bootet erneut, BUSY wieder HIGH → `radio.std_init()` trifft Chip mitten im | + | SX1262 bootet erneut, BUSY wieder HIGH → '' |
| - | Bootvorgang → `RADIOLIB_ERR_CHIP_NOT_FOUND` = `-2`. | + | Bootvorgang → '' |
| - | **Fix in `NessoN1Board:: | + | **Fix in '' |
| - | ```cpp | + | < |
| static bool s_boardBeginCalled = false; | static bool s_boardBeginCalled = false; | ||
| if (s_boardBeginCalled) { | if (s_boardBeginCalled) { | ||
| Zeile 317: | Zeile 312: | ||
| } | } | ||
| s_boardBeginCalled = true; | s_boardBeginCalled = true; | ||
| - | ``` | + | </ |
| - | Der Guard stellt sicher dass `loraReset()` und `lora_spi.begin()` genau einmal | + | Der Guard stellt sicher dass '' |
| - | laufen, unabhängig von der Aufruf-Reihenfolge in `main.cpp`. | + | laufen, unabhängig von der Aufruf-Reihenfolge in '' |
| - | **Vollständige Lösung:** In `main.cpp` `board.begin()` und `display.begin()` | + | **Vollständige Lösung:** In '' |
| - | aus `setup()` entfernen — beide werden intern durch `radio_init()` erledigt. | + | aus '' |
| - | Da `main.cpp` MeshCore-eigener Code ist, ist der Guard die robustere Variante | + | Da '' |
| - | ohne Repository-Fork. Hinweis: | + | ohne Repository-Fork. Hinweis: |
| - | --- | + | ---- |
| - | ### Fix 4 — APB-Callback-Duplikat und Wire.setPins-Warnung | + | ==== Fix 4 — APB-Callback-Duplikat und Wire.setPins-Warnung |
| **Datum:** April 2026 | **Datum:** April 2026 | ||
| - | **Betroffene Dateien: | + | **Betroffene Dateien: |
| **Symptom: | **Symptom: | ||
| - | ``` | + | < |
| [E][Wire.cpp: | [E][Wire.cpp: | ||
| [E][esp32-hal-cpu.c: | [E][esp32-hal-cpu.c: | ||
| [E][esp32-hal-cpu.c: | [E][esp32-hal-cpu.c: | ||
| - | ``` | + | </ |
| **Ursache — präzise:** | **Ursache — präzise:** | ||
| - | `main.cpp` ruft `display.begin()` vor `radio_init()` auf. Beim ersten | + | '' |
| - | `display.begin()`-Aufruf konstruiert | + | '' |
| - | static-local. M5GFX ruft intern | + | static-local. M5GFX ruft intern |
| - | `Wire.begin()` auf. Wenn anschließend | + | '' |
| - | `lora_spi.begin()` läuft, versucht der ESP-IDF SPI-Treiber denselben | + | '' |
| - | APB-Callback erneut zu registrieren → `duplicate`. `Wire.begin()` auf | + | APB-Callback erneut zu registrieren → '' |
| - | bereits initialisierten Bus → `setPins warning`. | + | bereits initialisierten Bus → '' |
| **Fix:** | **Fix:** | ||
| - | Der Board-Guard (Fix 3) verhindert den zweiten | + | Der Board-Guard (Fix 3) verhindert den zweiten |
| - | `BUSY` bleibt LOW, `std_init` läuft durch. Die drei `[E]`-Zeilen erscheinen | + | '' |
| - | trotzdem solange | + | trotzdem solange |
| **funktional harmlos** (System funktioniert korrekt), aber ein sichtbarer | **funktional harmlos** (System funktioniert korrekt), aber ein sichtbarer | ||
| Indikator für die unvollständig behobene Aufruf-Reihenfolge. | Indikator für die unvollständig behobene Aufruf-Reihenfolge. | ||
| - | --- | + | ---- |
| - | ### Fix 5 — BUSY-Puls-Timing nach loraReset() | + | ==== Fix 5 — BUSY-Puls-Timing nach loraReset() |
| **Datum:** April 2026 | **Datum:** April 2026 | ||
| - | **Betroffene Datei: | + | **Betroffene Datei: |
| - | **Symptom: | + | **Symptom: |
| **Ursache — präzise:** | **Ursache — präzise:** | ||
| - | Der `delay(20)` nach NRST HIGH war zu lang. Der SX1262 auf dem Nesso N1 hat | + | Der '' |
| einen BUSY-HIGH-Puls von unter 1 ms nach dem Reset — der Chip hatte BUSY längst | einen BUSY-HIGH-Puls von unter 1 ms nach dem Reset — der Chip hatte BUSY längst | ||
| - | wieder LOW gezogen wenn `digitalRead()` nach 20 ms lief. Es handelte sich um | + | wieder LOW gezogen wenn '' |
| keinen echten Fehler, sondern um ein zu konservatives Timing kombiniert mit einer | keinen echten Fehler, sondern um ein zu konservatives Timing kombiniert mit einer | ||
| zu alarmistischen Logmeldung. | zu alarmistischen Logmeldung. | ||
| **Fix:** | **Fix:** | ||
| - | ```cpp | + | < |
| _exp0.digitalWrite(NESSO_EXP0_SX_NRST, | _exp0.digitalWrite(NESSO_EXP0_SX_NRST, | ||
| delay(2); | delay(2); | ||
| - | ``` | + | </ |
| Logmeldung geändert zu: | Logmeldung geändert zu: | ||
| - | ``` | + | < |
| [loraReset] BUSY 2 ms nach NRST HIGH: LOW (Chip hat BUSY-Puls bereits abgeschlossen — normal auf Nesso N1) | [loraReset] BUSY 2 ms nach NRST HIGH: LOW (Chip hat BUSY-Puls bereits abgeschlossen — normal auf Nesso N1) | ||
| - | ``` | + | </ |
| - | --- | + | ---- |
| - | ## Verzeichnisstruktur | + | ===== Verzeichnisstruktur |
| - | ``` | + | < |
| variants/ | variants/ | ||
| ├── NessoN1Board.h | ├── NessoN1Board.h | ||
| Zeile 404: | Zeile 399: | ||
| ├── RfSwitchCallback.h | ├── RfSwitchCallback.h | ||
| └── CustomSX1262Wrapper.h | └── CustomSX1262Wrapper.h | ||
| - | ``` | + | </ |
| - | --- | + | ---- |
| - | ## Schnellstart | + | ===== Schnellstart |
| - | ### 1. Voraussetzungen | + | ==== 1. Voraussetzungen |
| - | - [PlatformIO](https:// | + | * [PlatformIO](https:// |
| - | - Arduino Nesso N1 per USB-C verbunden | + | |
| - | ### 2. Zugangsdaten einrichten | + | ==== 2. Zugangsdaten einrichten |
| - | ```bash | + | < |
| cd < | cd < | ||
| cp variants/ | cp variants/ | ||
| - | ``` | + | </ |
| - | `credentials.ini` anpassen: | + | '' |
| - | ```ini | + | < |
| [credentials] | [credentials] | ||
| build_flags_repeater = | build_flags_repeater = | ||
| Zeile 432: | Zeile 427: | ||
| -D WIFI_SSID='" | -D WIFI_SSID='" | ||
| -D WIFI_PWD='" | -D WIFI_PWD='" | ||
| - | ``` | + | </ |
| - | > `credentials.ini` ist in `.gitignore` und wird **nicht** ins Repository eingecheckt. | + | > '' |
| - | ### 3. Firmware bauen und flashen | + | ==== 3. Firmware bauen und flashen |
| **Repeater mit Display** (empfohlen als Einstieg): | **Repeater mit Display** (empfohlen als Einstieg): | ||
| - | ```bash | + | < |
| pio run -e NessoN1_repeater_display --target upload | pio run -e NessoN1_repeater_display --target upload | ||
| pio device monitor -b 115200 | pio device monitor -b 115200 | ||
| - | ``` | + | </ |
| **Repeater ohne Display:** | **Repeater ohne Display:** | ||
| - | ```bash | + | < |
| pio run -e NessoN1_repeater --target upload | pio run -e NessoN1_repeater --target upload | ||
| - | ``` | + | </ |
| **Companion Radio — BLE:** | **Companion Radio — BLE:** | ||
| - | ```bash | + | < |
| pio run -e NessoN1_companion_ble --target upload | pio run -e NessoN1_companion_ble --target upload | ||
| - | ``` | + | </ |
| **Companion Radio — WiFi/TCP:** | **Companion Radio — WiFi/TCP:** | ||
| - | ```bash | + | < |
| pio run -e NessoN1_companion_wifi --target upload | pio run -e NessoN1_companion_wifi --target upload | ||
| - | ``` | + | </ |
| - | ### 4. Erwartete Serial-Ausgabe beim Boot (Repeater mit Display) | + | ==== 4. Erwartete Serial-Ausgabe beim Boot (Repeater mit Display) |
| - | ``` | + | < |
| [board] begin() gestartet | [board] begin() gestartet | ||
| [board] | [board] | ||
| Zeile 477: | Zeile 472: | ||
| [init] === radio_init() abgeschlossen — Radio bereit === | [init] === radio_init() abgeschlossen — Radio bereit === | ||
| Repeater ID: ... | Repeater ID: ... | ||
| - | ``` | + | </ |
| - | Drei `[E]`-Zeilen (Wire.setPins, | + | Drei '' |
| - | `main.cpp` die Reihenfolge aus Fix 3/4 hat — sie sind harmlos. | + | '' |
| - | --- | + | ---- |
| - | ## Pin-Referenz | + | ===== Pin-Referenz |
| - | ### Direkte ESP32-C6 GPIOs | + | ==== Direkte ESP32-C6 GPIOs ==== |
| | Funktion | GPIO | | | Funktion | GPIO | | ||
| Zeile 502: | Zeile 497: | ||
| | Touch INT | G3 | | | Touch INT | G3 | | ||
| - | ### Über I²C-Expander 0 (0x43) | + | ==== Über I²C-Expander 0 (0x43) |
| | Funktion | Expander-Pin | | | Funktion | Expander-Pin | | ||
| Zeile 512: | Zeile 507: | ||
| | LoRa Reset (NRST) | P7 | | | LoRa Reset (NRST) | P7 | | ||
| - | ### Über I²C-Expander 1 (0x44) | + | ==== Über I²C-Expander 1 (0x44) |
| | Funktion | Expander-Pin | | | Funktion | Expander-Pin | | ||
| Zeile 519: | Zeile 514: | ||
| | LCD Backlight | P6 | | | LCD Backlight | P6 | | ||
| - | --- | + | ---- |
| - | ## RF-Switch-Schaltlogik | + | ===== RF-Switch-Schaltlogik |
| | Modus | ANT_SW | LNA_EN | Beschreibung | | | Modus | ANT_SW | LNA_EN | Beschreibung | | ||
| Zeile 529: | Zeile 524: | ||
| | IDLE | LOW | LOW | HF-Pfad getrennt, Stromsparmodus | | | IDLE | LOW | LOW | HF-Pfad getrennt, Stromsparmodus | | ||
| - | --- | + | ---- |
| - | ## Architektur | + | ===== Architektur |
| - | ``` | + | < |
| target.cpp | target.cpp | ||
| └─ radio_init() | └─ radio_init() | ||
| Zeile 552: | Zeile 547: | ||
| ├─ onRfRx() | ├─ onRfRx() | ||
| └─ onRfIdle() | └─ onRfIdle() | ||
| - | ``` | + | </ |
| - | --- | + | ---- |
| - | ## Offene Punkte | + | ===== Offene Punkte |
| | # | Thema | Status | | | # | Thema | Status | | ||
| |---|---|---| | |---|---|---| | ||
| - | | 1 | `main.cpp`: `board.begin()`/`display.begin()` vor `radio_init()` entfernen | Workaround aktiv (Guard) | | + | | 1 | '' |
| | 2 | KEY1/KEY2 als UITask Screen-Wakeup einhängen | offen | | | 2 | KEY1/KEY2 als UITask Screen-Wakeup einhängen | offen | | ||
| | 3 | Touch FT6336U (I²C 0x38) integrieren | offen | | | 3 | Touch FT6336U (I²C 0x38) integrieren | offen | | ||
| Zeile 566: | Zeile 561: | ||
| | 5 | Akku-Monitor (I²C 0x49) für Display-Anzeige | offen | | | 5 | Akku-Monitor (I²C 0x49) für Display-Anzeige | offen | | ||
| - | --- | + | ---- |
| - | ## Lizenz | + | ===== Lizenz |
| MIT-Lizenz, identisch mit MeshCore. Vollständiger Text im Wurzelverzeichnis. | MIT-Lizenz, identisch mit MeshCore. Vollständiger Text im Wurzelverzeichnis. | ||
| + | |||