Esp8266 Soft WDT reset Exception (4): ESPnow

Hallo Leute,

bisher war ich hier nur stiller Mitleser, hab mir Code Schnipsel "geklaut" und damit meine Sachen realisieren können.

In einem Sketch hab ich das Problem, dass ständig ein "Soft WDT reset" passiert.
Ich habe einen bisher schon funktionsfähigen Sketch um etwas erweitern wollen. Und zwar um die ESPnow Funktion. Dabei ist der ESP der ständig neu startet der Empfänger der Nachricht.

Kurz zusammengefasst was der ESP machen soll.
Ich hab am ESP ein Relais. Diese wiederum hängt am Garagentoröffner.
Bisher konnte ich per Telegram Bot die Garage öffnen.
Jetzt wollte ich noch das öffnen per RFID hinzufügen.
Und da hakt es :-/

Ich hab auch die Stelle gefunden, verstehe es aber nicht.
Ggf. kann mir jemand den notwendigen Gedankenstoß geben :slight_smile:

Der Fehler tritt in der Funktion "void recive" auf, und zwar dann, wenn das Relais das erste mal geschaltet wurde.
und dann, zack, der ESP startet neu

Hier mal der gesamte Code

#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
#include <UniversalTelegramBot.h>
#include <ArduinoOTA.h>

// Wifi network station credentials
#define WIFI_SSID "
#define WIFI_PASSWORD "
// Telegram BOT Token (Get from Botfather)
#define BOT_TOKEN ""


const unsigned long BOT_MTBS = 1000;  // mean time between scan messages
const int GarageRechts = 13;  //Pin D7 = GPIO 13 // linkes Relais (da spiegelverkehrt)
const int GarageLinks = 4;  //Pin für Garage links, D2 als GPIO 4 //rechtes Relais, da spiegelverkehrt

X509List cert(TELEGRAM_CERTIFICATE_ROOT);
WiFiClientSecure secured_client;
UniversalTelegramBot bot(BOT_TOKEN, secured_client);
unsigned long bot_lasttime;  // last time messages' scan has been done
int ledStatus = 0;

String chat_id = "";
String woher = "";

// Bnoetgte Bibliotheken
#include <ESP8266WiFi.h>
#include <espnow.h>


// struct welches durch ESPnow übertragen wird
// Muss mit Empfaenger uebereinstimmen
typedef struct message {
  long number;
  // Speicher reserviert
  char string[64];
} message;

// Erzeuge struct
message myMessage;

const char* host = "OTA-Garage";

void handleNewMessages(int numNewMessages) {
  Serial.println("handleNewMessages");
  Serial.println(String(numNewMessages));

  for (int i = 0; i < numNewMessages; i++) {
    //    String chat_id = bot.messages[i].chat_id;
    chat_id = bot.messages[i].chat_id;
    String text = bot.messages[i].text;

    Serial.println(chat_id);
    Serial.println(text);

    String from_name = bot.messages[i].from_name;
    if (from_name == "")
      from_name = "Gast";

    if (text == "/rechts") {
      woher = "Telegram";
      schalteRechts();
    }

    if (text == "/links") {
      woher = "Telegram";
      schalteLinks();
    }

    if (text == "/beide") {
      woher = "Telegram";
      schalteBeide();
    }

    if (text == "/status") {

	//nix
    }

    if (text == "/options") {
      String keyboardJson = "[[\"/links\", \"/rechts\"], [\"/beide\", \"/status\"]]";
      bot.sendMessageWithReplyKeyboard(chat_id, "eine der Optionen auswählen", "", keyboardJson, true);
    }

    if (text == "/start") {
      String welcome = "willkommen " + from_name + " im Garagen Chat.\n";
      bot.sendMessage(chat_id, welcome, "Markdown");
    }
  }
}

void setup() {
  Serial.begin(115200);

  // attempt to connect to Wifi network:
  Serial.print("Connecting to Wifi SSID ");
  Serial.print(WIFI_SSID);
  Serial.print(" ");
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  secured_client.setTrustAnchors(&cert);  // Add root certificate for api.telegram.org
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
  }
  Serial.println();

  Serial.print("WiFi connected. IP address: ");
  Serial.println(WiFi.localIP());


  Serial.print("Retrieving time: ");
  configTime(0, 0, "pool.ntp.org");  // get UTC time via NTP
  time_t now = time(nullptr);
  while (now < 24 * 3600) {
    Serial.print(".");
    delay(100);
    now = time(nullptr);
  }
  Serial.println(now);


  pinMode(GarageRechts, OUTPUT);
  pinMode(GarageLinks, OUTPUT);

  digitalWrite(GarageRechts, HIGH);
  digitalWrite(GarageLinks, HIGH);

  bot.sendMessageWithReplyKeyboard(chat_id, "", "", keyboardJson, true);
  bot.sendMessage(chat_id, "ESP wurde neu gestartet", "");

  // Gibt MAC-Adresse aus
  Serial.print("MAC Address:  ");
  Serial.println(WiFi.macAddress());

  // Setze Geraet in Station mode
  WiFi.mode(WIFI_STA);

  // Init ESP-NOW
  if (esp_now_init() != 0) {
    Serial.println("Error initializing ESP-NOW");
  }

  // Setze Rolle
  esp_now_set_self_role(ESP_NOW_ROLE_SLAVE);

  // Sezte Callback Funktion
  esp_now_register_recv_cb(recive);


  //neu Funktionen für den OTA UPdate Server

  ArduinoOTA.setHostname(host);

  ArduinoOTA.onStart([]() {  // wird ausgeführt, wenn das Update ausgeführt wird
  });

  ArduinoOTA.onEnd([]() {  // do a fancy thing with our board led at end
  });

  ArduinoOTA.onError([](ota_error_t error) {
    (void)error;
    ESP.restart();
  });

  /* setup the OTA server */
  ArduinoOTA.begin();
  Serial.println("OTA Update Server Ready");
  Serial.println(WiFi.localIP());
}

void loop() {

  ArduinoOTA.handle();

  if (millis() - bot_lasttime > BOT_MTBS) {
    int numNewMessages = bot.getUpdates(bot.last_message_received + 1);


    while (numNewMessages) {
      //Serial.println("got response");
      handleNewMessages(numNewMessages);
      numNewMessages = bot.getUpdates(bot.last_message_received + 1);
    }

    bot_lasttime = millis();
  }

  if (WiFi.status() != WL_CONNECTED) {
    Wiederaufnahme_WLAN();
  }
}

void Wiederaufnahme_WLAN() {

  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  secured_client.setTrustAnchors(&cert);  // Add root certificate for api.telegram.org
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
  }
  Serial.println();
}


// Diese Funktion wird aufgerufen wenn Daten empfangen werden
void recive(uint8_t* incommingMacAddress, uint8_t* incomingData, uint8_t len) {
  // Daten umkopieren um ggf. spaeter nutzen zu koennen
  memcpy(&myMessage, incomingData, sizeof(myMessage));

  // Daten ausgeben
  Serial.print("Number: ");
  Serial.println(myMessage.number);
  Serial.print("String: ");
  Serial.println(myMessage.string);
  Serial.println();

  woher = "RFID";
  schalteRechts();
  
}

void schalteRechts() {

  digitalWrite(GarageRechts, LOW);
  delay(1000);
  digitalWrite(GarageRechts, HIGH);
    delay(1000);
  bot.sendMessage(chat_id, "Garage rechts wird über " + woher + " geschaltet", "");

  woher = "";
}

void schalteLinks() {

  digitalWrite(GarageLinks, LOW);
  delay(1000);
  digitalWrite(GarageLinks, HIGH);
  delay(1000);
  bot.sendMessage(chat_id, "Garage links wird über " + woher + " geschaltet", "");
  woher = "";
}

void schalteBeide() {

  digitalWrite(GarageLinks, LOW);
  digitalWrite(GarageRechts, LOW);
  delay(1000);
  digitalWrite(GarageLinks, HIGH);
  digitalWrite(GarageRechts, HIGH);
  delay(1000);
  bot.sendMessage(chat_id, "beide Garagen über " + woher + " geschaltet", "");
  woher = "";
}

Dein Code ist defekt. Bitte korrigieren. So kann man nichts sinnvoll erkennen.

Gruß Tommy

Wie hast du das Relais und welches wo angeschlossen ?

wie meinst du das mit "defekt"

hab in der Arduino IDE die Funktion "für Forum kopieren"

wie kann ich es anders machen?

dieses Relais hab ich angeschlossen, Strom etc. kommt alles über den ESP

voher, also bevor ich den Datenempfang über ESPnow eingebaut hab, hat alles geklappt, also schalten per Telegram Bot.
Auch das klappt noch ohne Probleme.

Aber wenn ich die Schaltung per ESPnow auslösen will, crasht er.

hab interessehalber aus "void recive(uint8_t* incommingMacAddress, uint8_t* incomingData, uint8_t len)" mal die Funktion "schalteRechts" rausgenommen.
Dafür in der Main Loop auf "woher == "RFID" geprüft und dann "schalteRechts" ausgeführt.
und siehe da, es kommt kein Neustart

ich versteh grad nur noch Bahnhof

Nach
#define BOT_TOKEN
ist alles als Zeichenkette dargestellt. Da fehlt wohl etwas. Kontrolliere das mal.

Gruß Tommy

ah, verstehe, jetzt.
Ich hab den tollen raus gelöscht und die Gänsefüßchen vergessen

ist ausgebessert

Ich vermute dass der Strom für den ESP zu hoch ist und der dadurch resettet.
Bei ESPnow benötigt der ESP selbst auch ca. 400 mA plus dem Strom für das Relais, das wird zu viel sein.

Ich denke nicht das der Grund die Stromversorgung ist.

  • auch die aktive WLAN Verbindung braucht mit Telegramm 400mA
  • das Programm funktioniert beim auslagern der Funktion aus der Callback Routine
  • ein SoftwareWatchdog löst den Reset aus

Ich vermute, das du dich zu lange in der Callback Routine aufhältst und dadurch der Wachhund zubeißt.

Die Callback Routine wird beim ESPnow Interrupt basierend aufgerufen. Vermutlich werden dadurch andere Interrupts blockiert.
Das spricht auch für das auslagern der Schaltfunktion.
Du blockierst mit deiner Schaltfunktion und deren 2 Delays das Programm für mindestens 2 Sekunden, zuviel für den Wachhund.
Ein löschen der Delays verhindert vermutlich das auslösen des Watchdogs.

Aber Vermutungen sind der Direkte Weg in die Hölle.

Was nicht bedeutet, das die Stromversorgung ordentlich ausgeführt werden soll!

1 Like

ah, ok.

ich probiere heute Abend mal was passiert, wenn ich das delay weg lasse
eins der beiden delays brauch ich aber, sonst merkt der Garagentorantrieb nicht, dass geschaltet werden muss.

vielen Dank schon mal an alle.
ich werde berichten :slight_smile:

noch ne Frage dazu, oft liest man ja, man soll delay nicht so verwenden sondern auch yield ausweichen.

würd das in den Zusammenhang was bringen? und so müsste ich das yield einbauen?
vor dem delay?

Delay() ruft intern yield() auf.

Gruß Tommy

Alles was auf Interupt basiert sollte so schnell wie möglich abgearbeitet werden.
Es ist schon richtig, wie du es weiter oben gemacht hast. Setze ein Flag in der Callback Routine und reagiere dann woanders darauf.

Wie man ohne delay arbeitet wird in der IDE im Beispiel Blink without Delay gezeigt. Du darfst dein Code halt nicht mit Delay blockieren, sondern nach Ablauf einer gewissen Zeit etwas ausführen. Dabei hilft dir millis(), was die abgelaufenen Millisekunden seit Start deines Programms wiedergibt.

1 Like

Das sollte immer der erste Punkt sein, der richtig dimensioniert ist.
Und wenn ich lese, die Spannung wird vom Controller abgenommen, weiß ich genau, da hat sich derjenige keine Gedanken drüber gemacht.
Aber ok, hier ist der Auslöser evtl. ein anderer. :wink:

das mit dem Strom stimmt, hab mich da einfach an eine Verkabelung gehalten, was ich auf einer Seite gefunden habe.
Hab mich als erstes in die Programmierung eingelesen und versucht zu verstehen.

Mein technischer Aufbau ist auch noch nicht ideal.
Wenn die Software Mal richtig läuft, geht's an die Optimierung der Hardware.
Im Augenblick hängen ESP und Relais in einer Aufputz Abzweigdose. Das wird wohl auch so bleiben.
Die Kabel und auch die Versorgung mit Strom muss ich noch anschauen.
Bin froh das ich vor kurzen das over the Air Update gefunden hab, dann muss ich nicht alles weg bauen und wieder hin bauen :sweat_smile:

Aber nochmal, vielen lieben Dank an alle :smiling_face::smiling_face:

Das ist übrigens der bisherige Hardware Entwurf.
Wie gesagt, das möchte ich schon noch sauberer machen.

Die zwei Kabel die vom ESP nach außen gehen, da möchte ich einen Fensterkontakt Sensor oder wie die Dinger heißen anbauen.
Damit möchte ich prüfen, ob die Garage offen oder zu ist.
Aber ein Schritt nach dem anderen...

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.