ESP Webserver mit FastLED

Guten Abend,

bevor ich loslege, solltet Ihr wissen, dass ich der englischen Sprache nicht mächtig bin und auch keine Programmiersprache beherrsche. Ich habe lediglich vor vielen Jahren mal einen Elektroberuf erlernt. Meine bisherigen Bekanntschaften mit Arduinos, ESPs und Raspberrys gingen über das Basteln nicht hinaus. Und selbst das beschränkte sich auf Codeschnipsel so lange zusammen schmieden, bis es gelaufen ist.

Also ich möchte in/an meinem Gartenhaus ein Dachfenster motorisieren, innen und aussen die Temperatur messen und einen LED-Strip zum Leuchten bringen. Alle Steuerungen sollen über den Browser zu realisieren sein. Dazu habe ich mir einen ESP32 Dev Kit C V4, 2 Sensoren DS18B20 und einen WS2812B-Strip zugelegt.

Der 24V-Motor vom Dachfenster soll über 2 Relais angesteuert werden. Zusätzlich möchte ich über ein 3. Relais das Netzteil vom Strip zu- und abschalten können.

Zum Ansteuern der LEDs habe ich FastLED ausgewählt.
In dem Sketch habe ich 3 Animationen hinterlegt, die ich per Hand über den Browser starten möchte.

Die Relais- und Temperaturfunktionen sind soweit i.O.

Ich habe nur ein Problem damit, die Animationen zu starten. Im Moment ist es so, dass zwar mehrere LEDs angehen, aber keine Animation läuft.

Ich nehme an, dass dort irgendetwas mit dem Funktionsaufruf nicht stimmt.

Es wäre nett, wenn mir dahingehend jemand entgegen kommt.

Den kompletten Sketch kann ich leider nicht anhängen. Jetzt schon.

MfG Kurt

// Bibliotheken einbinden
#include <WiFi.h>
#include <ESPAsyncWebServer.h>
#include <SPIFFS.h>
#include <DallasTemperature.h>
#include <OneWire.h>
#include <FastLED.h>

// Zugangsdaten zum lokalen Netzwerk
const char* ssid = "********";
const char* password =  "********";

// Einstellungen für FastLED
#define NUM_LEDS 20
#define DATA_PIN 5
#define LED_TYPE WS2812B
#define COLOR_ORDER RGB
#define BRIGHTNESS 50

CRGB leds[NUM_LEDS];

// LED-Animationen einbinden
#include "MovingDot.h"
#include "RainbowBeat.h"
#include "RedWhiteBlue.h"

// Pins der Relais | relaisPin1 = Dachfenster auf | relaisPin2 = Dachfenster zu | relaisPin3 = Beleuchtung an/aus
const int relaisPin1 = 32;
const int relaisPin2 = 25;
const int relaisPin3 = 27;

// automatisches Ausschalten der Relais
unsigned long aktuelleZeit = 0;
const int laufzeit = 5000;

// Einstellungen für die DS18B20-Temperatursensoren
#define ONE_WIRE_BUS 4
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature tempSensoren(&oneWire);
uint8_t sensorInnen[8] = { 0x28, 0x66, 0x99, 0x75, 0xD0, 0xFF, 0x3C, 0x87  };
uint8_t sensorAussen[8] = { 0x28, 0x83, 0x9C, 0x75, 0xD0, 0x01, 0x3C, 0xD2  };
float tempSensorInnen;
float tempSensorAussen;

// Erzeuge einen AsyncWebServer auf Port 80
AsyncWebServer server(80);

// Ersetze Platzhalter
String processor(const String& var) {

  Serial.println(var);

  if (var == "TEMP_INNEN") {
    return String(tempSensorInnen);
  }

  else if (var == "TEMP_AUSSEN") {
    return String(tempSensorAussen);
  }

  return String();
}

void setup() {
  // Serieller Port für Ausgaben
  Serial.begin(115200);
  tempSensoren.begin();

  FastLED.addLeds<LED_TYPE, DATA_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
  FastLED.setBrightness(BRIGHTNESS);

  // Ausgänge festlegen
  pinMode(relaisPin1, OUTPUT);
  pinMode(relaisPin2, OUTPUT);
  pinMode(relaisPin3, OUTPUT);

  // SPIFFS initialisieren
  if (!SPIFFS.begin(true)) {
    Serial.println("An Error has occurred while mounting SPIFFS");
    return;
  }

  // Verbindung zum WLAN herstellen
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi..");
  }

  // Anzeigen der ESP-IP-Adresse im lokalen Netzwerk
  Serial.println(WiFi.localIP());

  // Route für Hauptseite (index.html)
  server.on("/", HTTP_GET, [](AsyncWebServerRequest * request) {
    request->send(SPIFFS, "/index.html", String(), false, processor);
  });

  // Route für das Icon
  server.on("/favicon.ico", HTTP_GET, [](AsyncWebServerRequest * request) {
    request->send(SPIFFS, "/favicon.ico", "image/x-icon");
  });

  // Route für effekte.html
  server.on("/effekte.html", HTTP_GET, [](AsyncWebServerRequest * request) {
    request->send(SPIFFS, "/effekte.html", String(), false, processor);
  });

  // Route für temperatur.html
  server.on("/temperatur.html", HTTP_GET, [](AsyncWebServerRequest * request) {
    request->send(SPIFFS, "/temperatur.html", String(), false, processor);
  });

  // Route für style.css
  server.on("/style.css", HTTP_GET, [](AsyncWebServerRequest * request) {
    request->send(SPIFFS, "/style.css", "text/css");
  });

  // Route für Relais 1 Dachfenster auf
  server.on("/df_auf", HTTP_GET, [](AsyncWebServerRequest * request) {
    digitalWrite(relaisPin2, LOW);
    digitalWrite(relaisPin1, HIGH);
    Serial.println("Dachfenster auf");
    aktuelleZeit = millis();
    request->send(SPIFFS, "/index.html", String(), false, processor);
  });

  // Route für Relais 1 & 2 Dachfenster stop
  server.on("/df_stop", HTTP_GET, [](AsyncWebServerRequest * request) {
    digitalWrite(relaisPin1, LOW);
    digitalWrite(relaisPin2, LOW);
    Serial.println("Dachfenster Stop");
    aktuelleZeit = 0;
    request->send(SPIFFS, "/index.html", String(), false, processor);
  });

  // Route für Relais 2 Dachfenster zu
  server.on("/df_zu", HTTP_GET, [](AsyncWebServerRequest * request) {
    digitalWrite(relaisPin1, LOW);
    digitalWrite(relaisPin2, HIGH);
    Serial.println("Dachfenster zu");
    aktuelleZeit = millis();
    request->send(SPIFFS, "/index.html", String(), false, processor);
  });

  // Route für Relais 3 Beleuchtung an
  server.on("/bel_an", HTTP_GET, [](AsyncWebServerRequest * request) {
    digitalWrite(relaisPin3, HIGH);
    Serial.println("Beleuchtung an");
    request->send(SPIFFS, "/index.html", String(), false, processor);
  });

  // Route für Relais 3 Beleuchtung aus
  server.on("/bel_aus", HTTP_GET, [](AsyncWebServerRequest * request) {
    digitalWrite(relaisPin3, LOW);
    Serial.println("Beleuchtung aus");
    request->send(SPIFFS, "/index.html", String(), false, processor);
  });

  // Route für LED-Animationen
  // alle LEDs aus
  server.on("/led_aus", HTTP_GET, [](AsyncWebServerRequest * request) {
    FastLED.clear();
    request->send(SPIFFS, "/effekte.html", String(), false, processor);
  });

  // MovingDot
  server.on("/mov", HTTP_GET, [](AsyncWebServerRequest * request) {
    movingDot();
    FastLED.show();
    request->send(SPIFFS, "/effekte.html", String(), false, processor);
  });

  // RainbowBeat
  server.on("/rai", HTTP_GET, [](AsyncWebServerRequest * request) {
    rainbowBeat();
    FastLED.show();
    request->send(SPIFFS, "/effekte.html", String(), false, processor);
  });

  // RedWhiteBlue
  server.on("/rwb", HTTP_GET, [](AsyncWebServerRequest * request) {
    redWhiteBlue();
    FastLED.show();
    request->send(SPIFFS, "/effekte.html", String(), false, processor);
  });

  // Serverstart
  server.begin();
}

void loop() {

  // Wenn Relais 1 angezogen hat, so schalte es nach der
  // programmierten Laufzeit wieder aus.
  if (digitalRead(relaisPin1) == HIGH) {
    if (millis() - aktuelleZeit >= laufzeit) {
      digitalWrite(relaisPin1, LOW);
    }
  }

  // Wenn Relais 2 angezogen hat, so schalte es nach der
  // programmierten Laufzeit wieder aus.
  else if (digitalRead(relaisPin2) == HIGH) {
    if (millis() - aktuelleZeit >= laufzeit) {
      digitalWrite(relaisPin2, LOW);
    }
  }

  // Temperatursensordaten auslesen
  tempSensoren.requestTemperatures();
  tempSensorInnen = tempSensoren.getTempC(sensorInnen);
  tempSensorAussen = tempSensoren.getTempC(sensorAussen);
}

Gartenhaus2.zip (6,3 KB)

Hallo,
also ich hab jetzt noch nicht ganz verstanden wie der Ablauf der Animation sein soll. Du fragst die Eingabe des Clients ab und rufst dann die function movingDot() auf. Irgendwie ist doch da noch ein zeitlicher Ablauf für nötig.
ich würde mit der Abfrage des clients jeweils eine Hilfsvariable setzen und die dann im loop abfragen und die entsprechende Animation movingDot() aufrufen. Dazu wird dann bestimmt noch was dazu gehören. Schließlich willst Du den Dot ja auch moven lassen. Meint da müssen dann ja in einem Zeitraster z.B die Position und Farbe der LED verändert werden. Üblicher Weise kann man das mit for... Schleifen über die Anzahl der LED´s , und mit einer zeitlichen Komponente außerhalb der for .. Schleife damit es nicht blokiert machen.

mach mal einen einfachen Sketch mit nur einer Animation so wie Du Dir das denkst. Da rufst Du im loop erst mal dann nur die eine Animation auf. Fast LED bietet dazu auch Funktionen für den zeitlichen Ablauf z.B sowas

loop(){
EVERY_N_MILLISECONDS(50) {
   movingDot();
    FastLED.show();
  }
}

Heinz

Hallo Heinz,

die MovingDot.h ist eingebunden.

#include "Arduino.h"

void movingDot() {

  uint16_t posBeat  = beatsin16(30, 0, NUM_LEDS - 1, 0, 0);
  uint16_t posBeat2 = beatsin16(60, 0, NUM_LEDS - 1, 0, 0);

  uint16_t posBeat3 = beatsin16(30, 0, NUM_LEDS - 1, 0, 32767);
  uint16_t posBeat4 = beatsin16(60, 0, NUM_LEDS - 1, 0, 32767);

  // Wave for LED color
  uint8_t colBeat  = beatsin8(45, 0, 255, 0, 0);

  leds[(posBeat + posBeat2) / 2]  = CHSV(colBeat, 255, 255);
  leds[(posBeat3 + posBeat4) / 2]  = CHSV(colBeat, 255, 255);

  fadeToBlackBy(leds, NUM_LEDS, 10);

//  FastLED.show();
}

Ich möchte diese Animation gern über einen Button im Webinterface aufrufen.
Dazu habe ich das eingebaut...

// MovingDot
  server.on("/mov", HTTP_GET, [](AsyncWebServerRequest * request) {
    movingDot();
    FastLED.show();
    request->send(SPIFFS, "/effekte.html", String(), false, processor);
  });

Anscheinend ist das falsch.

Wenn ich in der MovingDot.h

FastLED.show();

aktiviere und in den loop

movingDot();

setze, dann läuft die Animation direkt nach dem Booten des ESP.
Ich möchte sie aber nur über das Webinterface manuell schalten können.

mfG Kurt

Hallo,
ok und was hälst Du von einer Hilfsvariablen

server.on("/mov", HTTP_GET, [](AsyncWebServerRequest * request) {
    program=1;
  
    request->send(SPIFFS, "/effekte.html", String(), false, processor);
  });

und dann im loop

if (program==1){
  movingDot();
  }
else  if ( program==2){

  }
FastLED.show();

:pray: :+1:

Danke Heinz, das war es.