From 58b386b0123e5485099118efbe0ebd604dc41005 Mon Sep 17 00:00:00 2001 From: "XPS\\Micro" Date: Sun, 19 Apr 2026 11:17:28 +0200 Subject: [PATCH] Implementiere WiFi-Integration und Projektverbesserungen MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - WiFi-Aktivierung für A/B-Test (bootCount ungerade = WiFi ON, gerade = WiFi OFF) - Zyklusende nach TOTAL_CYCLES*2 Boots implementiert - SERIAL_DEBUG-Guards für alle Debug-Ausgaben hinzugefügt - Secrets-Schutz: config.h in .gitignore, config_example.h als Template - Funktionsfehler behoben: esp_reset_cause → esp_reset_reason - Dokumentation aktualisiert (README, Info.md, CLAUDE.md) - USB-Anforderungen für Upload und Serial Monitor dokumentiert --- .gitignore | 6 + CLAUDE.md | 51 ++++++ README.md | 23 ++- docs/Info.md | 367 +++++++++++++++++++++++++++++++++++++++ include/config_example.h | 19 ++ src/main.cpp | 38 +++- 6 files changed, 495 insertions(+), 9 deletions(-) create mode 100644 .gitignore create mode 100644 CLAUDE.md create mode 100644 docs/Info.md create mode 100644 include/config_example.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b9f7f63 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +.pio +.vscode/.browse.c_cpp.db* +.vscode/c_cpp_properties.json +.vscode/launch.json +.vscode/ipch +include/config.h diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..0fd8e12 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,51 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project Overview + +ESP32-C3 firmware for measuring power consumption across different sleep states using a PowerProfiler Kit II. The firmware cycles between active periods (5s, LED on) and deep sleep (30s, minimal power), with optional WiFi enabling for A/B testing. + +## Build & Development + +All commands use PlatformIO. Board: `esp32-c3-devkitm-1`, Framework: Arduino + +```bash +# Build firmware +pio run -e esp32-c3-devkitm-1 + +# Upload to device +pio run -e esp32-c3-devkitm-1 -t upload + +# Monitor serial output (115200 baud) +pio device monitor -b 115200 + +# Clean build artifacts +pio run -e esp32-c3-devkitm-1 -t clean +``` + +## Architecture + +**Single-purpose firmware** with execution entirely in `setup()` — `loop()` is never reached due to `esp_deep_sleep_start()`. + +**Key design pattern**: RTC memory persistence via `RTC_DATA_ATTR` variables (e.g., `bootCount`) survive deep sleep resets, allowing multi-cycle experiments without external state. + +**Control flow**: +1. Boot → increment RTC counter +2. Report reset reason and cycle status +3. LED on for `ACTIVE_DURATION_MS` +4. Configure timer wakeup for `SLEEP_DURATION_S` +5. Enter deep sleep (CPU halts, only RTC timer remains) +6. Auto-wakeup via RTC timer → restart from boot + +**Configuration** (all in `include/config.h`): +- `SLEEP_DURATION_S`: Deep sleep interval +- `ACTIVE_DURATION_MS`: Time spent awake (measurement window) +- `TOTAL_CYCLES`: Number of complete cycles to run +- `WIFI_ENABLED_CYCLE_1/2`: Alternating WiFi on/off for A/B measurement comparison + +Serial debug output includes reset reason code (5 = DEEPSLEEP_RESET) for timing validation and cycle tracking. + +## Power Measurement Setup + +Device connects via PowerProfiler Kit II (supplies power + measures current). Use nRF Power Profiler app on host to record measurements. Firmware will cycle autonomously once uploaded; each boot generates serial output for correlation with profiler traces. diff --git a/README.md b/README.md index 91385da..f0ec7a7 100644 --- a/README.md +++ b/README.md @@ -9,29 +9,42 @@ Dieses PlatformIO-Projekt misst die Stromaufnahme eines ESP32-C3 in verschiedene - **UART (Optional)** → RX/TX für Debug-Output ### 2. Konfiguration -Datei `include/config.h` anpassen: +Datei `include/config_example.h` kopieren zu `include/config.h` und anpassen: +```bash +cp include/config_example.h include/config.h +``` +Dann in `include/config.h` bearbeiten: - `SLEEP_DURATION_S`: Deep Sleep Dauer (Standard: 30s) - `ACTIVE_DURATION_MS`: Zeit wach (Standard: 5s) -- `WIFI_SSID/WIFI_PASSWORD`: WLAN Credentials falls benötigt +- `WIFI_SSID/WIFI_PASSWORD`: Deine WLAN Credentials eintragen - `TOTAL_CYCLES`: Anzahl Messvorgänge +**⚠️ Wichtig**: `config.h` ist in `.gitignore` aufgeführt — Credentials werden nicht in git committed. + ### 3. Kompilieren & Hochladen +**Voraussetzung**: ESP32-C3 per **Micro-USB** mit Computer verbinden + In VSCode mit PlatformIO: ``` -Ctrl+Shift+P → PlatformIO: Build -Ctrl+Shift+P → PlatformIO: Upload +Ctrl+Shift+P → PlatformIO: Build (USB nicht nötig) +Ctrl+Shift+P → PlatformIO: Upload (USB erforderlich!) ``` Oder Terminal: ```bash -pio run -e esp32-c3-devkitm-1 -t upload +pio run -e esp32-c3-devkitm-1 # Kompilieren +pio run -e esp32-c3-devkitm-1 -t upload # Hochladen (USB erforderlich!) ``` ### 4. Serial Monitor +**Voraussetzung**: ESP32-C3 bleibt per USB angesteckt + ```bash pio device monitor -b 115200 ``` +Zeigt Echtzeit-Debug-Ausgabe der laufenden Firmware. Mit `Ctrl+C` beenden. + ## Messbetrieb Das Programm läuft automatisch in Zyklen: diff --git a/docs/Info.md b/docs/Info.md new file mode 100644 index 0000000..dbc0d35 --- /dev/null +++ b/docs/Info.md @@ -0,0 +1,367 @@ +# ESP32-C3 Power Measurement Projekt – Dokumentation + +## Projektübersicht + +Dieses Projekt misst die **Stromaufnahme eines ESP32-C3** in verschiedenen Betriebszuständen mithilfe des **PowerProfiler Kit II** von Nordic Semiconductor. Das Ziel ist es, das Stromverbrauchsprofil des Mikrocontrollers unter verschiedenen Bedingungen (Deep Sleep, aktiv, mit/ohne WLAN) zu charakterisieren. + +--- + +## 1. Systemarchitektur + +``` +┌─────────────────────────────────────────────────────┐ +│ PowerProfiler Kit II (extern) │ +│ ┌─────────────────┬─────────────────┐ │ +│ │ Stromquelle │ Strommessung │ │ +│ │ (VDD) │ (Datenerfassung│ │ +│ └────────┬────────┴────────┬────────┘ │ +└──────────────┼────────────────┼───────────────────────┘ + │ │ + ↓ ↓ + ┌─────────────────────────────┐ + │ ESP32-C3 DevKit │ + │ │ + │ ┌───────────────────────┐ │ + │ │ Firmware (Arduino) │ │ + │ │ │ │ + │ │ • RTC-Memory │ │ + │ │ • Deep Sleep Timer │ │ + │ │ • GPIO/LED Control │ │ + │ │ • Serial Debug │ │ + │ └───────────────────────┘ │ + │ │ + └─────────────────────────────┘ + ↓ + ┌─────────────────────────────┐ + │ nRF Power Profiler App │ + │ (Windows/macOS/Linux) │ + │ → Grafische Messdaten │ + └─────────────────────────────┘ +``` + +--- + +## 2. Hardware-Verbindungen + +### PowerProfiler Kit II ↔ ESP32-C3 + +| PowerProfiler Signal | ESP32-C3 Pin | Funktion | +|:---|:---|:---| +| **GND** | GND | Masse | +| **VDD** | 5V / 3V3 | Stromversorgung | +| **USB (zur Host-PC)** | — | Datenübertragung & Kalibrierung | + +### ESP32-C3 GPIO (Optional) + +| GPIO | Funktion | Status | +|:---|:---|:---| +| **GPIO 2 (LED_BUILTIN)** | Status-LED | High = aktiv, Low = deep sleep | +| **GPIO 9 (RX)** | Externe Wakeup (optional) | Konfigurierbar in main.cpp | +| **GPIO 20 (TX) / GPIO 21 (RX)** | Serial Monitor (UART) | 115200 Baud | + +**Aktuelle Konfiguration**: Deep Sleep wird nur per Timer ausgelöst, GPIO-Wakeup ist optional. + +--- + +## 3. Firmware-Ausführungsfluss + +### Übersicht: Boot-Zyklus + +``` +┌─────────────────────────────────────────────────────┐ +│ Power-On Reset │ +│ oder RTC-Timer Wakeup │ +└────────────────────┬────────────────────────────────┘ + ↓ + ┌────────────────────────────┐ + │ setup() wird ausgeführt │ + │ (loop() läuft nie!) │ + └────────┬───────────────────┘ + ↓ + ┌─────────────────────────────────┐ + │ 1. Serial initialisieren │ + │ 2. bootCount++ (RTC-Speicher) │ + │ 3. Boot-Information ausgeben: │ + │ • Boot-Nummer │ + │ • Reset-Grund │ + │ • Aktuelle Cycle-Nr. │ + │ • WiFi-Status │ + └────────────┬────────────────────┘ + ↓ + ┌────────────────────────────┐ + │ LED einschalten (HIGH) │ + │ ACTIVE_DURATION_MS warten │ + │ (Standard: 5000ms = 5s) │ + └────────┬───────────────────┘ + ↓ + ┌──────────────────────────────────────┐ + │ 4. Cycle-Status ausgeben │ + │ 5. Sleep-Dauer ankündigen │ + │ 6. Serial-Buffer leeren (flush) │ + └──────────┬───────────────────────────┘ + ↓ + ┌──────────────────────────────────────┐ + │ esp_sleep_enable_timer_wakeup() │ + │ (SLEEP_DURATION_S * 1.000.000 µs) │ + │ Standard: 30 Sekunden │ + └──────────┬───────────────────────────┘ + ↓ + ┌──────────────────────────────────────┐ + │ LED ausschalten (LOW) │ + │ esp_deep_sleep_start() │ + │ → CPU-Halt, nur RTC läuft │ + └──────────┬───────────────────────────┘ + ↓ + [DEEP SLEEP] + Dauer: SLEEP_DURATION_S + Stromaufnahme: µA-Bereich + ↓ + ┌──────────────────────────────────────┐ + │ RTC-Timer läuft ab → Wakeup │ + │ Reset-Grund: DEEPSLEEP_RESET (Code) │ + │ bootCount bleibt erhalten │ + └──────────┬───────────────────────────┘ + ↓ + [Rückkehr zu setup()] + ← Der Zyklus beginnt von vorne +``` + +### Reset-Ursachen (esp_reset_cause) + +| Code | Bedeutung | Häufigkeit | +|:---|:---|:---| +| **1** | Power-On Reset | Einmalig beim Start | +| **5** | Deep Sleep Reset | Jeder Wakeup aus Timer | +| **6** | GPIO Reset (ext. Wakeup) | Nur mit GPIO-Konfiguration | + +**Wichtig**: Die Firmware prüft die Reset-Ursache, um zwischen erstem Boot und regelmäßigen Wakeups zu unterscheiden. + +--- + +## 4. Konfigurationsparameter + +Alle Einstellungen befinden sich in `include/config.h`: + +```c +// Zyklusparameter +#define SLEEP_DURATION_S 30 // Deep Sleep Dauer [Sekunden] +#define ACTIVE_DURATION_MS 5000 // Aktive Zeit [Millisekunden] +#define TOTAL_CYCLES 10 // Anzahl Messzyklen + +// WLAN-Parameter +#define WIFI_SSID "YOUR_SSID" +#define WIFI_PASSWORD "YOUR_PASSWORD" +#define WIFI_ENABLED_CYCLE_1 true // A/B-Test: Erste Messung MIT WLAN +#define WIFI_ENABLED_CYCLE_2 false // A/B-Test: Zweite Messung OHNE WLAN + +// Debug +#define SERIAL_DEBUG 1 // Serial-Output aktivieren +``` + +### Berechnete Werte + +``` +Gesamtdauer pro Zyklus = SLEEP_DURATION_S + (ACTIVE_DURATION_MS / 1000) + = 30 + 5 = 35 Sekunden (Beispiel) + +Gesamtmessdauer = TOTAL_CYCLES × Gesamtdauer pro Zyklus + = 10 × 35 = 350 Sekunden ≈ 5,8 Minuten +``` + +--- + +## 5. RTC-Memory (Datenpersistierung über Sleep) + +### Was ist RTC-Memory? + +RTC = **Real Time Clock**. Während Deep Sleep sind fast alle Komponenten des ESP32-C3 ausgeschaltet, aber der RTC-Timer läuft mit minimalem Stromverbrauch weiter. RTC-Memory behält seinen Zustand. + +### Verwendung im Projekt + +```cpp +RTC_DATA_ATTR uint32_t bootCount = 0; +``` + +- **RTC_DATA_ATTR**: Speichert die Variable in RTC-Memory +- **bootCount**: Wird bei jedem Boot inkrementiert, bleibt über Deep Sleep erhalten +- **Nutzen**: Tracking der Messvorgänge ohne externe Speicherung + +### Ablauf + +``` +Boot #1: bootCount=1, Deep Sleep 30s +Boot #2: bootCount=2 (erhalten!), Deep Sleep 30s +Boot #3: bootCount=3 (erhalten!), Deep Sleep 30s +... +Boot #10: bootCount=10, fertig +``` + +--- + +## 6. Serial-Debug-Output + +### Beispiel-Ausgabe + +``` +=== ESP32-C3 Power Measurement === +Boot #1 +Reset Reason: 5 +Cycle: 1/20 | WiFi: ON +Going to sleep for 30 seconds... + +=== ESP32-C3 Power Measurement === +Boot #2 +Reset Reason: 5 +Cycle: 2/20 | WiFi: OFF +Going to sleep for 30 seconds... + +[weitere Zyklen...] +``` + +### Ausgabe-Bedeutung + +| Feld | Erklärung | +|:---|:---| +| **Boot #X** | Seitwert seit Erstes Einschalten | +| **Reset Reason: 5** | DEEPSLEEP_RESET = regulärer Wakeup | +| **Cycle: X/20** | Aktuelle Messposition / Gesamtanzahl | +| **WiFi: ON/OFF** | A/B-Test-Status: Ist WLAN aktiviert? | + +### Serial-Monitoring + +**Voraussetzung**: ESP32-C3 per USB mit Computer verbunden (bleibt angesteckt während der Messung). + +```bash +# Terminal-Verbindung starten (115200 Baud) +pio device monitor -b 115200 + +# ESP32-spezifische Exception-Dekodierung +pio device monitor -b 115200 --filter=esp32_exception_decoder +``` + +Mit `Ctrl+C` beenden. + +--- + +## 7. Power-Measurement-Prozess + +### Physikalischer Ablauf + +``` +┌──────────────────────────────────────────┐ +│ nRF Power Profiler App öffnen (Host-PC) │ +└────────────┬─────────────────────────────┘ + ↓ +┌──────────────────────────────────────────┐ +│ PowerProfiler Kit II via USB anschließen│ +│ → Firmware kalibrieren & starten │ +└────────────┬─────────────────────────────┘ + ↓ +┌──────────────────────────────────────────┐ +│ ESP32-C3 per Micro-USB anschließen │ +│ (bleibt während Messung angesteckt) │ +└────────────┬─────────────────────────────┘ + ↓ +┌──────────────────────────────────────────┐ +│ Recording starten (PowerProfiler App) │ +│ → Profiler erfasst Stromkurve │ +└────────────┬─────────────────────────────┘ + ↓ +┌──────────────────────────────────────────┐ +│ Firmware hochladen (pio run -t upload) │ +│ → Firmware startet automatisch │ +└────────────┬─────────────────────────────┘ + ↓ +┌──────────────────────────────────────────┐ +│ Firmware läuft Zyklen (Stromzustandsändr.│ +│ → Power Profiler erfasst Daten │ +│ → Serial Monitor zeigt Milestones │ +└────────────┬─────────────────────────────┘ + ↓ +┌──────────────────────────────────────────┐ +│ Nach TOTAL_CYCLES: Gerät bleibt im │ +│ Deep Sleep (RTC Timer wartet) │ +│ → Recording stoppen │ +│ → Messungen exportieren/analysieren │ +└──────────────────────────────────────────┘ +``` + +### Messgröße und Genauigkeit + +- **PowerProfiler Kit II Genauigkeit**: µA-Bereich (Mikro-Ampere) +- **Samplingrate**: App-abhängig (typisch: 1 kHz oder mehr) +- **Zeitsynchronisation**: Serial-Output (Boot/Sleep-Ankündigung) korreliert mit Stromkurve +- **A/B-Test**: Vergleich Cycle 1 (WiFi-ON) vs. Cycle 2 (WiFi-OFF) zeigt WiFi-Stromverbrauch + +--- + +## 8. Erweiterungsmöglichkeiten + +### 1. WiFi-Aktivierung +```cpp +if (wifiEnabled) { + WiFi.begin(WIFI_SSID, WIFI_PASSWORD); + // Stromaufnahme während WiFi-Verbindung messen +} +``` + +### 2. BLE statt WiFi +```cpp +#include +// BLE-Beacon oder Scan für höhere Stromaufnahme als WiFi +``` + +### 3. GPIO-Trigger für genaue Timing +```cpp +// Pin 9 als Wakeup-Quelle statt nur Timer +esp_sleep_enable_ext0_wakeup(GPIO_NUM_9, 0); +``` + +### 4. Längere Messserien +Erhöhen Sie `TOTAL_CYCLES` für längere Messzeiten (z. B. 100 Zyklen = ~58 min bei 35s Periode). + +--- + +## 9. Troubleshooting + +| Problem | Ursache | Lösung | +|:---|:---|:---| +| Gerät startet nicht | Zu viel Strom beim Upload | PowerProfiler ausschalten, dann erneut hochladen | +| Keine Serial-Ausgabe | Falsche Baud-Rate | Auf 115200 Baud stellen | +| bootCount setzt sich zurück | Stromunterversorgung | PowerProfiler-Verbindung prüfen | +| Unerwartetes Wakeup | GPIO-Interferenz | GPIO-Wakeup deaktivieren | +| Stromzustandssprünge | WiFi-Activity | WIFI_ENABLED_CYCLE Flags prüfen | + +--- + +## 10. Zusammenfassung: Messprinzip + +1. **Setup**: PowerProfiler Kit II liefert Strom, nRF App erfasst Stromkurve +2. **Firmware-Laden**: Enthält Konfiguration (Sleep-/Wakeup-Parameter, WiFi-Flags) +3. **Boot-Zyklus**: Jeder Boot inkrementiert `bootCount`, wartet `ACTIVE_DURATION_MS`, schläft dann `SLEEP_DURATION_S` +4. **RTC-Memory**: Erhält `bootCount` über Sleep-Phasen +5. **Messdaten**: Stromkurve vom PowerProfiler + Serial-Milestones vom ESP32 → Korrelation = genaues Profil +6. **A/B-Test**: Erste Messung (WiFi-ON) vs. zweite Messung (WiFi-OFF) direkt vergleichbar + +--- + +## Dateien & Verzeichnisse + +``` +ESP32C3-ULP/ +├── src/ +│ └── main.cpp ← Hauptfirmware +├── include/ +│ └── config.h ← Alle Konfigurationsparameter +├── platformio.ini ← PlatformIO-Konfiguration +├── README.md ← Kurze Anleitung +├── CLAUDE.md ← Hinweise für Claude Code +└── docs/ + └── Info.md ← Diese Datei +``` + +--- + +**Version**: 1.0 +**Letztes Update**: 19.04.2026 +**Autor**: Projekt-Dokumentation diff --git a/include/config_example.h b/include/config_example.h new file mode 100644 index 0000000..a7f410d --- /dev/null +++ b/include/config_example.h @@ -0,0 +1,19 @@ +#ifndef CONFIG_H +#define CONFIG_H + +// Zyklusparameter +#define SLEEP_DURATION_S 30 // Deep Sleep Dauer in Sekunden +#define ACTIVE_DURATION_MS 5000 // Aktive Zeit in Millisekunden +#define TOTAL_CYCLES 10 // Gesamte Anzahl Zyklen + +// WLAN Parameter (kann per Schleife ändern) +// HINWEIS: Kopiere diese Datei zu config.h und trage deine echten Credentials ein! +#define WIFI_SSID "YOUR_SSID" +#define WIFI_PASSWORD "YOUR_PASSWORD" +#define WIFI_ENABLED_CYCLE_1 true // Erstes Experiment: WLAN aktiviert +#define WIFI_ENABLED_CYCLE_2 false // Zweites Experiment: WLAN deaktiviert + +// Debug Output +#define SERIAL_DEBUG 1 + +#endif diff --git a/src/main.cpp b/src/main.cpp index 525a3bb..9e052a3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -7,14 +7,16 @@ RTC_DATA_ATTR uint32_t bootCount = 0; void setup() { +#if SERIAL_DEBUG Serial.begin(115200); delay(500); - bootCount++; - Serial.println("\n\n=== ESP32-C3 Power Measurement ==="); Serial.printf("Boot #%lu\n", bootCount); - Serial.printf("Reset Reason: %d\n", esp_reset_cause()); + Serial.printf("Reset Reason: %d\n", esp_reset_reason()); +#endif + + bootCount++; // GPIO initialisieren (optional, für externe Trigger/Status-LED) pinMode(LED_BUILTIN, OUTPUT); @@ -27,12 +29,40 @@ void setup() { uint32_t currentCycle = (bootCount - 1) % (TOTAL_CYCLES * 2); bool wifiEnabled = (bootCount % 2 == 1) ? WIFI_ENABLED_CYCLE_1 : WIFI_ENABLED_CYCLE_2; +#if SERIAL_DEBUG Serial.printf("Cycle: %lu/%u | WiFi: %s\n", currentCycle + 1, TOTAL_CYCLES * 2, wifiEnabled ? "ON" : "OFF"); +#endif - // Vor Sleep: Statistiken ausgeben + // WiFi aktivieren falls konfiguriert + if (wifiEnabled) { + WiFi.mode(WIFI_STA); + WiFi.begin(WIFI_SSID, WIFI_PASSWORD); + uint8_t attempts = 0; + while (WiFi.status() != WL_CONNECTED && attempts < 20) { + delay(500); + attempts++; + } +#if SERIAL_DEBUG + Serial.printf("WiFi: %s\n", WiFi.status() == WL_CONNECTED ? "Connected" : "Failed"); +#endif + WiFi.disconnect(true); + WiFi.mode(WIFI_OFF); + } + +#if SERIAL_DEBUG Serial.printf("Going to sleep for %d seconds...\n", SLEEP_DURATION_S); Serial.flush(); +#endif + + // Nach allen Zyklen beenden + if (bootCount >= TOTAL_CYCLES * 2) { +#if SERIAL_DEBUG + Serial.println("Alle Zyklen abgeschlossen. Gerät bleibt wach."); + Serial.flush(); +#endif + while (true) { delay(1000); } + } // Deep Sleep mit Timer-Wakeup esp_sleep_enable_timer_wakeup(SLEEP_DURATION_S * 1000000ULL);