Skip to content

Absturz verschiedener ESP32, seit Version 3.2.0 + Fehlerhafte Ansteuerung von Neopixel #11259

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
1 task done
schneeer opened this issue Apr 18, 2025 · 6 comments
Closed
1 task done
Labels
Status: Awaiting triage Issue is waiting for triage

Comments

@schneeer
Copy link

schneeer commented Apr 18, 2025

Board

ESP32-D0WD-V3 (revision v3.1) = ESP32-S, Aber auch ESP32-WROOM...

Device Description

ESP32-S von AZ-Delivery,
montiert auf einer Lochstreifenplatine,
Über Pegelwandler ist ein Atmel328P angebunden, dieser empfängt Infrarot-Ferbedienungs-Befehle.
Zusätzlich gibt es einen Helligkeitssensor und ein Potentiometer.
Weiterhin sind mehrere Neopixel-LEDs angeschlossen.
Der ESP32 mit der restlichen Hardware und die Neopixel werden getrennt mit Spannung versorgt.
Alle Lötartbeiten wurden sorgfältig durchgeführt.

Tests habe ich auch mit einem ESP32 Dev Module ohne angeschlossene Hardware durchgeführt.

Hardware Configuration

(BuildinLED an 2)
Potentiometer an 36
Lichtsensor (Licht-Widerstand) an 39
Atmega328P am Hardware-I2C (als Empfänger für IR-Signale (Fernbedienung)) ESP32 ist Master
Atmega328P-Reset-Pin an 32 (als Hardware-Reset zu Atmega328P)
20x Neopixel an 16

Ist noch nicht fertig, sieht aber so aus:
Image

Version

v3.2.0

IDE Name

Arduino IDE 2.3.5 und 2.3.6 (2 verschiedene Notebooks)

Operating System

Windows 11 Pro

Flash frequency

80

PSRAM enabled

no

Upload speed

921600

Description

Mein ESP lief mehrere Monate fehlerfrei.
Ich habe verschiedene Sensoren angeschlossen und steuere aber hauptsächlich Neopixel an.
Zur Veränderung der Neopixel macht der ESP32 einen AP auf und es ist eine Webseite hinterlegt.
Bis Version 3.1.3 hatte ich keine Probleme.

  1. Der ESP32 steuert die Neopixel nicht mehr an, läuft aber sonst.
  2. Er läuft aber nur solange, wie nicht versucht wird sich per WLAN zum AP zu verbinden; beim Verbindungsversuch stürzt der ESP sofort ab.
    ein Zurückwechseln von 3.2.0 auf 3.1.3 beseitigt sofort alle Probleme.

Sketch

// Benötigte Bibliotheken
#include <Arduino.h>
#include <EEPROM.h> 
// I2C Bibliothek zur Kommunikation zwischen den Boards
#include <Wire.h>
//Wifi
#include <WiFi.h>
#include <WiFiClient.h>
#include <WebServer.h>
#include <ESPmDNS.h>
#include <Update.h>
// LED-Streifen-Bibliothek
#include <Adafruit_NeoPixel.h>

// EEPROM
int EEPROM_SIZE    = 118; //  Größe, int, da wir damit rechnen
// Adressen der einzelnen Variablen im Eeprom (Standartwerte, nicht verändern)
#define ssid_Adr         0  // SSID, 0 - 32 = 33 Byte, da 32 Zeichen eines Strings 1 Byte mehr im Eeprom brauchen
#define pass_Adr        33  // Passwort, 33 - 65 = 33 Byte, da 32 Zeichen eines Strings 1 Byte mehr im Eeprom brauchen
#define ip_Adr          66  // IP, 66 - 81 = 16 Byte, da 15 Zeichen eines Strings 1 Byte mehr im Eeprom brauchen
int Chk_Adr           = 82; // Prüfsumme der gespeicherten Einstellungen, int, da wir damit rechnen
#define Power_Adr       86  // Ein - Aus
#define Blink_Adr       90  // Blinklichtgeschwindigkeit
#define Pixel_Adr       94  // Lauflichthgeschwindigkeit
#define Bright_Adr      98  // Helligkeit
#define Mode_Adr       102  // Standart-Mode, aktiv nach dem Einschalten oder am nächsten Tag
#define Richtung_Adr   106  // Richtung des Lauflichts
#define Regler_Adr     110  // Benutzter Helligkeitsregler
#define Daemmerung_Adr 114  // Hinterlegte Dämmerung

#define BuildIn_LED 2      //  und zur Anzeige an der Onboard LED, das etwas über I2C kommt (IR-Befehle)
// wir benötigen mehrere Timer
unsigned long currentTime; // aktuelle Zeit aller Zähler
const unsigned long TimerLZ = 2000; // Intervall des Lebenszeichens
unsigned long startTimeLZ;   // Startzeit des Zählers
const unsigned long TimerSA = 10000; // Intervall der seriellen Ausgabe
unsigned long startTimeSA;   // Startzeit des Zählers

// Dämerung
#define PotiPin 36       // Anschluss des Potis
#define DaemmerungPin 39 // Anschluss des Fotowiderstandes
int Regler  =  0;  // 1 = Potentiometer, 2 = Schieberegler im Webinterface
// Schaltschwelle zur Dämmerungssteuerung
bool Schwelle = false;
// Toleranz, damit es bei entsprechender Dämmerung an der Schwelle "zu hell - dunkel genug" nicht flackert (entprellen)
int Tolleranz = 20;
int int_SensValue = 0; 

// Reset-Pin zum IR-IC
#define Resetpin 32 // Ein Reset des ESP 32 soll den IR- Chip mit resetten

//I2C
// ESP32 ist Master, Adresse am I2C-BUS
#define MasterAdresse 1
// kommende IR-Daten
byte addressIR;        // Typ des IR-Protokolls (Typ der FB)
byte commandIR;        // = Taste / Kommando der FB
byte flagIR;           // 0 = FB kurz gedrückt, 1 = FB länger gedrückt
// Zähler für Taste länger gedrückt, zum Speichern in den Eeprom
byte flagCounter = 0;  // zum Zählen, wie lange eine Taste der Fernbedienung gedrückt wird (einst. Laden / Speichern)
bool newIR = false;    // true wenn was kommt, zur Seriellen Ausgabe der Daten und für Onboard-LED

//Wifi
String host             = "ESP32_Lighthouse"; // teoretisch als Web-Adresse benutzbar, klappt aber nur wen ein DNS-Server verbunden ist (z.B. Fritz!Box)
String soft_ap_ssid     = ""; // aktuelle SSID, sofer sie aus dem Speicher geladen wurde
String soft_ap_pass = "";     // Passwort dazu
String soft_ap_ip       = ""; // IP-Adresse
// Die ersten Variablen für Server, Webseite... der Rest kommt im Setup
WebServer server(80); // Für Webseite Port 80 festlegen
String htmlResponse;  // Das ist / wird der (komplette) Inhalt der jeweiligen angezeigten Webseite

//gepackte Java Script Funktion für das OTA Web Update (System-Funktion: Datei öffnen ...)
/*
  jquery.min.js version 3.2.1
	size of original js file:  85 KB
	size in this source file: 148 KB
	size on ESP:               30 KB
 */

#define jquery_min_js_v3_2_1_gz_len 30178
PROGMEM const char jquery_min_js_v3_2_1_gz[]  = {
// Entfernt. Ist zu viel Code.
};

// Callback for the embedded jquery.min.js page
void onJavaScript(void) {
		server.setContentLength(jquery_min_js_v3_2_1_gz_len);
		server.sendHeader(F("Content-Encoding"), F("gzip"));
    server.send_P(200, "text/javascript", jquery_min_js_v3_2_1_gz, jquery_min_js_v3_2_1_gz_len);
}


// Power, Ein - Aus; erstmal auf Aus setzen
int Power = 0; 

// Programme
int Mode = 0;
  // 0 Kurz Aus (Stand-By bis zum nächsten Abend)
  // 1 Lauflicht
  // 2 Eizel-LED
  // 3 Blinker
  // 4 Ein
// maximale Anzahl der Programme
int MaxMode = 4; 
// zum Testen des Standartmode für nächste Start bei Mode 0 = Stand-By
int ModeTest = 0; 

// es laufen unter Umständen mehrere Schleifen ineinander,die länger dauern und die auf Tastendruck gestoppt werden müssen
bool PlayLauflicht1 = true;    // zum Anhalten/Starten per Play Taste
bool PlayLauflicht2 = true;    // zum Anhalten/Starten...
bool CancelLauflicht1 = false; // zum Abbrechen bei Mode-Wechsel
bool CancelLauflicht2 = false; // zum Abbrechen...
bool CancelBlinker1 = false;   // zum Abbrechen...
bool CancelBlinker2 = false;   // zum Abbrechen...

// für Lauflicht
int Richtung = 0;

// Für das IR-/ Web-Bestätigungsblinken
bool Blinken = false; // Steht in allen Schleifen/ Verzögerungen drin, da das auch bei langerdauernden Funktionen sofort Blinken soll
                      // wird bei Bedarf (IR- oder Web-Signal) true
// Farbe beim Bestätigen wenn ein FB-/ Web-Befehl kommt (wird unterwegs festgelegt)
byte rot   = 0;
byte gruen = 0;
byte blau  = 0;

// LED-Streifen
#define LED_PIN       16 // hier ist der Streifen angeschlossen
#define NUMPIXELS     20 // Anzahl der LEDs
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, LED_PIN, NEO_GRB + NEO_KHZ800); // Bibliothek starten
int  EinzelPixel1 =  9;  // Startposition der Einzelpixel (es leuchten immer 2)
int  EinzelPixel2 = 10;  // wie eben

// Zum Einstellen der Helligkeit ( Wert von 0-255) in 0 - 32 Stufen mit logarythmischer Korrektur 
int MaxHell = 32; // 0 - 32 = 33 Stufen

// Das empfinden der Helligkeit am Auge ist nicht linear, das korrigieren wir in einer passenden Tabelle mit 33 Stufen (0 - 32)
const byte pwmTable[33] = 
  {    1, 
       3,   6,  10,  14,  19,  24,  30,  36,  42,  49,
      56,  64,  71,  79,  87,  95, 104, 113, 122, 131, 
     140, 150, 159, 169, 180, 190, 200, 211, 222, 233,
     244, 255
  };

// Zum Einstellen der Geschwindigkeit Lauflicht und Blinker
int MaxSpeed =  32;       // 0 bis 32= 33 Stufen
// aktuelle Werte
int BlinkSpeed  = 0; // 0 - MaxSpeed; klein ist schnell !! Da das die Verzögerung in den Schleifen ist.
int PixelSpeed  = 0; // 0 - MaxSpeed; klein ist schnell !! Da das die Verzögerung in den Schleifen ist.
int StripBright = 0; // 0 - MaxHell; aktuelle Helligkeit am gesamten LED Streifen

// Beim Speichern zum Merken der Einstellungen benötigt, bedingt durch die Mehrfachbelegung der EQ-Taste
byte BlinkSpeedalt;
byte PixelSpeedalt;
byte StripBrightalt;

//Für Werksreset am seriellen Monitor  = "ja"
int char1 = 0;
int char2 = 0;
bool VarWerksreset = false;


// Durch User veränderliche Variablen
 // Helligkeit beim Bestätigen (0 - 255)
byte rotdefault    = 125;
byte gruendefault  = 125;
byte blaudefault   = 125;
byte orangedefault = gruendefault/2; // Wert für grün (mit rotdefault) ergibt orange 
// ein Teiler für blau, damit das eigentliche LED-Licht gelblicher wird
byte gelbkorr = 8 ;  // 0 = gelb, 1 (weiß) - 255 (gelb) teoretisch möglich

// Default Werte zum Wiederherstellen der Werkseinstellungen
String soft_ap_ssidDefault = "******************";
String soft_ap_passDefault = "******************";
String soft_ap_ipDefault   = "***.***.***.***";
byte PowerDefault       =  1; // Standardmäßig eingeschaltet
byte BlinkSpeedDefault  = 16; // 0 - MaxSpeed (32); klein ist schnell !!
byte PixelSpeedDefault  = 16; // 0 - MaxSpeed (32); klein ist schnell !!
byte StripBrightDefault = 16; // 0 - MaxHell (32)
byte ModeDefault        =  1; // Lauflicht
byte RichtungDefault    =  1; // für Lauflicht und Einzel-LED
byte ReglerDefault    =  1; // Externes Potentiometer ein
int int_SensValueDefault = 2048; // Hier eingegebene Werte müssen durch 64 teilbar sein! (0 - 4096) 2048 ist der Mittelwert (= 0) des Schiebereglers im Webinterface.

void setup()
  { 
    // Pin der internen (blauen) LED auf Ausgang
    pinMode(BuildIn_LED,OUTPUT);

    // Reset soll den IR-Empfänger beim Start mit resetten  
    pinMode(Resetpin, OUTPUT);
    digitalWrite(Resetpin, LOW);
    delay(10);
    digitalWrite(Resetpin, HIGH);
    // Damit der Pin hochohmig wird und den IR-Empfänger nicht blockiert, wenn der mal z.B. in einem Arduino UNO-Board  programmiert werden soll auf Eingang setzen
    // gedacht für echten Arduino, der ja USB hat und direkt programmiert werden kann. Mit einem einzelnen Atmel-Chip macht das wenig Sinn.
    pinMode(Resetpin, INPUT); 

    Serial.begin(115200); //Start der seriellen Schnittstelle für den Monitor, wird zwingend benötigt um eine neue /andere Fernbedienung zu analysieren
    delay(2000);          // der ESP32 hat eine Macke ab Werk, ohne Verzögerung gehen sonst die ersten Ausgben am Monitor verloren
    //Am seriellen Monitor "Hallo"  sagen
    Serial.println("");
    Serial.println("Systemstart ...");

    // Eeprom initialisieren
    while (!EEPROM.begin(EEPROM_SIZE))
      { true; }
    // Eeprom-Daten auslesen
    // und auf Gültigkeit prüfen
    EepromLesenAlles();
    EepromCheck();
    // die IP ist ein String, die müssen wir zum Verwenden in 4 Einzelteile zerlegen, das Macht die Funktion "getValue"
    int ip1 = getValue (soft_ap_ip,'.',0).toInt(); 
    int ip2 = getValue (soft_ap_ip,'.',1).toInt();
    int ip3 = getValue (soft_ap_ip,'.',2).toInt();
    int ip4 = getValue (soft_ap_ip,'.',3).toInt();
    // dun die betreffenden Variablen beschreiben
    IPAddress local_ip(ip1,ip2,ip3,ip4);
    IPAddress gateway(ip1,ip2,ip3,ip4);
    IPAddress subnet(255,255,255,0);

    // Der ESP hat die aktuellen IP-Einstellungen in einen separaten Speicher, müssen wir bei Bedarf löschen, damit neue Einstellungen funktionieren
    WiFi.disconnect(true, true); 

    // WLAN mit einen Access Point konfigurieren
    WiFi.mode(WIFI_AP);
    Serial.println("");
    Serial.println("Erstelle ESP32-Accesspoint");

    // Den Access Point aufmachen
    WiFi.softAPConfig(local_ip, gateway, subnet);
    WiFi.softAP(soft_ap_ssid, soft_ap_pass);  
    // MDNS zum Auflösen des Host Namens benutzen, Als AccessPoint unnötig, bringt mehr, wenn der ESP32 als WLAN Client läuft
    if (!MDNS.begin(host)) { 
        Serial.println("Fehler beim Einrichten des MDNS-Responders!");
        // bei Fehler kurz warten
        while (1) {
            delay(1000);
          }
      }
      else
      {
        Serial.println("mDNS-Responder gestartet");
      }
  
    // unsere Webseiten definieren: Bei welcher Webadresse dann die passende Funktion ausgeführt und damit die richtige Webseite angezeigt wird
    server.on("/", HTTP_GET, handleStartseite);
    server.on("/start", HTTP_GET, handleStartseite);
    server.on("/config", HTTP_GET, handleKonfiguration);
    server.on("/hilfe", HTTP_GET, handleHilfe);
    server.on("/werks_reset", HTTP_GET, handleWerksReset);
    server.on("/ap_settings", HTTP_GET, handleAP_Seite);
    server.on("/ap_save", HTTP_GET, handleAP_Safe_Form); 
    server.on("/web_update", HTTP_GET, handleUpdateseite);      // Hauptseite für Firmware Update
    server.on("/jquery.min.js", HTTP_GET, onJavaScript);        // return javascript jquery - für die Dateiauswahl beim Update
    server.on("/update", HTTP_POST, handleUpdate, handleUpload);// Ausführen des Uploads und Durchführung des Updates
    server.onNotFound(handle404Umleitung);                      // falls eine Falsche Adresse eingegeben wurde, auf die startseite umleiten
    
    //Web-Server starten
    server.begin();

    // Kommunikation über die I2C-Schnittstelle starten
    Wire.begin(MasterAdresse);    // I2C starten (Adresse (, Daten , Clock, Speed) )

    Wire.onReceive(IR_Auswerten); // erstellt ein Empfangen-Ereignis mit Angabe der auszuführenden Funktion zum Auswerten der empfangenen Signale
    delay(100);

    // LED-Streifen starten
    pixels.begin();
    
    // Alle Zähler auf "jetzt" setzen
    startTimeLZ = millis();    // Zähler für Lebenszeichen
    startTimeSA = millis();    // Zähler für serielle Ausgabe

    // und schon geht es los
    Serial.println("Beginne mit dem Betrieb"); // Setup ist endlich durch
    Serielle_AusgabeWerte(); // aktuelle Einstellungen ausgeben
  }


void loop()
  { 
    // ab und zu muss das eine oder andere getätigt werden, das rufen wir in allen längeren Schleifen, Funktionen  und auch jetzt in der Hauptschleife mal auf
    GelegentlicheAufgaben();

    if (Power == 0) //Wenn aus,
      {
        None();     //mache nichts
      }
    else           // Falls an
      { 
        if (Daemmerung_Ein() == false)  // Leider noch zu hell !!
          {
            // falls Stand By gewählt wurde vorsorglich Standard Werte Laden
            EepromLesenWerte();
            // falls Stand By gewählt wurde orsorglich Standard Mode Laden
            EEPROM.get(Mode_Adr, Mode);  
            None();             // mach' sonst (erstmal) nichts
          }
        else                    // Es ist dunkel. Perfekt. Tu was.
          {
            // Programm feststellen und ausführen
            if (Mode == 0)  
              { None(); }

            if (Mode == 1)
              { 
                if(Richtung == 0)
                  {
                    Lauflicht1();
                  }
                else
                  {
                    Lauflicht2();
                  }
              }

            if (Mode == 2)
              { Einzel(); }

            if (Mode == 3)
              { Blinker(); }

            if (Mode == 4)
              { Ein(); }
          }
      }
      // Das war es, zurück an den Anfang und von vorn...
};

void None()
{
  // es gibt immer etwas (außer der Reihe) zu tun
  GelegentlicheAufgaben();
  // erstmal alles ausknipsen (r, g, b), von, bis
  pixels.fill(pixels.Color(0, 0, 0), 0, NUMPIXELS);
  // und übernehmen
  pixels.show();
  // bissel bremsen, rennt sich sonst vieleicht tot.
  delay(200);
}


void Lauflicht1()
{
   // Schleife für jedes einzelne Pixel
   for (int a=0; a<NUMPIXELS; a++)
    { 
      // es gibt immer etwas (außer der Reihe) zu tun
      GelegentlicheAufgaben();
      // Falls ein Ereignis kommt (Fernbedienug oder Web-Befehl) unterbrechen
      if (CancelLauflicht1 == true)
        { CancelLauflicht1 = false;  
          CancelLauflicht2 = true;  
          a=NUMPIXELS; // Zähler auf größten Wert setzen
          break;
        }

      // Lauflicht gestoppt?
      if (PlayLauflicht1 == false )
        {
          a--; // Zähler des aktuellen Pixels für gestopptes Lauflicht konstant halten
          continue;
        }

      // Schleife für die Helligkeit am aktuellen Pixel
      for (int b=0; b<(StripBright+1); b++)
       {  // es gibt immer etwas (außer der Reihe) zu tun
          GelegentlicheAufgaben();
          // Falls ein Ereignis kommt (Fernbedienug oder Web-Befehl) unterbrechen
          if (CancelLauflicht2 == true)
           { 
            CancelLauflicht2 = false;
            a=NUMPIXELS;  // Zähler auf größten Wert setzen
            b=MaxHell+1; // Zähler auf größten Wert setzen
            break;
           }
          // Pause der Geschwindigkeit folgt am Ende in dieser Schleife, damit noch eine Anzeige kommt

          long aus = 0;

          int einr = pwmTable[StripBright];  // 255
          int eing = pwmTable[StripBright];  // 237
          int einb = pwmTable[StripBright]/gelbkorr;// 230
          if (einb<1)
            {einb=1;}
          //a_e Variable für jede Farbe anteigend von von aus nach ein mit der Schleife der Helligkeit für jedes Pixel verknüpfen
          long a_er = (pwmTable[0+b]);
          long a_eg = (pwmTable[0+b]);
          long a_eb = (pwmTable[0+b]/gelbkorr);
          if (a_eb<1)
            {a_eb=1;}

          //a_e Variable für jede Farbe abfallend von von ein nach aus mit der Schleife der Helligkeit für jedes Pixel verknüpfen
          long e_ar = (pwmTable[StripBright-b]);
          long e_ag = (pwmTable[StripBright-b]);
          long e_ab = (pwmTable[StripBright-b]/gelbkorr);
          if (e_ab<1)
            {e_ab=1;}

          // alle Pixel mit Position entsprechend der Schleife Position versehen
          int z0 =a+11; if (z0>NUMPIXELS-1) {z0= z0 - NUMPIXELS;}
          int z1 =a+12; if (z1>NUMPIXELS-1) {z1= z1 - NUMPIXELS;}
          int z2 =a+13; if (z2>NUMPIXELS-1) {z2= z2 - NUMPIXELS;}
          int z3 =a+14; if (z3>NUMPIXELS-1) {z3= z3 - NUMPIXELS;}
          int z4 =a+15; if (z4>NUMPIXELS-1) {z4= z4 - NUMPIXELS;}
          int z5 =a+16; if (z5>NUMPIXELS-1) {z5= z5 - NUMPIXELS;}
          int z6 =a+17; if (z6>NUMPIXELS-1) {z6= z6 - NUMPIXELS;}
          int z7 =a+18; if (z7>NUMPIXELS-1) {z7= z7 - NUMPIXELS;}
          int z8 =a+19; if (z8>NUMPIXELS-1) {z8 = z8 - NUMPIXELS;}
          int z9 =a; 
          int z10 =a+1; if (z10>NUMPIXELS-1) {z10= z10 - NUMPIXELS;}
          int z11 =a+2; if (z11>NUMPIXELS-1) {z11= z11 - NUMPIXELS;}
          int z12 =a+3; if (z12>NUMPIXELS-1) {z12= z12 - NUMPIXELS;}
          int z13 =a+4; if (z13>NUMPIXELS-1) {z13= z13 - NUMPIXELS;}
          int z14 =a+5; if (z14>NUMPIXELS-1) {z14= z14 - NUMPIXELS;}
          int z15 =a+6; if (z15>NUMPIXELS-1) {z15= z15 - NUMPIXELS;}
          int z16 =a+7; if (z16>NUMPIXELS-1) {z16= z16 - NUMPIXELS;}
          int z17 =a+8; if (z17>NUMPIXELS-1) {z17= z17 - NUMPIXELS;}
          int z18 =a+9; if (z18>NUMPIXELS-1) {z18= z18 - NUMPIXELS;}
          int z19 =a+10;if (z19>NUMPIXELS-1) {z19= z19 - NUMPIXELS;}

          // falls wir pausieren und / oder gleich zum Programm Einzelpixel wechseln, denen eine Position zuweisen
          if (b<= StripBright/2)
            { EinzelPixel1=z18;
              EinzelPixel2=z19; }
          else
            { EinzelPixel1=z19;
              EinzelPixel2=z0; }

          // aktuelle Helligkeit an jeder LED setzen 
          pixels.setPixelColor(z0, pixels.Color( a_er , a_eg , a_eb ));
          pixels.setPixelColor(z1, pixels.Color( aus , aus , aus ));
          pixels.setPixelColor(z2, pixels.Color( aus , aus , aus ));
          pixels.setPixelColor(z3, pixels.Color( aus , aus , aus ));
          pixels.setPixelColor(z4, pixels.Color( aus , aus , aus ));
          pixels.setPixelColor(z5, pixels.Color( aus , aus , aus ));
          pixels.setPixelColor(z6, pixels.Color( aus , aus , aus ));
          pixels.setPixelColor(z7, pixels.Color( aus , aus , aus ));
          pixels.setPixelColor(z8, pixels.Color( aus , aus , aus ));
          pixels.setPixelColor(z9, pixels.Color( aus , aus , aus ));
          pixels.setPixelColor(z10, pixels.Color( aus , aus , aus ));
          pixels.setPixelColor(z11, pixels.Color( aus , aus , aus ));
          pixels.setPixelColor(z12, pixels.Color( aus , aus , aus ));
          pixels.setPixelColor(z13, pixels.Color( aus , aus , aus ));
          pixels.setPixelColor(z14, pixels.Color( aus , aus , aus ));
          pixels.setPixelColor(z15, pixels.Color( aus , aus , aus ));
          pixels.setPixelColor(z16, pixels.Color( aus , aus , aus ));
          pixels.setPixelColor(z17, pixels.Color( aus , aus , aus ));
          pixels.setPixelColor(z18, pixels.Color( e_ar , e_ag , e_ab ));
          pixels.setPixelColor(z19, pixels.Color( einr , eing , einb ));
          pixels.show(); // This sends the updated pixel color to the hardware.

          // Lauflicht gestoppt?
          if (PlayLauflicht2==false)
            {
              b--; // Zähler der aktuellen Helligkeit konstant halten
              continue;
            }
         
          // Verzögerung für die Geschwindigkeit
          float delayer;
          // Je nach Helligkeit ist der Loop unterschiedlich schnell, die geringste Helligkeit ist 33 x schneller als höchste Helligkeit
          // Daher muss die Anzahl der Helligkeitstufen und die aktuelle Helligkeit einfließen
          // 0 sollte möglichst nicht heraus kommen
          // (ganz geschickt wäre das über einen extra!! Timer)
          delayer = ( ((MaxHell+1)*((PixelSpeed+1))) / (StripBright+1) ); 

          // jetziger Zeitpunkt
          long millisNow = millis(); 
          // Warte etwas
          while (millis() < millisNow + delayer) // Delay for a period of time (in milliseconds).
            {   
                // es gibt immer etwas (außer der Reihe) zu tun
                GelegentlicheAufgaben();
                // Falls ein Ereignis kommt (Fernbedienug oder Web-Befehl) unterbrechen
                if (CancelBlinker1 == true)
                   { CancelBlinker1 = false;  
                     break;
                   }
            }
        } 
    }
}


void Lauflicht2()
{  
  // Kommentare wie eben... sind hier nicht vollständig
   for (int a=NUMPIXELS-1; a>(-1); a--)
    { 
      GelegentlicheAufgaben();
      if (CancelLauflicht1 == true)
        { CancelLauflicht1 = false;  
          CancelLauflicht2 = true;  
          a=0; // Zähler auf größten Wert setzen
          break;
        }
      if (PlayLauflicht1 == false )
        {
          a++; // Zähler konstant halten
          continue;
        }

      for (int b=0; b<(StripBright+1); b++)
       {  
          GelegentlicheAufgaben();
          if (CancelLauflicht2 == true)
           { 
            CancelLauflicht2 = false;
            a=0;  // Zähler auf größten Wert setzen
            b=MaxHell+1; // Zähler auf größten Wert setzen
            break;
           }
          // Pause folgt am Ende in dieser Schleife, damit noch eine Anzeige kommt

          long aus = 0;

          int einr = pwmTable[StripBright];  // 255
          int eing = pwmTable[StripBright];  // 237
          int einb = pwmTable[StripBright]/gelbkorr;// 230
          if (einb<1)
            {einb=1;}

          long a_er = (pwmTable[0+b]);
          long a_eg = (pwmTable[0+b]);
          long a_eb = (pwmTable[0+b]/gelbkorr);
          if (a_eb<1)
            {a_eb=1;}

          long e_ar = (pwmTable[StripBright-b]);
          long e_ag = (pwmTable[StripBright-b]);
          long e_ab = (pwmTable[StripBright-b]/gelbkorr);
          if (e_ab<1)
            {e_ab=1;}

          int z0 =a-11; if (z0<0) {z0= z0 + NUMPIXELS;}
          int z1 =a-12; if (z1<0) {z1= z1 + NUMPIXELS;}
          int z2 =a-13; if (z2<0) {z2= z2 + NUMPIXELS;}
          int z3 =a-14; if (z3<0) {z3= z3 + NUMPIXELS;}
          int z4 =a-15; if (z4<0) {z4= z4 + NUMPIXELS;}
          int z5 =a-16; if (z5<0) {z5= z5 + NUMPIXELS;}
          int z6 =a-17; if (z6<0) {z6= z6 + NUMPIXELS;}
          int z7 =a-18; if (z7<0) {z7= z7 + NUMPIXELS;}
          int z8 =a-19; if (z8<0)  {z8 = z8 +NUMPIXELS;}
          int z9 =a;
          int z10 =a-1; if (z9<0)  {z9 = z9 +NUMPIXELS;}
          int z11 =a-2; if (z11<0) {z11= z11 +NUMPIXELS;}
          int z12 =a-3; if (z12<0) {z12= z12 +NUMPIXELS;}
          int z13 =a-4; if (z13<0) {z13= z13 +NUMPIXELS;}
          int z14 =a-5; if (z14<0) {z14= z14 +NUMPIXELS;}
          int z15 =a-6; if (z15<0) {z15= z15 +NUMPIXELS;}
          int z16 =a-7; if (z16<0) {z16= z16 +NUMPIXELS;}
          int z17 =a-8; if (z17<0) {z17= z17 +NUMPIXELS;}
          int z18 =a-9; if (z18<0) {z18= z18 +NUMPIXELS;}
          int z19 =a-10;if (z19<0) {z19= z19 +NUMPIXELS;}
          if (b<= StripBright/2)
            { EinzelPixel1=z18;
              EinzelPixel2=z19; }
          else
            { EinzelPixel1=z19;
              EinzelPixel2=z0; }
          pixels.setPixelColor(z0, pixels.Color( a_er , a_eg , a_eb ));
          pixels.setPixelColor(z1, pixels.Color( aus , aus , aus ));
          pixels.setPixelColor(z2, pixels.Color( aus , aus , aus ));
          pixels.setPixelColor(z3, pixels.Color( aus , aus , aus ));
          pixels.setPixelColor(z4, pixels.Color( aus , aus , aus ));
          pixels.setPixelColor(z5, pixels.Color( aus , aus , aus ));
          pixels.setPixelColor(z6, pixels.Color( aus , aus , aus ));
          pixels.setPixelColor(z7, pixels.Color( aus , aus , aus ));
          pixels.setPixelColor(z8, pixels.Color( aus , aus , aus ));
          pixels.setPixelColor(z9, pixels.Color( aus , aus , aus ));
          pixels.setPixelColor(z10, pixels.Color( aus , aus , aus ));
          pixels.setPixelColor(z11, pixels.Color( aus , aus , aus ));
          pixels.setPixelColor(z12, pixels.Color( aus , aus , aus ));
          pixels.setPixelColor(z13, pixels.Color( aus , aus , aus ));
          pixels.setPixelColor(z14, pixels.Color( aus , aus , aus ));
          pixels.setPixelColor(z15, pixels.Color( aus , aus , aus ));
          pixels.setPixelColor(z16, pixels.Color( aus , aus , aus ));
          pixels.setPixelColor(z17, pixels.Color( aus , aus , aus ));
          pixels.setPixelColor(z18, pixels.Color( e_ar , e_ag , e_ab ));
          pixels.setPixelColor(z19, pixels.Color( einr , eing , einb ));
          pixels.show(); // This sends the updated pixel color to the hardware.

          if (PlayLauflicht2==false)
            {
              b--; // Zähler konstant halten
              continue;
            }
         
          float delayer;
          // Je nach Helligkeit ist der Loop unterschiedlich schnell, die geringste Helligkeit ist 33 x schneller als höchste Helligkeit
          // Daher muss die Anzahl der Helligkeitstufen und die aktuelle Helligkeit einfließen
          // 0 sollte möglichst nicht heraus kommen
          delayer = ( ((MaxHell+1)*((PixelSpeed+1))) / (StripBright+1) ); 

          long millisNow = millis();
          while (millis() < millisNow + delayer) // Delay for a period of time (in milliseconds).
            {
              GelegentlicheAufgaben();
              if (CancelBlinker1 == true)
                { CancelBlinker1 = false;  
                  break;
                }
            }
        } 
    }
}


void Einzel()
{
    GelegentlicheAufgaben();
    pixels.clear(); // This sends the updated pixel color to the hardware
    int einr = pwmTable[StripBright];  // 255
    int eing = pwmTable[StripBright];  // 237
    int einb = pwmTable[StripBright]/gelbkorr;// 230
          if (einb<1)
            {einb=1;}
    pixels.setPixelColor(EinzelPixel1, pixels.Color(einr, eing, einb));
    pixels.setPixelColor(EinzelPixel2, pixels.Color(einr, eing, einb));
    pixels.show(); // This sends the updated pixel color to the hardware
    delay(100);
}


void Blinker()
{  
  // Einschalten
  // Helligkeit zuweisen
  int einr = pwmTable[StripBright];
  int eing = pwmTable[StripBright];
  int einb = pwmTable[StripBright]/gelbkorr;
  if (einb<1)
    {einb=1;}
  pixels.fill(pixels.Color(einr, eing, einb), 0, NUMPIXELS);
  pixels.show();
  // Verzögerung
  // sieht komplizierter aus als es ist,im Prinzip 20 Sekunden in 33 Teile gestückelt und wieder mit der Geschwindikeit multipliziert, darf nicht 0 sein, daher +1
  long DelayBlinker = ( 20000 - ((20000/33)*(33-(BlinkSpeed+1))) );
  long millisNow=millis();
  while (millis() < millisNow + DelayBlinker)// Delay for a period of time (in milliseconds).
    { 
      GelegentlicheAufgaben();
      // Falls was anderes gemacht werden soll
      if (CancelBlinker1 == true)
        { CancelBlinker1 = false;  
          CancelBlinker2 = true; 
        break;
        }
    }
  
  //Auschalten
  pixels.clear();
  pixels.fill(pixels.Color(0, 0, 0), 0, NUMPIXELS);
  pixels.show();
  // Verzögerung
  millisNow=millis();
  while (millis() < millisNow + DelayBlinker)// Delay for a period of time (in milliseconds).
    {
      GelegentlicheAufgaben();
      // Falls was anderes gemacht werden soll
      if (CancelBlinker2 == true)
        { CancelBlinker2 = false; 
          break;
        }
    }

}

void Ein()
{ 
  GelegentlicheAufgaben();
  int einr = pwmTable[StripBright];  // 255
  int eing = pwmTable[StripBright];  // 237
  int einb = pwmTable[StripBright]/gelbkorr;// 230
  if (einb<1)
   {einb=1;}
  pixels.fill(pixels.Color(einr, eing, einb), 0, NUMPIXELS);
  pixels.show();
  delay(100);
}

void IR_Auswerten(int anzahl) // Anzahl sind die  mit i2C übermittelten Bytes, Wird vom Protokoll mit übergeben
{ 
  /*
  Hier ist wichtig, dass diese Funktion nicht zu lange dauert!
  Das liegt daran, das der Wire-Aufruf, damit der Empfang der IR-Daten mittels Interrupt erfolgt.
  Der ESP32 macht irgendwann gnadenlos im Loop weiter und führt dann möglicherweise nicht alle Funktion bis zum Ande aus.
  Daher beschreiben wir hauptsächlich nur Variablen.
  Das Bestätigen per LED erfolgt in den Schleifen.
  Einzig das Lesen und Speichern vom Eeprom trauen wir uns teilweise noch zu.
  */

  bool UnbekanntesIR = true; // falls was kommt, was noch nicht bekannt ist, dammit die interne blaue LED blinkt, damit wir sehen, das doch ein IR-Signal ankam

  // lies die gesendeten Daten aus
  // mehr oder weniger als 3 Bytes? Es kommen vom IR Empfänger genau 3
  if (anzahl!=3) 
    {    
      while(Wire.available()){
      Wire.read();
    }	
    return;                     // schnell raus hier...
  }
  
  // Wenn etwas Gescheites dabei war, empfangene Daten den jeweiligen Variablen zuweisen
  if (Wire.available())
    {
      addressIR = Wire.read(); 
      if (Wire.available())
        {
          commandIR=Wire.read();
	        if (Wire.available())
            {
              flagIR=Wire.read();
              newIR = true;  
            }	
        }	
  }

  /*
  Joy-IT MP3-IR 
  Adresse      = 0x0

  NEC-Protokoll
  Power        = 0x45;
  Mode         = 0x46;
  Mute         = 0x47;
  Play_Pause   = 0x44;
  Skip_Back    = 0x40;
  Skip_Forward = 0x43;
  Equalizer    = 0x07;
  Minus        = 0x15;
  lus          = 0x09;
  0            = 0x16;
  Repeat       = 0x19;
  USB_SD       = 0x0D;  noch frei, falls vorhanden
  1            = 0x0C;
  2            = 0x18;
  3            = 0x5E;
  4            = 0x08;
  5            = 0x1C;
  6            = 0x5A;
  7            = 0x42;  noch frei
  8            = 0x52;
  9            = 0x4A;
  */

  if (addressIR == 0x0)
    {
    // Power ist halt für Ein und Aus, nur optisch aus, der ESP muss ja für die Fernbedienung und von der Webseite her erreichbar sein
    if (commandIR == 0x45 && flagIR == 0 )
      { 
        UnbekanntesIR = false;
        if (Power == 0)
          { PowerONsave(); }
        else
          { PowerOFFsave(); }
      }

    // Mode Programmweiterschaltung  (0) -> 1 -> 2 -> 3 -> 4 -> 1 ...
    if (commandIR == 0x46  && flagIR == 0 && Power == 1)
    { 
      UnbekanntesIR = false;
      Mode = Mode +1;      
      if (Mode > MaxMode)
        {Mode=1;}
      ModeChange(Mode);
    }


    // EQ Einstellung für Helligkeit UND die Geschwindigkeiten 
    if (commandIR == 0x07   && Mode != 0 && Power == 1)
    {
      UnbekanntesIR = false;
      if (flagIR == 0)
        {
          flagCounter = 0;
          BlinkSpeedalt = BlinkSpeed;
          PixelSpeedalt = PixelSpeed;
          StripBrightalt = StripBright;
          CancelLauflicht1 = true; 
          CancelLauflicht2 = true; 
          CancelBlinker1 = true; 
          CancelBlinker2 = true;  
          PlayLauflicht1 = true;
          PlayLauflicht2 = true;
          EepromLesenWerte();
            Blinken = true;
            rot   = 0;
            gruen = gruendefault;
            blau  = 0;
        }
      else
      {
       flagCounter = flagCounter + flagIR;
       if (flagCounter == 16)
        {
          CancelLauflicht1 = true; 
          CancelLauflicht2 = true; 
          CancelBlinker1 = true; 
          CancelBlinker2 = true;  
          PlayLauflicht1 = true;
          PlayLauflicht2 = true; 
          BlinkSpeed = BlinkSpeedalt;
          PixelSpeed = PixelSpeedalt;
          StripBright = StripBrightalt;
          EepromSchreibenWerte();
            Blinken = true;
            rot   = rotdefault;
            gruen = gruendefault;
            blau  = 0;
        }
       if (flagCounter == 32)
        {
          CancelLauflicht1 = true; 
          CancelLauflicht2 = true; 
          CancelBlinker1 = true; 
          CancelBlinker2 = true;  
          PlayLauflicht1 = true;
          PlayLauflicht2 = true;
          EepromSchreibenDefaults();
            Blinken = true;
            rot   = 0;
            gruen = 0;
            blau  = blaudefault;
        }
      }
    }

    // USB_SD
    if (commandIR == 0x0D && Mode != 0)
     { 
      UnbekanntesIR = true;
    }

    //Play/Pause für Lauflicht
    if (commandIR == 0x44 && flagIR == 0  && Mode != 0 && Power == 1)
     {
      UnbekanntesIR = false;
      if(Mode == 1)
        {
          TooglePlayPause();
        }
      if (Mode == 2)
        { 
          TooglePlayPause();
          Mode=1;
          PlayLauflicht1 = true;
          PlayLauflicht2 = true; 
        }
    }


    // Richtung (Repeat) für Lauflicht
    if (commandIR == 0x19 && Power == 1)
    {
      UnbekanntesIR = false;
      if (Mode == 1)
        {
          if ( flagIR == 0 )
            {
              ToogleRichtung();
            }
          else
            {
             flagCounter = flagCounter + flagIR;
              if (flagCounter == 16)
                {
                  CancelLauflicht1 = true; 
                  CancelLauflicht2 = true; 
                  RichtungSave(Richtung);
                }
            }   
        }
      if (Mode == 2)
        {
          Mode = 1;
          PlayLauflicht1 = true;
          PlayLauflicht2 = true;
          ModeChange(Mode); 
        }
      
    }

  
    // 0 Programm Stand-By bis zum nächsten Abend (Start dann mit allen Standarteinstellungen)
    if (commandIR == 0x16 && flagIR == 0  && Mode != 0 && Power == 1)
    {
      UnbekanntesIR = false;
      ModeChange(0);
    }


    // 1 Programm Lauflicht
    if (commandIR == 0x0C && Power == 1)
    {
      UnbekanntesIR = false;
      if (flagIR == 0)
        {
          ModeChange(1);
        }
      
      if (flagIR == 1 && Mode == 1)
        {
          if (Mode == 1)
            {
              flagCounter = flagCounter + flagIR;
              if (flagCounter == 16)
                {
                  Modesave(Mode);
                }
            }
        }
    }


    // 2 Programm Einzel-LED
    if (commandIR == 0x18 && Power == 1)
    {
      UnbekanntesIR = false;
      if (flagIR == 0)
        {
          ModeChange(2);
        }
      if (flagIR == 1 && Mode == 2)
        {
          flagCounter = flagCounter + flagIR;
          if (flagCounter == 16)
            {
                  Modesave(Mode);
            }
            
        }
    }


    // 3 Programm Blinker
    if (commandIR == 0x5E && Power == 1)
    {
      UnbekanntesIR = false;
      if (flagIR == 0)
        {
          ModeChange(3);
        }

      if (flagIR == 1 && Mode == 3)
        {
          flagCounter = flagCounter + flagIR;
          if (flagCounter == 16)
            {
                  Modesave(Mode);
            }           
        }
    }


    // 4 Programm alles Ein
    if (commandIR == 0x08 && Power == 1)
    {
      UnbekanntesIR = false;
      if (flagIR == 0 )
        {
          ModeChange(4);
        }

      if (flagIR == 1 && Mode == 4)
        {
          flagCounter = flagCounter + flagIR;
          if (flagCounter == 16)
            {
                  Modesave(Mode);
            }
        }
    }
    

    // 5 = Minimalste Geschwindigkeit
    if (commandIR == 0x1C && flagIR == 0 && Mode != 0 && Power == 1)
    {    
      UnbekanntesIR = false; 
        if (Mode == 1)
          {  
            if (PixelSpeed == MaxSpeed)
             {
                LedMaxMinErreicht();
             }
            else
              {
                PixelSpeed = MaxSpeed;
                LedChange();
              }
          }

        if (Mode == 3)
          {
            if (BlinkSpeed == MaxSpeed)
             {
                LedMaxMinErreicht();
             }
            else
              {
                BlinkSpeed = MaxSpeed;
                LedChange();
              }
          }
    }


    // 6 = maximalste Geschwindigkeit
    if (commandIR == 0x5A && flagIR == 0 && Mode != 0 && Power == 1)
    {   
      UnbekanntesIR = false;
        if (Mode == 1)
          { 
            if (PixelSpeed == 0)
             {
                LedMaxMinErreicht();
             }
            else
              {
                PixelSpeed = 0;
                LedChange();
              }
          }

        if (Mode == 3)
          { 
            if (BlinkSpeed == 0)
              {
                LedMaxMinErreicht();
              }
            else
              {
                BlinkSpeed = 0;
                LedChange();
              }
          }
    }


    // 7
    if (commandIR == 0x42 && Mode != 0)
     { 
      UnbekanntesIR = true;
     }


    // 8
    if (commandIR == 0x52 && flagIR == 0 && Mode != 0 && Power == 1)
    {
      UnbekanntesIR = false;
        if (StripBright == 0)
          {
            LedMaxMinErreicht();
          }
        else
          {
            StripBright = 0;
            LedChange();
          }
    }
 

    // 9
    if (commandIR == 0x4A && flagIR == 0 && Mode != 0 && Power == 1)
    {
      UnbekanntesIR = false;
        if (StripBright == MaxHell)
          {
            LedMaxMinErreicht();
          }
        else
          {
            StripBright = MaxHell;
            LedChange();
          }
    }


    // >> (Forward)
    if (commandIR == 0x43 && PlayLauflicht1 == true && Mode != 0 && Power == 1)
    { 
      UnbekanntesIR = false;
      if(Mode == 1)
        {LedSpeedPlus();
        }
        
      if(Mode == 2)
        {EinzelPositionPlus();
        }

      if(Mode == 3)
        {BlinkerSpeedPlus();
        }
    }


    // << (Back)
    if (commandIR == 0x40 && PlayLauflicht1 == true && Mode != 0 && Power == 1)
    { 
      UnbekanntesIR = false;
      if(Mode == 1)
      {LedSpeedMinus();
      }

      if(Mode == 2)
      {EinzelPositionMinus();
      }

      if(Mode == 3)
      {
        BlinkerSpeedMinus();
      } 
    }


    // Minus
    if (commandIR == 0x15  && Mode != 0 && Power == 1) 
    { 
      UnbekanntesIR = false;
      LedHellMinus();
    } 

    // Plus
    if (commandIR == 0x09  && Mode != 0 && Power == 1)
    {
      UnbekanntesIR = false;
      LedHellPlus();
    }
  }


  if (UnbekanntesIR == true)
  { // (nur) Blinken der eingebauten blauen LED
    BestaetigenUnbekanntIR();
  }
}

void EepromLesenWerte()
{
  EEPROM.get(Bright_Adr, StripBright);
  EEPROM.get(Pixel_Adr, PixelSpeed);
  EEPROM.get(Blink_Adr, BlinkSpeed);
}

void EepromLesenAlles()
{
  soft_ap_ssid = readStringFromEEPROM(ssid_Adr);
  soft_ap_pass = readStringFromEEPROM(pass_Adr);
  soft_ap_ip   = readStringFromEEPROM(ip_Adr);
  EEPROM.get(Power_Adr, Power);
  EepromLesenWerte();
  EEPROM.get(Mode_Adr, Mode);
  EEPROM.get(Richtung_Adr, Richtung);
  EEPROM.get(Regler_Adr, Regler);
  EEPROM.get(Daemmerung_Adr, int_SensValue);
}


void PowerONsave()
  {
            Power = 1;
            EepromSchreibenPower();
            EepromLesenAlles();
            PlayLauflicht1 = true;
            PlayLauflicht2 = true; 
            Blinken = true;
            rot   = 0;
            gruen = gruendefault;
            blau  = 0;
}
void PowerOFFsave()
  {
            Power = 0;
            EepromSchreibenPower();
            CancelLauflicht1 = true; 
            CancelLauflicht2 = true;  
            CancelBlinker1 = true;  
            CancelBlinker2 = true; 
            Blinken = true;
            rot   = rotdefault;
            gruen = 0;
            blau  = 0;
}
void EepromSchreibenPower()
  {
    EEPROM.put(Power_Adr, Power);
   Eeprom_Quersumme_Commit();
}


void Modesave(int Data)
 {
    EepromSchreibenMode(Data);
    Blinken = true;
    rot   = rotdefault;
    gruen = gruendefault;
    blau  = 0;
} 
void EepromSchreibenMode(int Data)
  {
    EEPROM.put(Mode_Adr, Data);
    Eeprom_Quersumme_Commit();
}


void DaemerungModesave(int Data)
  {
    EEPROM.put(Regler_Adr, Data);
    Eeprom_Quersumme_Commit();
    Blinken = true;
    rot   = rotdefault;
    gruen = gruendefault;
    blau  = 0;
}


void Daemerungsave(int Data)
  {
    EEPROM.put(Daemmerung_Adr, (4096/2)-(Data*64));
    Eeprom_Quersumme_Commit();
    Blinken = true;
    rot   = rotdefault;
    gruen = gruendefault;
    blau  = 0;
}


void RichtungSave(int Data)
  {
    EepromSchreibenRichtung(Data);
    Blinken = true;
    rot   = rotdefault;
    gruen = gruendefault;
    blau  = 0;
} 
void EepromSchreibenRichtung(int Data)
 {
  EEPROM.put(Richtung_Adr, Data);
  Eeprom_Quersumme_Commit();
}

void EepromSchreibenWerte() // nur Fernbedienung
{
  EEPROM.put(Bright_Adr, StripBright);
  EEPROM.put(Pixel_Adr, PixelSpeed);
  EEPROM.put(Blink_Adr, BlinkSpeed);
  Eeprom_Quersumme_Commit();
}


 void Hellsave(int Data)
  {
    EepromSchreibenStripBright(Data);
    Blinken = true;
    rot   = rotdefault;
    gruen = gruendefault;
    blau  = 0;
} 
void EepromSchreibenStripBright(int Data)
{
  EEPROM.put(Bright_Adr, Data);
  Eeprom_Quersumme_Commit();
}


 void BlinkerSpeedsave(int Data)
  {
    EepromSchreibenBlinkerSpeed(Data);
    Blinken = true;
    rot   = rotdefault;
    gruen = gruendefault;
    blau  = 0;
} 
void EepromSchreibenBlinkerSpeed(int Data)
{
  EEPROM.put(Blink_Adr, Data);
  Eeprom_Quersumme_Commit();
}


 void PixelSpeedsave(int Data)
  {
    EepromSchreibenPixelSpeed(Data);
    Blinken = true;
    rot   = rotdefault;
    gruen = gruendefault;
    blau  = 0;
} 
void EepromSchreibenPixelSpeed(int Data)
{
  EEPROM.put(Pixel_Adr, Data);
  Eeprom_Quersumme_Commit();
}


void EepromSchreibenIP()
{
    writeStringToEEPROM(ssid_Adr, soft_ap_ssid);
    writeStringToEEPROM(pass_Adr, soft_ap_pass);
    writeStringToEEPROM(ip_Adr, soft_ap_ip);
    Eeprom_Quersumme_Commit();
}

void EepromSchreibenAlles()
{
  writeStringToEEPROM(ssid_Adr, soft_ap_ssid);
  writeStringToEEPROM(pass_Adr, soft_ap_pass);
  writeStringToEEPROM(ip_Adr, soft_ap_ip);
  EEPROM.put(Power_Adr, Power);
  EEPROM.put(Blink_Adr, BlinkSpeed);
  EEPROM.put(Pixel_Adr, PixelSpeed);
  EEPROM.put(Bright_Adr, StripBright);
  EEPROM.put(Mode_Adr, Mode);
  EEPROM.put(Richtung_Adr, Richtung);
  EEPROM.put(Regler_Adr, Regler);
  EEPROM.put(Daemmerung_Adr, int_SensValue);
  Eeprom_Quersumme_Commit();
}

void EepromSchreibenDefaults()
{
  soft_ap_ssid  = soft_ap_ssidDefault;
  soft_ap_pass  = soft_ap_passDefault;
  soft_ap_ip    = soft_ap_ipDefault;
  Power         = PowerDefault;
  BlinkSpeed    = BlinkSpeedDefault;
  PixelSpeed    = PixelSpeedDefault;
  StripBright   = StripBrightDefault;
  Mode          = ModeDefault;
  Richtung      = RichtungDefault;
  Regler        = ReglerDefault;
  int_SensValue = int_SensValueDefault;
  EepromSchreibenAlles(); 
}

void writeStringToEEPROM(int addrOffset, const String &strToWrite)
{
  byte len = strToWrite.length();
  EEPROM.write(addrOffset, len);
  for (int i = 0; i < len; i++)
  {
    EEPROM.write(addrOffset + 1 + i, strToWrite[i]);
  }
}

String readStringFromEEPROM(int addrOffset)
{
  int newStrLen = EEPROM.read(addrOffset);
  char data[newStrLen + 1];
  for (int i = 0; i < newStrLen; i++)
  {
    data[i] = EEPROM.read(addrOffset + 1 + i);
  }
  data[newStrLen] = '\0';
  return String(data);
}

void EepromCheck()
{
  // Eeprom-Daten auf Gültigkeit prüfen
  Serial.print("Lese abgespeicherte Checksumme: ");
  int CheckEE;
  EEPROM.get(Chk_Adr, CheckEE);
  Serial.println(CheckEE);
  Serial.print("Lese alle Einstellungen und berechne Checksumme: ");
  int EEdata = QuerSumm_Calc_Read();
  Serial.println(EEdata);
  //Quersumme vergleichen
  if (EEdata > 0 && EEdata == CheckEE)
    {
      Serial.print("Checksummen stimmen überein, ");
      Serial.println("Eeprom OK"); 
    }
  else
    { 
      Serial.print("Checksummen sind nicht gleich, ");
      Serial.println("Eeprom Fehler"); 
      EepromSchreibenDefaults();
      Serial.println("Eeprom wurde wiederhergestellt");
    }
}

int QuerSumm_Calc_Read()
{
  int EEchk  = 0;
  int EEdata = 0;
  //  Checksumme für die IP-Werte anpassen
  for(int i = 0; i < readStringFromEEPROM(ssid_Adr).length(); i++)
    { EEchk  += (int) readStringFromEEPROM(ssid_Adr).charAt(i); }
  for(int i = 0; i < readStringFromEEPROM(pass_Adr).length(); i++)
    { EEchk  += (int) readStringFromEEPROM(pass_Adr).charAt(i); }
  for(int i = 0; i < readStringFromEEPROM(ip_Adr).length(); i++)
    { EEchk  += (int) readStringFromEEPROM(ip_Adr).charAt(i); }
  //  Checksumme für die Lichtwerte anpassen
  for (int i = (Chk_Adr+4); i < EEPROM_SIZE; i=i+4)
    {
      EEPROM.get(i, EEdata);
      EEchk  += EEdata;
    }   
  return EEchk;
}

void Eeprom_Quersumme_Commit()
{ //Quersumme
  Serial.println("Eeprom Daten wurden geändert."); 
  Serial.print("Berechne Checksumme: ");    
  int chk_EE = QuerSumm_Calc_Read();
  Serial.println(chk_EE);
  EEPROM.put(Chk_Adr, chk_EE);  // Checksumme
  EEPROM. commit ();
  Serial.println("Eeprom Daten wurden gespeichert."); 
}
void GelegentlicheAufgaben()
 {
  yield();               // der ESP benötigt Zeit für die Webseite und Wifi, die geben wir ihm hier
  server.handleClient(); // zum bevorzugten Behandeln der Web-Clienten
  Seriell_Abfragen();    // Schauen, ob etwas per Tastatur über den Monitor rein kommt

  if (newIR == true)     // falls was per I2C von der Fernbedienung kam
    {
      newIR = false;
      Serielle_AusgabeIR();
      commandIR = 0;
    }

  if (Blinken == true)    // Wenn angefordert, zum Bestätigen blinken
    {
      Bestaetigen(rot,gruen,blau);
    }
  
  currentTime = millis();
  // Die interne LED rythmisch blinken lassen
  if ( currentTime >= (startTimeLZ + TimerLZ) )
    {
        digitalWrite(BuildIn_LED,HIGH);
        delay(50);       
        digitalWrite(BuildIn_LED,LOW);
        startTimeLZ = currentTime;
    }

  // Gelegentlich seriell Ausgeben
  if ( currentTime >= (startTimeSA + TimerSA) )
    {
        Serielle_AusgabeWerte();
        startTimeSA = currentTime;
    }
}

bool Daemmerung_Ein()
 {  

    if (Regler  ==  1)
    {
      if ( float( 4095-analogRead(DaemmerungPin))<float(analogRead(PotiPin)-Tolleranz ) )
        {Schwelle = true;}
      if ( float( 4095-analogRead(DaemmerungPin))>float(analogRead(PotiPin)+Tolleranz ) )
        {Schwelle = false;}
    }
    else
    {
      int GespeicherterWert      = 0; EEPROM.get(Daemmerung_Adr,   GespeicherterWert);
      if ( float( 4096-analogRead(DaemmerungPin))< (4096-GespeicherterWert)-Tolleranz )
        {Schwelle = true;}
      if ( float(  4096-analogRead(DaemmerungPin))> (4096-GespeicherterWert)+Tolleranz )
        {Schwelle = false;}
    }
    return Schwelle;
}


// String zerlegen; z.B. gespeicherte IP-Adresse
String getValue(String data, char separator, int index)   // Token String
 {
    int found = 0;
    int strIndex[] = { 0, -1 };
    int maxIndex = data.length() - 1;

    for (int i = 0; i <= maxIndex && found <= index; i++) {
        if (data.charAt(i) == separator || i == maxIndex) {
            found++;
            strIndex[0] = strIndex[1] + 1;
            strIndex[1] = (i == maxIndex) ? i+1 : i;
        }
    }
    return found > index ? data.substring(strIndex[0], strIndex[1]) : "";
}

void BestaetigenUnbekanntIR() // (nur) Blinken der eingebauten LED
 {
  Blinken = false;
  byte PauseOn =20;
  byte PauseOff =35;
  // 5x Blinken
  for (int i = 0; i < 5; i++)
    {
      digitalWrite(BuildIn_LED,HIGH);
      delay(PauseOff);
      digitalWrite(BuildIn_LED,LOW);
      delay(PauseOn);
    }
}

void Bestaetigen(byte Rot, byte Gruen, byte Blau)
 { 
  Blinken = false;
  byte PauseOn =20;
  byte PauseOff =35;
  // 5x Blinken der eingebauten LED und aller Pixel in irgendeiner Farbe 
  for (int i = 0; i < 5; i++)
    {
      pixels.clear();
      pixels.fill(pixels.Color(0, 0, 0), 0, NUMPIXELS);
      pixels.show();
      digitalWrite(BuildIn_LED,HIGH);
      delay(PauseOff);
      pixels.clear();
      pixels.fill(pixels.Color(Rot, Gruen, Blau), 0, NUMPIXELS);
      pixels.show();
      digitalWrite(BuildIn_LED,LOW);
      delay(PauseOn);
    }
  pixels.clear();
  pixels.fill(pixels.Color(0, 0, 0), 0, NUMPIXELS);
  pixels.show();
  delay(PauseOff);
}

void LedChange()
  {
        CancelBlinker1 = true; 
        CancelBlinker2 = true;
        Blinken = true;
        rot   = 0;
        gruen = gruendefault;
        blau  = 0;
}

void LedMaxMinErreicht()
  {
        CancelBlinker1 = true; 
        CancelBlinker2 = true; 
        Blinken = true;
        rot   = rotdefault;
        gruen = orangedefault;
        blau  = 0;
}







void ModeChange(int Data)
  {
          flagCounter = 0;
          CancelLauflicht1 = true; 
          CancelLauflicht2 = true; 
          CancelBlinker1 = true; 
          CancelBlinker2 = true;
          Mode = Data;  
          PlayLauflicht1 = true;
          PlayLauflicht2 = true;  
          Blinken = true;
          if (Mode == 0)
            {
              rot   = rotdefault;
              gruen = 0;
              blau  = blaudefault;
            }
          else
            {
              rot   = 0;
              gruen = gruendefault;
              blau  = 0;
            }
}

void LedHellPlus()
  {
    StripBright = StripBright + 1;
    if(StripBright >MaxHell)
      {
        StripBright = MaxHell;
        LedMaxMinErreicht();
      }
    else
      {
        if (flagIR !=1)
          {
            LedChange();
           }
      }
}

void LedHellMinus()
  {
    StripBright = StripBright - 1;
    if(StripBright < 0)
      { 
        StripBright = 0;
        LedMaxMinErreicht();
      }
    else
      {
        if (flagIR !=1)
          {
            LedChange();
          }
      }
}

void LedSpeedPlus()
  {
          PixelSpeed = PixelSpeed -1;
          if(PixelSpeed < 0)
            { 
              PixelSpeed = 0;
              LedMaxMinErreicht();
            }
          else
            {
              if (flagIR !=1)
                { 
                  LedChange();
                }
            }
}

void LedSpeedMinus()
  {
        PixelSpeed = PixelSpeed +1;
        if(PixelSpeed > MaxSpeed)
        { 
          PixelSpeed = MaxSpeed;
        LedMaxMinErreicht();
        }
        else
        {
        if (flagIR !=1)
          {
             LedChange();
          }
        }
}

void TooglePlayPause()
   {
          PlayLauflicht1 = !PlayLauflicht1;
          PlayLauflicht2 = PlayLauflicht1;
          Blinken = true;
          rot   = 0;
          gruen = gruendefault;
          blau  = 0;
}

void ToogleRichtung()
  {
              PlayLauflicht1 = true;
              PlayLauflicht2 = true;
              if (Richtung == 1)
                {Richtung  = 0;}
              else
                {Richtung  = 1;}
             ModeChange(Mode);
}

void EinzelPositionPlus()
  {
        EinzelPixel1 = EinzelPixel1+1;
        if(EinzelPixel1 == NUMPIXELS)
          {EinzelPixel1=0;
          }
        EinzelPixel2 = EinzelPixel2+1;
        if(EinzelPixel2 == NUMPIXELS)
          {EinzelPixel2=0;
          }
        if (flagIR ==0)
          { LedChange();
          }
}

void EinzelPositionMinus()
  {
        EinzelPixel1 = EinzelPixel1-1;
        if(EinzelPixel1 <0)
          {EinzelPixel1= NUMPIXELS-1;
          }
        EinzelPixel2 = EinzelPixel2-1;
        if(EinzelPixel2 <0)
          {EinzelPixel2= NUMPIXELS-1;
          }
        if (flagIR ==0)
          { LedChange();
          }
}

void BlinkerSpeedPlus()
  {
      BlinkSpeed = BlinkSpeed -1;
      if(BlinkSpeed < 0)
        {
          BlinkSpeed = 0;
          LedMaxMinErreicht();
        }
      else
        {
          if (flagIR ==0)
            { 
              LedChange();
            }
        }
}
  
void BlinkerSpeedMinus()
  {
      BlinkSpeed = BlinkSpeed +1;
      if(BlinkSpeed > MaxSpeed)
        { 
          BlinkSpeed = MaxSpeed;
          LedMaxMinErreicht();
        }
      else
        {
          if (flagIR ==0)
            {
              LedChange();
            }
        }   
}

void Werksreset()
{
// Entfernt. Ist zu viel Code.
}

void Seriell_Abfragen()
{  
// Entfernt. Ist zu viel Code.
}


void Serielle_AusgabeIR()
{
// Entfernt. Ist zu viel Code.
}


void Serielle_AusgabeWerte()
{
// Entfernt. Ist zu viel Code.
}
void handleStartseite()
{ 
// Entfernt. Ist zu viel Code.
}

void handle404Umleitung()
{
// Entfernt. Ist zu viel Code.
}

void handleKonfiguration()
{  
// Entfernt. Ist zu viel Code.
}

void handleAP_Seite()
{
// Entfernt. Ist zu viel Code.
}

void handleUpdateseite()
{
// Entfernt. Ist zu viel Code.
}

void handleUpdate()
{
// Entfernt. Ist zu viel Code.
}

void handleUpload()
{
// Entfernt. Ist zu viel Code.
}
void handleWerksReset()
{
// Entfernt. Ist zu viel Code.
}

void handleHilfe()
{
// Entfernt. Ist zu viel Code.
}

String HTML_Tool(String Element, String AktivNav)
{
// Entfernt. Ist zu viel Code.
}

Debug Message

Es beginnt mit: 
14:50:17.366 -> assert failed: vTaskPriorityDisinheritAfterTimeout tasks.c:5267 (pxTCB != pxCurrentTCBs[ xPortGetCoreID() ])
14:50:17.366 -> 
14:50:17.366 -> 
14:50:17.366 -> Backtrace: 0x4008259c:0x3ffb2010 0x4008d011:0x3ffb2030 0x40093261:0x3ffb2050 0x4008ff72:0x3ffb2190 0x4008d887:0x3ffb21b0 0x400e1ab2:0x3ffb21f0 0x400e19af:0x3ffb2210 0x400d93ad:0x3ffb2230 0x400d9dbf:0x3ffb2250 0x400e6984:0x3ffb2270 0x4008dc96:0x3ffb2290
14:50:17.411 -> 
14:50:17.411 -> 
14:50:17.411 -> 
14:50:17.411 -> 
14:50:17.411 -> ELF file SHA256: ed09114b4
14:50:17.411 -> 
14:50:17.725 -> Rebooting...

dann...
14:50:20.391 -> E (2284) rmt: rmt_new_tx_channel(269): not able to power down in light sleep
14:50:26.858 -> 
14:50:26.858 -> assert failed: vTaskPriorityDisinheritAfterTimeout tasks.c:5267 (pxTCB != pxCurrentTCBs[ xPortGetCoreID() ])
14:50:26.858 -> 
14:50:26.858 -> 
14:50:26.858 -> Backtrace: 0x4008259c:0x3ffb2010 0x4008d011:0x3ffb2030 0x40093261:0x3ffb2050 0x4008ff72:0x3ffb2190 0x4008d887:0x3ffb21b0 0x400e1ab2:0x3ffb21f0 0x400e19af:0x3ffb2210 0x400d93ad:0x3ffb2230 0x400d9dbf:0x3ffb2250 0x400e6984:0x3ffb2270 0x4008dc96:0x3ffb2290
14:50:26.903 -> 
14:50:26.903 -> 
14:50:26.903 -> 
14:50:26.903 -> 
14:50:26.903 -> ELF file SHA256: ed09114b4
14:50:26.903 -> 

Die letzte Meldung wiederholt sich dann immer wieder.

Other Steps to Reproduce

Ich habe mehrere verschiedene ESP32 probiert.
Ich habe mehrere Rechner zum kompilieren probiert.
Ich habe verschiedene Versionen der Arduino IDE probiert.
Alles ohne Erfolg.
Erfolg hate ich nur beim Downgrade der Arduino ESP32 Boarderweiterung zurück auf 3.1.3.

I have checked existing issues, online documentation and the Troubleshooting Guide

  • I confirm I have checked existing issues, online documentation and Troubleshooting guide.
@schneeer schneeer added the Status: Awaiting triage Issue is waiting for triage label Apr 18, 2025
@Jason2866
Copy link
Collaborator

Maybe same as #11166

@schneeer
Copy link
Author

Maybe same as #11166

Ok und danke, ich schaue dort vorbei.

@schneeer
Copy link
Author

Vielleicht dasselbe wie #11166

Ok und danke, ich schaue dort vorbei.

Ich habe, wie dort angegeben, die Datei "build_opt.h" erstellt.
Das hilft mir leider nicht. Der ESP32 stürzt immer noch ab, wenn versucht wird eine Verbindung zum AP aufzubauen.

@me-no-dev
Copy link
Member

Closing this because it is not in English. Feel free to start a new issue that is written and communicated in English

@schneeer
Copy link
Author

Super Gleichberechtigung hier. Das ist mal wirklich gelebte Diversität.
Jeder vernünftige Browser übersetzt das in Echtzeit.
Dann schließt eben andersprachige Menschen hier aus.
Schämt euch!

@schneeer
Copy link
Author

schneeer commented Apr 19, 2025

Ich habe das wegen Diskriminierung Github gemeldet.
Wenn das hier häufiger vorkommt und gemeldet wird, nehmen die ganz nett Kontakt zu euch auf.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Status: Awaiting triage Issue is waiting for triage
Projects
None yet
Development

No branches or pull requests

3 participants