Verzweiflung mit reboot von ESP8266

Hallo zusammen. Ich habe ein ESP8266 als Steuerung für einen LED Streifen.
Ich habe an einen PIN ein Relais angeschlossen, mit dem ich den Trafo für die 12V LEDs ein und aus schalte.
Zusätzlich wird über einen anderen PIN ein PWM Signal an die LEDs schickt um die LEDs zu dimmen.
2 Schalter an 2 anderen PINs dienen als Hardwareschalter um ein und aus zu schalten, sowie rauf und runter zu dimmen. Das gleiche soll auch über MQTT möglich sein.
Die LEDs sind mit dem Plus Pol direkt am Trafo angeschlossen. Der Minus Pol geht über einen LB8721, welcher durch das PWM Signal gesteuert wird.
An sich funktioniert alles so weit. Relais schaltet aus und ein und es dimmt auch.
Leider ist es aber so, dass der EPS8266 immer wieder mal neu bootet, wenn ein MQTT Signal zum Ausschalten kommt (hauptsächlich eben da). Kann mir das nicht erklären. Eventuell fällt euch was im Code auf, oder es passt irgendwas an der Hardware nicht.

Bin echt schon verzweifelt.

Hier ist der Code:

#include <TimeLib.h>

#include <WiFiUdp.h>
#include <ArduinoOTA.h>
#include <PubSubClient.h>
#include <OneButton.h>

#define SWLICHTUP 4
#define SWLICHTDN 2

#define RELLICHT 5

#define DIMPIN 12
#define MAXDIM 10

#define LOCALIP IPAddress(192, 168, 11, 151)

int vals [] = { 10, 20, 30, 50, 100, 200, 300, 500, 700, 900, 1023 };

const char* ssid = "xxxxxxx";
const char* password = "xxxxxxx";
const char* mqtt_server = "192.168.11.51";
const char* mqtt_username = "xxxxxxx";
const char* mqtt_password = "xxxxxxx";
const int mqtt_port = 1883;

const char* HOSTNAME = "esp151";

const char* GETDIM = "getdim";
const char* SETDIM = "setdim";

const char* SETLICHT = "setlicht";
const char* GETLICHT = "getlicht";
const char* DIMLICHT = "dimlicht";
const char* DIMUP = "up";
const char* DIMDN = "dn";

const char* STATUSON = "ON";
const char* STATUSOFF = "OFF";
const char* STATUSCHANGE = "CHANGE";

const char* GETSTATUS = "getstatus";
const char* SENDSSID = "ssid";
const char* SENDRSSI = "rssi";
const char* SENDUPTIME = "uptime";

WiFiClient espClient;
PubSubClient client_MQTT(espClient);

OneButton swlichtup(SWLICHTUP, true);
OneButton swlichtdn(SWLICHTDN, true);

#define DATA_SIZE 30

char l_str[DATA_SIZE];
char MQTTtopic[DATA_SIZE];
char MQTTpayload[DATA_SIZE];

int i;
int len;
int aktdim;
int brightness = 0;

void sendMQTT () {
  strcpy (l_str, HOSTNAME);
  strcat (l_str, "/");
  strcat (l_str, MQTTtopic);
  client_MQTT.publish(l_str, MQTTpayload);
}

void sendrelstatus () {
 strcpy (MQTTtopic, GETLICHT);
  if (digitalRead (RELLICHT))
    strcpy (MQTTpayload, STATUSOFF);
  else
    strcpy (MQTTpayload, STATUSON);
  sendMQTT ();
}

void sendstatus () {
  strcpy (MQTTtopic, SENDRSSI);
  sprintf (MQTTpayload, "%03i", WiFi.RSSI());
  sendMQTT ();

  strcpy (MQTTtopic, SENDSSID);
  strcpy (MQTTpayload, ssid);
  sendMQTT ();

  strcpy (MQTTtopic, SENDUPTIME);
  sprintf(MQTTpayload, "%04d:%02d:%02d", hour (), minute (), second());
  sendMQTT ();

  strcpy (MQTTtopic, GETDIM);
  sprintf(MQTTpayload, "%d", aktdim);
  sendMQTT ();

}

void callback(char* topic, byte* payload, unsigned int length) {

  len = strlen (topic);
  for (i = 0; i < len; i++) {
    MQTTtopic[i] = ((char)topic[i]);
  }
  MQTTtopic[len] = 0;

  for (i = 0; i < length; i++) {
    MQTTpayload[i] = ((char)payload[i]);
  }
  MQTTpayload[length] = 0;

  if (strstr (MQTTtopic, "clickup"))
    clicklichtup();

  if (strstr (MQTTtopic, "clickdn"))
    clicklichtdn();


  if (strstr (MQTTpayload, GETSTATUS)) {
    sendstatus ();
    sendrelstatus ();
  }
  else {
    if (strstr (MQTTtopic, SETLICHT)) {
      if (strstr (MQTTpayload, STATUSON)) {
        if (digitalRead (RELLICHT))
          clicklichtup();
      }
      else if (strstr (MQTTpayload, STATUSOFF))
        longPresslichtdn();
      else if (strstr (MQTTpayload, STATUSCHANGE)) {
        digitalWrite (RELLICHT, !digitalRead (RELLICHT));
        sendrelstatus ();
      }
    }

    else {
      if (strstr (MQTTtopic, SETDIM)) {
        aktdim = atoi(MQTTpayload);
        setdim(aktdim);
      }

      else {
        if (strstr (MQTTtopic, DIMLICHT)) {
          if (strstr (MQTTpayload, DIMUP))
            clicklichtup();
          else if (strstr (MQTTpayload, DIMDN))
            clicklichtdn();
        }
      }
    }
  }
}

void reconnect() {
  // Loop until we're reconnected
  while (!client_MQTT.connected()) {
    if (client_MQTT.connect(HOSTNAME, mqtt_username, mqtt_password)) {
      strcpy (MQTTtopic, HOSTNAME);
      strcat (MQTTtopic, "/");
      strcat (MQTTtopic, "#");
      client_MQTT.subscribe(MQTTtopic);
      sendrelstatus ();
      sendstatus ();
    } else {

    }
  }


  strcpy (MQTTtopic, HOSTNAME);
  strcpy (MQTTpayload, "reconnect");
  sendMQTT ();
}

void setup_wifi() {
  delay(10);
  // We start by connecting to a WiFi network
  WiFi.mode(WIFI_STA);
  //  WiFi.hostname(HOSTNAME);
  WiFi.begin(ssid, password);
  WiFi.config(LOCALIP, IPAddress(192, 168, 11, 1), IPAddress(255, 255, 255, 0), IPAddress(8, 8, 8, 8));
  while (WiFi.status() != WL_CONNECTED) {
    delay(50);
  }
}

void setdim(int dim) {
  if (dim > MAXDIM)
    dim = MAXDIM;
  if (dim < 0)
    dim = 0;
  brightness = vals[dim];
  analogWrite(DIMPIN, brightness);
  strcpy (MQTTtopic, GETDIM);
  sprintf(MQTTpayload, "%d", dim);
  sendMQTT ();
  strcpy (MQTTtopic, "brightness");
  sprintf(MQTTpayload, "%d", brightness);
  sendMQTT ();
}


void clicklichtup() {
  if (!digitalRead (RELLICHT))
    aktdim++;
  if (aktdim > MAXDIM)
    aktdim = MAXDIM;
  if (digitalRead (RELLICHT)) {
    digitalWrite (RELLICHT, LOW);
    sendrelstatus ();
  }
  setdim (aktdim);
}

void clicklichtdn() {
  aktdim--;
  if (aktdim < 0) {
    aktdim = 0;
    if (!digitalRead (RELLICHT)) {
      digitalWrite (RELLICHT, HIGH);
      sendrelstatus ();
    }

  }
  setdim (aktdim);
}

void longPresslichtup() {
  if (digitalRead (RELLICHT)) {
    digitalWrite (RELLICHT, LOW);
    sendrelstatus ();
  }
  aktdim = MAXDIM;
  setdim (aktdim);
}

void longPresslichtdn() {
  digitalWrite (RELLICHT, HIGH);
  sendrelstatus ();
}

void setup() {

  Serial.begin(115200);

  pinMode(RELLICHT, OUTPUT);
  pinMode(DIMPIN, OUTPUT);
  digitalWrite (RELLICHT, HIGH);

  pinMode(SWLICHTUP, INPUT_PULLUP);
  pinMode(SWLICHTDN, INPUT_PULLUP);

  swlichtup.attachClick(clicklichtup);
  swlichtup.attachLongPressStart(longPresslichtup);

  swlichtdn.attachClick(clicklichtdn);
  swlichtdn.attachLongPressStart(longPresslichtdn);

  setup_wifi();

  client_MQTT.setServer(mqtt_server, mqtt_port);
  client_MQTT.setCallback(callback);

  ArduinoOTA.setPort(8266);
  ArduinoOTA.setHostname(HOSTNAME);

  ArduinoOTA.onStart([]() {
    String type;
    if (ArduinoOTA.getCommand() == U_FLASH)
      type = "sketch";
    else // U_SPIFFS
      type = "filesystem";

    // NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end()
    Serial.println("Start updating " + type);
  });
  ArduinoOTA.onEnd([]() {
    Serial.println("\nEnd");
  });
  ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
    Serial.printf("Progress: % u % % \r", (progress / (total / 100)));
  });
  ArduinoOTA.onError([](ota_error_t error) {
    Serial.printf("Error[ % u]: ", error);
    if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
    else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
    else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
    else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
    else if (error == OTA_END_ERROR) Serial.println("End Failed");
  });
  ArduinoOTA.begin();
  aktdim = 5;

}


void loop() {
  ArduinoOTA.handle();

  if (!client_MQTT.connected()) {
    reconnect(); /// reconection MQTT
  }
  swlichtup.tick();
  swlichtdn.tick();

  client_MQTT.loop();
  yield();


}

Wenn der ESP neu bootet, gibt er eine Meldung aus.
In dieser Meldung findest du den Resetgrund
Dazu den Seriellen Monitor auf 74880 Baud einstellen.

Hallo,

ansonsten die Standardfragen: welches ESP-Modul, was für ein Relais, wie angesteuert, Freilaufdiode dran, Netzteildaten, Stromversorgung das ESP, Leitungsführung/Aufbau (Bild?)...
Ich denke mal, das Abschalten des Relais/Trafos erzeugt einen Störimpuls der für den Absturz sorgt, durch Einstrueung über die Letungsführung, durch Störung auf der Betriebsspannung usw.

Gruß aus Berlin
Michael

Vielen Dank für die Antworten.

Um die serielle Ausgabe auszulesen, muss ich mal schauen, ob es das auch macht, wenn ich es am USB Port angeschlossen habe. Werde das mal versuchen.
Ich vermute auch irgendeinen Störimpuls.
Es ist dieses ESP:
ESP8266
Dieses Relais: Relais
und die Stromversorgung des ESP geht über dieses Teil: StepDown
Als Trafo für die LEDs verwende ich das: LED Treiber

Freilaufdiode gibt es nicht. Wo soll die hin?

Vom StepDown wird das ESP über einen 3,3V Spannungsregler versorgt. Das Relais wird direkt mit 5V versorgt und lediglich der Signalpin wird direkt vom ESP angesteuert.
Ich kann dann mal einen Plan zeichnen, aber das geht sich erst am Montag aus.

Hallo,

das Wandlernetzteil kenne ich, ist durchuas ok. Das Relaismodul kenne ich nicht und das Bild sagt nicht viel. Ich vermute aber schon, daß die für das Relais eine Freilaufdiode vernaut haben.
3,3V-Regler vermutlich auch ein Chinamodul mit einem AMS1117 o.ä.?
Mach mal am ESP-Modul reltiv dicht an den Betriebsspannungsanschlüssen einen 100µF Elko falls Du das nicht schon hast.
Was für eine Trafo schaltest Du mit dem Relais?

In Deinem Sketch ist mir eigentlich nichts aufgefallen was Probleme machen könnte.
Du kannst den Resetgrund auch nach dem Booten des ESP auslesen:
const rst_info * resetInfo = system_get_rst_info(); // Resetgrund einlesen

Hier hatte ich mal ein Beipspiel gefunden:

https://www.esp8266.com/viewtopic.php?p=26862

Dann kannst Du den Grund auch per MQTT schicken lassen.

Gruß aus Berlin
Michael

Was passiert, wenn du zuerst per pwm die Led auf 0 dimmst und dann erst ausschaltest?

Wow, danke für die wirklich hilfreichen Antworten.
Auch bei Helligkeit 0 passiert es, dass das ESP rebootet. Habe es gerade ausprobiert. Musste mehrmals aus und ein schalten. Manchmal passiert es beim ersten Ausschalten, manchmal erst beim 5.
Ich habe nun die Resetinfo eingebaut und per MQTT ausgeben lassen. Das hat gut funktioniert.

reason: 1
excause: 4
epc1: 1073799744
epc2: 0
epc3: 1075873515
excvaddr: 0
depc: 0

Um ehrlich zu sein, sagt mir das jetzt noch gar nichts. Muss mich erst mal schlau machen. Habe aber erst morgen Abend Zeit dafür.

Jedenfalls war das schon mal ein hilfreicher Tipp.

Kondensator habe ich keinen verbaut. Kann ich aber machen.
Mit dem Relais schalte ich einen 15W LED Treiber. Den hier.

Als 3.3V Regler habe ich kein Modul, sondern nur einen AMS1117 dran.

Hallo,

hier sollte was drinstehen:

1 ist zumindest nicht der Watchdog, es wurde der PowerOn ausgelöst.
Löte mal die 100µ dicht an das ESP-Modul, der AMS1117 hat ja sicher seine kondensatoren dicht dran?

Der LED-"Trafo" sieht für mich nicht direkt problematisch aus, das heißt aber nicht, daß das Abschalten nicht irgendwie reinsaut.

Gruß aus Berlin
Michael

Schalte mal die Sekundärseite der Led-Versorgung. Und prüfe, ob die Diode an dem Relais funktioniert oder ob überhaupt eine dran ist

Hallo,

wie hast Du den RST Eingang verschaltetet. ist der eventuell offen ? ich kenne das von dem Kleinen Bruder 8266-01 da muß ein Pull-Up angeschlossen werden 2,2 / 3,3 KOhm.

Heinz

Hallo Helste,

ich kann deine Verzweifelung nachvollziehen, die ESP8266 ist manchmal eine Diva!

Was du bei der Beschaltung beachten solltest, je nachdem welches Board du verwendest (ESP01, nodeMCU ...), es werden einige PIN's vom System benutzt. Da gibt es einiges zu beachten. Eine gute Zusammenfassung dazu findest du hier: ESP8266 und ESP8285 WLAN Module

Dann gibt es da noch die "zickige" Software, denn beim ESP8266 läuft im Hintergrund eine Firmware. Diese führt schon mal öfter zu einem Reboot. Auch wenn der Arduino Compiler deine Software durchwinkt kann es sein das da noch etwas "nicht sauber" programmiert ist. Tritt dann während des Programmablaufs z.B. eine Division durch 0 auf würde ein normaler Arduino einfach nur ein paar komische Sachen machen, der ESP fliegt ab.

Wenn du die o.g. Sachen betrachtet, dann kriegst du den ESP schon stabil hin.

Welches ESP-Board verwendest du denn?

Gruß,
Achim

Wollte mich kurz mal mit einem Zwischenstand melden. Da ich die vergangenen Tage keine Zeit hatte, mich um das Problem zu kümmern und ich jetzt zumindest mal eine Notlösung probieren wollte, habe ich folgendes gemacht:
Das Relais auf dauerhaft ein geschaltet und lediglich den PWM PIN auf 0 gesetzt, wenn ich ganz aus schalten will. Das heißt, dass der Aus Schalter einfach PWM auf 0 setzt, aber nicht mehr das Relais aus schaltet.
Damit funktioniert es jetzt ohne Probleme.
Das war einfach softwareseitig lösbar. Für die Hardwarelösungen muss ich das Teil ausbauen und das ist mit mehr Aufwand verbunden. Werde ich aber die Tage mal machen.
Dann kommt der Kondensator dran und das Relais wird komplett entfernt.
RST habe ich nicht mit Pullup versehen. Der ist lediglich über einen Mikroschalter an GND. Soll dazu dienen, dass ich vom Bedienteil aus das ESP resetten kann. Ist aber eigentlich unnötig.

Vielen Dank jedenfalls für die vielen hilfreichen Hinweise.