From 590e054d7d543c5e36b73bfd426de4a2e2915c90 Mon Sep 17 00:00:00 2001 From: clawdia Date: Mon, 10 Aug 2026 11:22:57 +0200 Subject: [PATCH 1/3] Initial commit --- README.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..d3e3f96 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# led-laser-frequenzen + +ESP32-C6 LED-Laser-Frequenzsteuerung für Rotlichttherapie mit WS2812B (30 LEDs) \ No newline at end of file From c14ec63b3888d013e09be686b0689a24d0096f5d Mon Sep 17 00:00:00 2001 From: clawdia Date: Mon, 10 Aug 2026 11:34:21 +0200 Subject: [PATCH 2/3] Add LED frequency control sketch for ESP32-C6 --- led-laser-frequenzen.ino | 224 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 224 insertions(+) create mode 100644 led-laser-frequenzen.ino diff --git a/led-laser-frequenzen.ino b/led-laser-frequenzen.ino new file mode 100644 index 0000000..7623142 --- /dev/null +++ b/led-laser-frequenzen.ino @@ -0,0 +1,224 @@ +/* + * LED-Laser-Frequenzsteuerung für Rotlichttherapie + * Ziel-Hardware: ESP32-C6 mit WS2812B LED-Streifen (30 LEDs) + * + * Funktion: Steuert 30 WS2812B-LEDs über verschiedene Frequenz-Presets + * die Rotlichttherapie nachbilden. Jedes Preset definiert Farbe, Helligkeit + * und Pulsfrequenz für photobiostimulation. + */ + +#include + +// ===== KONFIGURATION ===== +#define LED_PIN GPIO6 // Datenleitung zum WS2812B-Streifen +#define NUM_LEDS 30 // Anzahl LEDs im Streifen +#define DATA_RESISTOR 330 // Vorwiderstand in Ohm an der Datenleitung + +// ===== FREQUENZ-PRESETS ===== +// Jeder Preset definiert: Name, Grundfrequenz (Hz), Farbe (R,G,B), Helligkeit (0-255) +struct LaserPreset { + const char* name; + float frequencyHz; // Puls-Frequenz in Hz + uint8_t colorR; + uint8_t colorG; + uint8_t colorB; + uint8_t brightness; // 0-255, 255 = maximal + uint32_t durationMs; // Wie lange das Preset läuft (0 = unbegrenzt) +}; + +// Therapeutische Frequenzen für Rotlichttherapie (Peptide / Laser Therapy) +// Diese Frequenzen sind typisch für die Behandlung von Gewebe/Regeneration +const LaserPreset presets[] = { + // [0] Niedrigfrequenz - Entspannung & Regeneration + {"Regeneration", 40.0, 255, 15, 0, 200, 60000}, + + // [1] Mittelfrequenz - Durchblutung + {"Durchblutung", 60.0, 255, 30, 0, 255, 60000}, + + // [2] Hochfrequenz - Tiefenwirksam + {"Tiefenwirkung", 80.0, 255, 60, 0, 230, 45000}, + + // [3] Gepulst Rot - Geweberegeneration + {"Gepulst Rot", 50.0, 255, 0, 0, 180, 60000}, + + // [4] Warmes Rot-Orange - Oberflächliche Heilung + {"Oberflächenlicht", 30.0, 255, 80, 10, 210, 45000}, + + // [5] Infrarot-Nachbildung (tiefes Rot) - Muskeln & Gelenke + {"Muskeln/Gelenke", 65.0, 200, 10, 0, 240, 60000}, + + // [6] Wechselnd - Ganzkörperbehandlung + {"Ganzkörper", 45.0, 255, 0, 0, 190, 90000}, +}; + +#define NUM_PRESETS (sizeof(presets) / sizeof(presets[0])) + +// ===== GLOBAL STATE ===== +Adafruit_NeoPixel strip(NUM_LEDS, LED_PIN, NEO_GRB + NEO_KHZ800); + +uint8_t currentR = 0, currentG = 0, currentB = 0; +float currentBrightness = 0.0; +uint32_t pulsePhase = 0; +unsigned long lastPulseUpdate = 0; +unsigned long presetStartTime = 0; +int currentPresetIndex = -1; +bool running = false; + +// ===== SETUP ===== +void setup() { + Serial.begin(115200); + while (!Serial && millis() < 3000) {} + + strip.begin(); + strip.clear(); + strip.show(); + + // Starte mit erstem Preset + selectPreset(0); + + Serial.println("========================================"); + Serial.println(" LED-Laser-Frequenzsteuerung (ESP32-C6)"); + Serial.println(" WS2812B x 30 LEDs"); + Serial.println("========================================"); + printPresets(); + running = true; + + presetStartTime = millis(); +} + +// ===== LOOP ===== +void loop() { + if (!running) { + // Warte auf seriellen Befehl zum Neustart + if (Serial.available()) { + String cmd = Serial.readStringUntil('\n'); + handleCommand(cmd); + } + yield(); + return; + } + + const LaserPreset& preset = presets[currentPresetIndex]; + unsigned long now = millis(); + + // Prüfe ob Preset-Zeit abgelaufen (wenn durationMs > 0) + if (preset.durationMs > 0 && (now - presetStartTime) >= preset.durationMs) { + nextPreset(); + } + + // Berechne pulsende Helligkeit basierend auf Frequenz + calculatePulse(preset, now); + + // Update alle LEDs + uint32_t color = strip.Color( + (uint8_t)(currentR * currentBrightness / 255.0), + (uint8_t)(currentG * currentBrightness / 255.0), + (uint8_t)(currentB * currentBrightness / 255.0) + ); + + for (int i = 0; i < NUM_LEDS; i++) { + strip.setPixelColor(i, color); + } + strip.show(); + + // Seriellen Input prüfen für Befehle + if (Serial.available()) { + String cmd = Serial.readStringUntil('\n'); + handleCommand(cmd.trim()); + } + + yield(); +} + +// ===== PULSBERECHNUNG ===== +void calculatePulse(const LaserPreset& preset, unsigned long now) { + float dutyCycle = 0.5; // Standard: 50% Tastgrad + + // Sinusbasiertes Pulsieren für sanfte Übergänge + float periodMs = 1000.0 / preset.frequencyHz; + float phase = fmodf((float)(now % (uint32_t)periodMs), periodMs) / periodMs; + + // Sanfter An- und Abstieg + currentBrightness = (uint8_t)(preset.brightness * sinf(phase * 3.14159f)); +} + +// ===== PRESET SELEKTION ===== +void selectPreset(int index) { + if (index < 0 || index >= NUM_PRESETS) return; + + currentPresetIndex = index; + presetStartTime = millis(); + currentBrightness = 0.0; + + Serial.printf("\n>>> Preset: %s\n", presets[index].name); + Serial.printf(" Frequenz: %.1f Hz\n", presets[index].frequencyHz); + Serial.printf(" Farbe: R=%d, G=%d, B=%d\n", + presets[index].colorR, + presets[index].colorG, + presets[index].colorB); + Serial.printf(" Helligkeit: %d/255\n", presets[index].brightness); + if (presets[index].durationMs > 0) { + Serial.printf(" Dauer: %lu ms (%.1f min)\n", + presets[index].durationMs, + presets[index].durationMs / 60000.0); + } else { + Serial.println(" Dauer: unbegrenzt (⏹ zum Stoppen)"); + } +} + +void nextPreset() { + int next = (currentPresetIndex + 1) % NUM_PRESETS; + selectPreset(next); +} + +// ===== PRESETS DRUCKEN ===== +void printPresets() { + Serial.println("\nVerfügbare Presets:"); + for (int i = 0; i < NUM_PRESETS; i++) { + const char* durStr; + if (presets[i].durationMs > 0) { + durStr = ""; + } else { + durStr = " (⏹ stopp)"; + } + Serial.printf(" [%d] %s %.1fHz R:%d G:%d B:%d hell:%d - Zeit: %s\n", + i, + presets[i].name, + presets[i].frequencyHz, + presets[i].colorR, + presets[i].colorG, + presets[i].colorB, + presets[i].brightness, + durStr); + } +} + +// ===== SERIELLE BEFEHLE ===== +void handleCommand(String cmd) { + if (cmd.equalsIgnoreCase("stop")) { + running = false; + strip.clear(); + strip.show(); + Serial.println("LEDs ausgeschaltet. Serieller Befehl zum Neustart."); + return; + } + + if (cmd.equalsIgnoreCase("next")) { + nextPreset(); + return; + } + + if (cmd.equalsIgnoreCase("list") || cmd.equalsIgnoreCase("presets")) { + printPresets(); + return; + } + + // Number parsing: "0", "1", etc. → Preset-Index + int idx = cmd.toInt(); + if (idx >= 0 && idx < NUM_PRESETS) { + selectPreset(idx); + } else if (cmd.length() > 0 && !cmd[0].isdigit()) { + Serial.printf("Unbekannter Befehl: '%s'\n", cmd.c_str()); + Serial.println("Verfügbare Befehle: 0-6, stop, next, list"); + } +} From b64766ce9f8982a04740a7b0c8bf82ca125380f3 Mon Sep 17 00:00:00 2001 From: clawdia Date: Mon, 10 Aug 2026 11:35:18 +0200 Subject: [PATCH 3/3] Add PlatformIO config for ESP32-C6 + NeoPixel --- platformio.ini | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 platformio.ini diff --git a/platformio.ini b/platformio.ini new file mode 100644 index 0000000..09db261 --- /dev/null +++ b/platformio.ini @@ -0,0 +1,14 @@ +; PlatformIO Project Configuration File +; ESP32-C6 mit WS2812B LED-Streifen (30 LEDs) + +[env:esp32-c6-devkitc-1] +platform = espressif32 +board = esp32-c6-devkitc-1 +framework = arduino +monitor_speed = 115200 +lib_deps = + adafruit/Adafruit NeoPixel@^1.12.3 +build_flags = + -D LED_PIN=GPIO6 + -D NUM_LEDS=30 + -D WS2812B_SERIAL_SPEED=800000