Forum: Mikrocontroller und Digitale Elektronik ESP8266 - WiFi "stoppt" seinen Betrieb - kein Crash - keine Funktion mehr


von Johannes R. (johannes_r981)


Lesenswert?

Ich habe den ESP8266-01M in einen Projekt von mir am Start - bin jetzt 
aber an einen kuriosen Problem angelangt wo ich nicht wirklich den 
root-Cause ermitteln kann.
Das Ziel soll es sein zur-Runtime hin mittels Webserver Request die WiFi 
Credentials ändern zu können - sollten dies u.U. falsch sein, oder das 
WiFi nicht vorhanden sein wird automatisch ein Fallback AP gestartet. 
Das Funktioniert soweit - leider so wie es der Teufel will nutze ich 
eine malloc() Funktion um dynamische Speicher zu reservieren.

Die Funktion für das WiFi funktioniert mit z.B. _size=5 Wunderbar! 
Bereits beim wechseln auf _size= 10 kommt es zu Probleme.

Das Problem besteht darin, dass die WiFi credentials erfolgreich 
upgedated werden (ob richtig oder falsch --> egal!) Der ESP8266 fällt 
zurück und der AP startet --> soweit auch OK! Der AP ist auch 
ersichtlich in den Netzwerkschnittstelen eines Clients (Smartphone, 
Computer) beim Versuch zu verbinden....passiert dann einfach nix mehr!
Keine Ausgaben mehr am Serial Monitor, keine Verbindung...einfach nix!
So als ob das ganze Gewerk einfach einfriert so wie es ist. Es kommt zu 
meinen Verwundern auch zu keinen Absturz des ESP's. Irgendwann nach ca. 
5min ist wieder der AP ersichtlich, ich kann ich mich wieder Verbinden 
aber es ist wieder keine Verbindung möglich. Das ganze Spiel kann man 
dann länger so treiben aber es kommt zu keinen Erfolgreichen 
Verbindungsaufbau und Serial.println() liefert keine Infos mehr. Der ESP 
bleibt bis ich ihn Resette so stehen! Mittels getfreeHeap() konnte ich 
ca. 20kB freien Speicher Feststellen im Status von _size=5. "Sollte" 
reichen!

Frage:
Beim Wechsel von STA zu AP Mode zur Runtime hin: Muss ich bzw. kann ich 
hier den WiFi Stack noch irgendwie freigeben? Kann das Eventuell daran 
liegen?
Der "freeze" ohne Absturz: Wie kann ich u.U. diesen Aufheben? Im Netz 
lese ich des öfteren von "yield()" sozusagen als ultimatives 
Laserschwert für all Probleme des ESP8266. Mein Versuch diese Funktion 
zu implementieren scheiterte allerdings IMMER in einen Absturz es ESP's 
und machte das Laufzeit verhalten eher schlechter als besser!

Die Funktion zum Speicher reservieren ist:
1
void initializeArray(uint8_t _size) {
2
  if (systemParameters.LedwithinEket != nullptr) {
3
    free(systemParameters.LedwithinEket); 
4
  }
5
  systemParameters.LedwithinEket = (uint8_t*)malloc(_size * sizeof(uint8_t));
6
}

Die Funktion für das WiFi:
1
uint8_t WiFiSetup(uint8_t _variant, bool* _switchMode){
2
3
  if(*_switchMode){
4
5
    DEBUG_SERIAL.println("[WiFi] Mode Changing!");
6
    if(WiFi.getMode() == WIFI_STA){
7
      WiFi.disconnect(true);
8
    }else if(WiFi.getMode() == WIFI_AP){
9
      WiFi.disconnect(true);
10
      dnsServer.stop();
11
      //WiFi.mode(WIFI_OFF);
12
    }
13
    //Connecting as Station Mode
14
    if(_variant == ConnectWiFiSTAMode){
15
      DEBUG_SERIAL.println("[WiFi] STA Mode!");
16
      WiFi.mode(WIFI_STA);
17
      WiFi.persistent(false);
18
      WiFi.begin(systemParameters.ssid, systemParameters.password);
19
      WiFi.config(IPAddress(0, 0, 0, 0), IPAddress(0, 0, 0, 0), IPAddress(0, 0, 0, 0),
20
                      IPAddress(AP_IP_ADDRESS), IPAddress(DNS_IP_ADDRESS));
21
22
      for(uint8_t _i = 0; _i< 10; _i++) {
23
        if (WiFi.status() == WL_CONNECTED) {
24
          WiFi.setAutoReconnect(true);
25
          WiFi.scanDelete();
26
          DEBUG_SERIAL.print("[WiFi] IP address: ");
27
          DEBUG_SERIAL.println(WiFi.localIP());
28
29
          updateLength((uint16_t)systemParameters.numLEDlenght, &pixels);
30
          initializeArray(systemParameters.numLEDlenght);
31
32
          *_switchMode = false;
33
          return StationModeStarted; 
34
        }
35
        DEBUG_SERIAL.println(_i + 1);
36
        delay(2000);
37
      }
38
39
      if(WiFi.status() != WL_CONNECTED){
40
        _variant = StartWiFiAPMode;
41
      }
42
    }
43
    //Connecting as AccessPointMode
44
    if (_variant == StartWiFiAPMode) {
45
46
      DEBUG_SERIAL.println("[WiFi] AP Mode!");
47
48
      WiFi.mode(WIFI_AP);
49
      WiFi.persistent(false);
50
      WiFi.softAPConfig(IPAddress(AP_IP_ADDRESS),IPAddress(AP_IP_ADDRESS),IPAddress(SUBNET_MASK));
51
      WiFi.softAP(APSSID, APPSK);
52
      WiFi.scanDelete();
53
54
      DEBUG_SERIAL.print("[WiFi] IP Address: ");
55
      DEBUG_SERIAL.print(IPAddress(WiFi.softAPIP()));
56
      DEBUG_SERIAL.print("\n");
57
      DEBUG_SERIAL.print(WiFi.softAPSSID());
58
      DEBUG_SERIAL.print("\t");
59
      DEBUG_SERIAL.print(WiFi.softAPPSK());
60
      DEBUG_SERIAL.print("\n");
61
62
      dnsServer.setErrorReplyCode(DNSReplyCode::NoError);
63
      dnsServer.start(53, "*", WiFi.softAPIP());
64
65
      *_switchMode = false;
66
      return  AccessPointModeStarted;
67
68
    };
69
  };
70
71
  //For Loop Function: Update dnsServer and MDNS Service!
72
73
  if(WiFiMode == AccessPointModeStarted){
74
    dnsServer.processNextRequest();  
75
  }
76
  MDNS.update();
77
78
  return _variant;
79
}

In der Main Loop rufe ich dann die Wifi funktion auf:
1
void loop() {
2
  WiFiMode = WiFiSetup(WiFiMode, &SwitchWiFiMode);
3
}

von Monk (roehrmond)


Lesenswert?

Johannes R. schrieb:
> Beim Wechsel von STA zu AP Mode zur Runtime hin: Muss ich bzw. kann ich
> hier den WiFi Stack noch irgendwie freigeben? Kann das Eventuell daran
> liegen?

Nein

> Der "freeze" ohne Absturz: Wie kann ich u.U. diesen Aufheben?

Durch einen Hardware reset

Zeige mal ganz detailliert, wie die Stromversorgung des Moduls gebaut 
hast. Ich will Fotos vom Aufbau sehen, vom man die Leitungen bis zur 
Quelle (Netzteil?) sehen kann.

von Johannes R. (johannes_r981)


Angehängte Dateien:

Lesenswert?

Steve van de Grens schrieb:
> Durch einen Hardware reset
>
> Zeige mal ganz detailliert, wie die Stromversorgung des Moduls gebaut
> hast. Ich will Fotos vom Aufbau sehen, vom man die Leitungen bis zur
> Quelle (Netzteil?) sehen kann.

Danke Steve für deine Rückmeldung!

Mit einen Bild kann ich dir derzeit nicht dienen - es wird auch nicht 
viel Aussagekraft haben! Ich betreibe den USB-Prommer mit ESP01 direkt 
an einen Microsoft Surface Pro 5 USB 3.0-Port.

Ein Hardware Reset kann doch nicht des Rätsels Lösung sein auf Dauer?

mfg

von Michael D. (nospam2000)


Lesenswert?

Johannes R. schrieb:
> Die Funktion für das WiFi funktioniert mit z.B. _size=5 Wunderbar!
> Bereits beim wechseln auf _size= 10 kommt es zu Probleme.

Es ist unklar wie systemParameters.numLEDlenght befüllt wird, d.h. ob 
der Wert zur Compile-Time bekannt ist oder nicht und ob er sich zur 
Runtime jemals ändern könnte.

Die Funktion updateLength() fehlt im obigen Code Listing.
Passt die Reihenfolge der Aufrufe von updateLength() und 
initializeArray()?

Eine Analyse ist immer schwierig, wenn wichtige Code-Teile fehlen.

Warum gibst du den Speicher frei und allokierst gleich wieder neuen? Das 
kann zur memory fragmentation führen und das ist genauso schlimm wie ein 
memory leak. Solange sich die Größe nicht ändert ist das unnötig.

Warum allokierst du den Speicher überhaupt dynamisch und verwendest 
nicht ein globales statisches Array? Probier mal den Speicher als 
globales statisches Array ggf. mit der maximalen Größe anzulegen.

 Michael

: Bearbeitet durch User
von Johannes R. (johannes_r981)


Lesenswert?

Michael D. schrieb:
> Es ist unklar wie systemParameters.numLEDlenght befüllt wird, d.h. ob
> der Wert zur Compile-Time bekannt ist oder nicht und ob er sich zur
> Runtime jemals ändern könnte.

Der Wert von numLEDlenght wird aus den nvs gelesen/geschrieben.

Entschuldige die Unanehmlichkeit!
Das war noch aus einer Debug funktion (Test: vor ändern des WiFi Modus 
-->> Speicher komplett freigeben ->> danch wieder neu anlegen) Der Code 
ist so von der Funktion nachstehend richtig gestellt.

Michael D. schrieb:
> Warum gibst du den Speicher frei und allokierst gleich wieder neuen? Das
> kann zur memory fragmentation führen und das ist genauso schlimm wie ein
> memory leak. Solange sich die Größe nicht ändert ist das unnötig.
>
> Warum allokierst du den Speicher überhaupt dynamisch und verwendest
> nicht ein globales statisches Array? Probier mal den Speicher als
> globales statisches Array ggf. mit der maximalen Größe anzulegen.

naja, die Idee ist eben zur Laufzeit hin das Array nur mit der 
entsprechenden Größe anzulegen und nicht mehr. Der Hintergrund davon war 
eben genau solche Performance Probleme zu umgehen. Wenn diese Funktion 
aufgerufen wird, wird sich auch zu 100% die Größe des Array's ändern.
1
uint8_t WiFiSetup(uint8_t _variant, bool* _switchMode){
2
  if(*_switchMode){
3
    DEBUG_SERIAL.println("[WiFi] Mode Changing!");
4
    if(WiFi.getMode() == WIFI_STA){
5
      WiFi.disconnect(true);
6
    }else if(WiFi.getMode() == WIFI_AP){
7
      WiFi.disconnect(true);
8
      dnsServer.stop();
9
      //WiFi.mode(WIFI_OFF);
10
    }
11
    //Connecting as Station Mode
12
    if(_variant == ConnectWiFiSTAMode){
13
      DEBUG_SERIAL.println("[WiFi] STA Mode!");
14
      WiFi.mode(WIFI_STA);
15
      WiFi.persistent(false);
16
      WiFi.begin(systemParameters.ssid, systemParameters.password);
17
      WiFi.config(IPAddress(0, 0, 0, 0), IPAddress(0, 0, 0, 0), IPAddress(0, 0, 0, 0),
18
                      IPAddress(AP_IP_ADDRESS), IPAddress(DNS_IP_ADDRESS));
19
      for(uint8_t _i = 0; _i< 10; _i++) {
20
        if (WiFi.status() == WL_CONNECTED) {
21
          WiFi.setAutoReconnect(true);
22
          WiFi.scanDelete();
23
          DEBUG_SERIAL.print("[WiFi] IP address: ");
24
          DEBUG_SERIAL.println(WiFi.localIP());
25
          updateLength((uint16_t)systemParameters.numLEDlenght, &pixels);
26
          initializeArray(systemParameters.numLEDlenght);
27
          *_switchMode = false;
28
          return StationModeStarted; 
29
        }
30
        DEBUG_SERIAL.println(_i + 1);
31
        delay(2000);
32
      }
33
      if(WiFi.status() != WL_CONNECTED){
34
        _variant = StartWiFiAPMode;
35
      }
36
    }
37
    //Connecting as AccessPointMode
38
    if (_variant == StartWiFiAPMode) {
39
      DEBUG_SERIAL.println("[WiFi] AP Mode!");
40
      WiFi.mode(WIFI_AP);
41
      WiFi.persistent(false);
42
      WiFi.softAPConfig(IPAddress(AP_IP_ADDRESS),IPAddress(AP_IP_ADDRESS),IPAddress(SUBNET_MASK));
43
      WiFi.softAP(APSSID, APPSK);
44
      WiFi.scanDelete();
45
      DEBUG_SERIAL.print("[WiFi] IP Address: ");
46
      DEBUG_SERIAL.print(IPAddress(WiFi.softAPIP()));
47
      DEBUG_SERIAL.print("\n");
48
      DEBUG_SERIAL.print(WiFi.softAPSSID());
49
      DEBUG_SERIAL.print("\t");
50
      DEBUG_SERIAL.print(WiFi.softAPPSK());
51
      DEBUG_SERIAL.print("\n");
52
      dnsServer.setErrorReplyCode(DNSReplyCode::NoError);
53
      dnsServer.start(53, "*", WiFi.softAPIP());
54
      *_switchMode = false;
55
      return  AccessPointModeStarted;
56
    };
57
  };
58
  //For Loop Function: Update dnsServer and MDNS Service!
59
  if(WiFiMode == AccessPointModeStarted){
60
    dnsServer.processNextRequest();  
61
  }
62
  MDNS.update();
63
  return _variant;
64
}

von Johannes R. (johannes_r981)


Lesenswert?

Michael D. schrieb:
> Warum allokierst du den Speicher überhaupt dynamisch und verwendest
> nicht ein globales statisches Array? Probier mal den Speicher als
> globales statisches Array ggf. mit der maximalen Größe anzulegen.

Achso: Und ich wollte eig. Speicher im globalen sketch sparen um OTA 
Funktion zu ermöglichen!

von Ben B. (Firma: Funkenflug Industries) (stromkraft)


Lesenswert?

Beim ESP8266 habe ich zumindest bei Arduino mal gelesen, daß es für 
seine Funktion kritisch ist, daß die interne Firmware alle paar ms 
Prozessorzeit bekommt, da er sonst abschmieren kann. Keine Ahnung, ob 
das beim hier gewählten Weg der Programmierung eine Rolle spielt, aber 
vielleicht ein Denkansatz.

von Monk (roehrmond)


Lesenswert?

Johannes R. schrieb:
> Mit einen Bild kann ich dir derzeit nicht dienen

Benutzt du diesen Programmieradapter zur Stromversorgung?

Erfahrungsgemäß laufen die Module damit nicht stabil, weil der 
Spannungsregler nicht genug Strom liefert, um die Funkschnittstelle zu 
versorgen. Bedenke das, wenn dein Fehler sporadisch auftritt.

Wenn er 100% nachvollziehbar ist, und ein anderer Sketch der WLAN aktiv 
nutzt, einigermaßen stabil läuft, dann ist der Adapter wohl nicht deine 
Problemursache.

> Ein Hardware Reset kann doch nicht des Rätsels Lösung sein auf Dauer?

Wenn ein Computer mit einer Fehlfunktion abstürzt dann muss man ihn 
resetten. Daran führt kein Weg vorbei. Viele Fehler erkennt der Watchdog 
im ESP Chip automatisch und löst dann einen Reset aus. Leider klappt das 
aber nicht immer.

: Bearbeitet durch User
von Monk (roehrmond)


Lesenswert?

Ben B. schrieb:
> Beim ESP8266 habe ich zumindest bei Arduino mal gelesen, daß es für
> seine Funktion kritisch ist, daß die interne Firmware alle paar ms
> Prozessorzeit bekommt, da er sonst abschmieren kann. Keine Ahnung, ob
> das beim hier gewählten Weg der Programmierung eine Rolle spielt, aber
> vielleicht ein Denkansatz.

Ja, das spielt eine Rolle. Die delay() Funktion macht es einem hier 
allerdings leicht, denn sie enthält einen Aufruf von yield().

Der Nachteil dieser schön einfachen Methode ist, dass man mehr Stack 
braucht, als wenn man so etwas über endliche Automaten (ohne delay) 
programmiert. Und Stack hat der ESP nicht viel. Etwa 5 kB sind für den 
Sketch nutzbar.

: Bearbeitet durch User
von Johannes R. (johannes_r981)


Angehängte Dateien:

Lesenswert?

Steve van de Grens schrieb:
> Benutzt du diesen Programmieradapter zur Stromversorgung?

Derzeit ja um mit dem Serial-Monitor arbeiten zu können und die Embedded 
Tests auf der Hardware durchführen zu können. Später werde ich dann den 
ESP8266 in eine Adapterplatine betreiben und mit einen 5V Smartphone 
Ladegerät betreiben.

Wie du bereits gesagt hast - ich vermute nicht dass es am Netzteil und 
der Spannungsversorgung liegt!

Steve van de Grens schrieb:
> Erfahrungsgemäß laufen die Module damit nicht stabil

Nur als Frage nebenbei (möchte aber nicht vom Thema ablenken):
Was würdest du mir für einen Prommer empfehlen welcher genug Strom 
liefert um die ESP8266 ausreichend und stabil zu versorgen?

mfg

von Monk (roehrmond)


Lesenswert?

Johannes R. schrieb:
> Was würdest du mir für einen Prommer empfehlen welcher genug Strom
> liefert um die ESP8266 ausreichend und stabil zu versorgen?

Ich kenne keinen guten Adapter. Zum programmieren reicht der obige ja 
auch, nur halt nicht für stabilen Betrieb.

> AdapterPCB.jpg
Ob der besser ist, kann ich nicht einschätzen. Spontan fehlt mir da ein 
"dicker" Elko mit 100 oder 200 µF direkt an VCC und GND vom ESP Module. 
Kann man leicht ergänzen.

Der Spannungsregler scheint dieser zu sein:
https://datasheet.lcsc.com/lcsc/2111081830_Shenzhen-Fuman-Elec-4A2D_C2832127.pdf
Die 3,3V Version ist für maximal 500mA spezifiziert, das reicht.

: Bearbeitet durch User
von Dieter S. (hotsystems)


Lesenswert?

Johannes R. schrieb:
> Wie du bereits gesagt hast - ich vermute nicht dass es am Netzteil und
> der Spannungsversorgung liegt!

Die meisten "Absturzprobleme" die mir bekannt sind, liegen beim ESP8266 
an einer schlecht dimensionierten Versorgungsspannung. Meine ESP8266-01 
Projekte erhalten alle einen eigenen Regler (AMS1117-3,3) für die 
3,3Volt. Und entsprechende Elkos für die Stromspitzen.

Johannes R. schrieb:
> Achso: Und ich wollte eig. Speicher im globalen sketch sparen um OTA
> Funktion zu ermöglichen!

Um für alle Anforderungen genügend Platz zu haben, wurde auf meinen 
ESP-01s der Speicherbaustein gewechselt. Damit habe ich auf dem ESP 4MB 
zur Verfügung.

von Johannes R. (johannes_r981)


Lesenswert?

So,
habe das ganze heute mal versucht indem ich das Array Global definiere 
und ohne free()/malloc().
Der AP startet Einwandfrei und es ist soweit auch alles gut und genau so 
wie es sein soll.
Wenn ich mich mit einen Client darauf Verbinde, kommt ein Endlos langer 
Output und der WiFi AP wird nicht mehr angezeigt. Der ESP8266 verfängt 
sich irgendwo und es passiert wie beschrieben wieder "nix-mehr"! Ich 
habe den Output mal angeführt:

Ganz zum schluss kommt dann nach ca. 5min Wartezeit irgendwann mal 
"Fatal exception 29(StoreProhibitedCause):" Kann jemand mit dem etwas 
anfangen bzw. wie kann ich dieses Problem in den Griff bekommen?

Habe jetzt auch mal ganz am Ende der Liternei: "mac 985" erhalten!

[WiFi] AP Mode!
scandone
del if0
usl
mode : softAP(aa:48:fa:cc:ed:2e)
add if1
dhcp server start:(ip:192.168.4.1,mask:255.255.255.0,gw:192.168.4.1)
bcn 100
[WiFi] IP Address: 8.8.8.8
WiFiAP Password
[mDNS] OK!
http://esp8266.local
---END-SETUP---
add 1
aid 1
station: c4:9d:ed:2c:de:cc join, AID = 1
:urn 42
:urd 42, 42, 0
:ust rc=-13
urn 28
:urd 28, 28, 0
:urn 28
:urd 28, 28, 0
:urch 56, 28
:urch 112, 28
:urch 168, 28
:urch 224, 28
:urd 28, 28, 0
:urd 28, 28, 0
:urd 28, 28, 0
:urd 28, 28, 0
:ust rc=-13
:urn 28
:urch 56, 28
:urd 28, 28, 0
:ust rc=-13
:urch 112, 28
:urch 168, 28
:urch 224, 28
:udr
:urd 28, 28, 0
:ust rc=-13
:urch 224, 28
:udr
:udr
:urn 39
:urd 2, 39, 0
:urd 1, 39, 2
:urd 1, 39, 3
:urd 2, 39, 4
:urd 2, 39, 6
:urd 2, 39, 8
:urd 2, 39, 10
:urd 1, 39, 12
:urd 15, 39, 13
:urd 1, 39, 28
:urd 5, 39, 29
:urd 1, 39, 34
:urd 2, 39, 35
:urd 2, 39, 37
:udr
:urch 67, 189
:urd 2, 189, 0
:urd 1, 189, 2
:urd 1, 189, 3
:urd 2, 189, 4
:urd 2, 189, 6
:urd 2, 189, 8
:urd 2, 189, 10
:udr
:urd 28, 28, 0
:ust rc=-13
:urd 28, 28, 0
:ust rc=-13
:urd 28, 28, 0
:ust rc=-13
:urd 28, 28, 0
:ust rc=-13
:urn 28
:urch 56, 28
:urch 112, 28
:urd 28, 28, 0
:ust rc=-13
:urch 168, 41
:urch 237, 41
:udr
:udr
:urd 28, 28, 0
:ust rc=-13
:urch 250, 28
:udr
:urd 28, 28, 0
:ust rc=-13
:urd 41, 41, 0
:ust rc=-13
:urd 41, 41, 0
:ust rc=-13
:urd 28, 28, 0
:ust rc=-13
:urch 217, 39
:urd 2, 39, 0
:urd 1, 39, 2
:urd 1, 39, 3
:urd 2, 39, 4
:urd 2, 39, 6
:urd 2, 39, 8
:urd 2, 39, 10
:urd 1, 39, 12
:urd 15, 39, 13
:urd 1, 39, 28
:urd 5, 39, 29
:urd 1, 39, 34
:urd 2, 39, 35
:urd 2, 39, 37
:urch 67, 189
:urd 2, 189, 0
:urd 1, 189, 2
:urd 1, 189, 3
:urd 2, 189, 4
:urd 2, 189, 6
:urd 2, 189, 8
:urd 2, 189, 10
:urch 217, 39
:urd 2, 39, 0
:urd 1, 39, 2
:urd 1, 39, 3
:urd 2, 39, 4
:urd 2, 39, 6
:urd 2, 39, 8
:urd 2, 39, 10
:urd 1, 39, 12
:urd 15, 39, 13
:urd 1, 39, 28
:urd 5, 39, 29
:urd 1, 39, 34
:urd 2, 39, 35
:urd 2, 39, 37
:urch 67, 77
:urd 2, 77, 0
:urd 1, 77, 2
:urd 1, 77, 3
:urd 2, 77, 4
:urd 2, 77, 6
:urd 2, 77, 8
:urd 2, 77, 10
:urch 105, 112
:urd 2, 112, 0
:urd 1, 112, 2
:urd 1, 112, 3
:urd 2, 112, 4
:urd 2, 112, 6
:urd 2, 112, 8
:urd 2, 112, 10
:urd 1, 112, 12
:urd 15, 112, 13
:urd 1, 112, 28
:urd 5, 112, 29
:urd 1, 112, 34
:urd 2, 112, 35
:urd 2, 112, 37
:urd 1, 112, 39
:urd 1, 112, 40
:urd 1, 112, 12
:urd 15, 112, 13
:urd 1, 112, 28
:urd 5, 112, 29
:urd 1, 112, 34
:urd 2, 112, 41
:urd 2, 112, 43
:urd 1, 112, 45
:urd 1, 112, 46
:urd 1, 112, 12
:urd 15, 112, 13
:urd 1, 112, 28
:urd 5, 112, 29
:urd 1, 112, 34
:urd 2, 112, 47
:urd 2, 112, 49
:urd 4, 112, 51
:urd 2, 112, 55
:urd 4, 112, 57
:urd 1, 112, 61
:urd 1, 112, 62
:urd 1, 112, 12
:urd 15, 112, 13
:urd 1, 112, 28
:urd 5, 112, 29
:urd 1, 112, 34
:urd 2, 112, 63
:urd 2, 112, 65
:urd 4, 112, 67
:urd 2, 112, 71
:urd 16, 112, 73
:urd 1, 112, 89
:urd 2, 112, 90
:urd 2, 112, 92
:urd 4, 112, 94
:urd 2, 112, 98
:urd 12, 112, 100
:urch 140, 112
:urd 2, 112, 0
:urd 1, 112, 2
:urd 1, 112, 3
:urd 2, 112, 4
:urd 2, 112, 6
:urd 2, 112, 8
:urd 2, 112, 10
:urd 1, 112, 12
:urd 15, 112, 13
:urd 1, 112, 28
:urd 5, 112, 29
:urd 1, 112, 34
:urd 2, 112, 35
:urd 2, 112, 37
:urd 1, 112, 39
:urd 1, 112, 40
:urd 1, 112, 12
:urd 15, 112, 13
:urd 1, 112, 28
:urd 5, 112, 29
:urd 1, 112, 34
:urd 2, 112, 41
:urd 2, 112, 43
:urd 1, 112, 45
:urd 1, 112, 46
:urd 1, 112, 12
:urd 15, 112, 13
:urd 1, 112, 28
:urd 5, 112, 29
:urd 1, 112, 34
:urd 2, 112, 47
:urd 2, 112, 49
:urd 4, 112, 51
:urd 2, 112, 55
:urd 4, 112, 57
:urd 1, 112, 61
:urd 1, 112, 62
:urd 1, 112, 12
:urd 15, 112, 13
:urd 1, 112, 28
:urd 5, 112, 29
:urd 1, 112, 34
:urd 2, 112, 63
:urd 2, 112, 65
:urd 4, 112, 67
:urd 2, 112, 71
:urd 16, 112, 73
:urd 1, 112, 89
:urd 2, 112, 90
:urd 2, 112, 92
:urd 4, 112, 94
:urd 2, 112, 98
:urd 12, 112, 100
:urch 140, 142
:urd 2, 142, 0
:urd 1, 142, 2
:urd 1, 142, 3
:urd 2, 142, 4
:urd 2, 142, 6
:urd 2, 142, 8
:urd 2, 142, 10
:urch 170, 112
:urd 2, 112, 0
:urd 1, 112, 2
:urd 1, 112, 3
:urd 2, 112, 4
:urd 2, 112, 6
:urd 2, 112, 8
:urd 2, 112, 10
:urd 1, 112, 12
:urd 15, 112, 13
:urd 1, 112, 28
:urd 5, 112, 29
:urd 1, 112, 34
:urd 2, 112, 35
:urd 2, 112, 37
:urd 1, 112, 39
:urd 1, 112, 40
:urd 1, 112, 12
:urd 15, 112, 13
:urd 1, 112, 28
:urd 5, 112, 29
:urd 1, 112, 34
:urd 2, 112, 41
:urd 2, 112, 43
:urd 1, 112, 45
:urd 1, 112, 46
:urd 1, 112, 12
:urd 15, 112, 13
:urd 1, 112, 28
:urd 5, 112, 29
:urd 1, 112, 34
:urd 2, 112, 47
:urd 2, 112, 49
:urd 4, 112, 51
:urd 2, 112, 55
:urd 4, 112, 57
:urd 1, 112, 61
:urd 1, 112, 62
:urd 1, 112, 12
:urd 15, 112, 13
:urd 1, 112, 28
:urd 5, 112, 29
:urd 1, 112, 34
:urd 2, 112, 63
:urd 2, 112, 65
:urd 4, 112, 67
:urd 2, 112, 71
:urd 16, 112, 73
:urd 1, 112, 89
:urd 2, 112, 90
:urd 2, 112, 92
:urd 4, 112, 94
:urd 2, 112, 98
:urd 12, 112, 100
:urch 140, 142
:urd 2, 142, 0
:urd 1, 142, 2
:urd 1, 142, 3
:urd 2, 142, 4
:urd 2, 142, 6
:urd 2, 142, 8
:urd 2, 142, 10
:urch 170, 274
:urd 2, 274, 0
:urd 1, 274, 2
:urd 1, 274, 3
:urd 2, 274, 4
:urd 2, 274, 6
:urd 2, 274, 8
:urd 2, 274, 10
:urch 302, 39
:urd 2, 39, 0
:urd 1, 39, 2
:urd 1, 39, 3
:urd 2, 39, 4
:urd 2, 39, 6
:urd 2, 39, 8
:urd 2, 39, 10
:urd 1, 39, 12
:urd 15, 39, 13
:urd 1, 39, 28
:urd 5, 39, 29
:urd 1, 39, 34
:urd 2, 39, 35
:urd 2, 39, 37
:urch 67, 77
:urd 2, 77, 0
:urd 1, 77, 2
:urd 1, 77, 3
:urd 2, 77, 4
:urd 2, 77, 6
:urd 2, 77, 8
:urd 2, 77, 10
:urch 105, 274
:urd 2, 274, 0
:urd 1, 274, 2
:urd 1, 274, 3
:urd 2, 274, 4
:urd 2, 274, 6
:urd 2, 274, 8
:urd 2, 274, 10

: Bearbeitet durch User
von Monk (roehrmond)


Lesenswert?

Das ist ohne den vollständigen Quelltext kaum nachvollziehbar. Wo du den 
"Endlos langen Output" erwähnst: Schau dir mal diese Hinweise an: 
http://stefanfrings.de/esp8266/index.html#fallstricke

Eventuell dauert die Ausgabe zu lange oder du hast die String Klasse 
(unbewusst) auf eine Weise verwendet, die den Speicher fragmentiert.

von Johannes R. (johannes_r981)


Lesenswert?

Steve van de Grens schrieb:
> Das ist ohne den vollständigen Quelltext kaum nachvollziehbar. Wo du den
> "Endlos langen Output" erwähnst: Schau dir mal diese Hinweise an:
> http://stefanfrings.de/esp8266/index.html#fallstricke

Das ist der Output wenn ich im Setup auch setDebugOutput aktiviert 
habe...
1
  DEBUG_SERIAL.begin(115200);
2
  DEBUG_SERIAL.setDebugOutput(true);

Diesen Blog von stefanfrings kenne ich soweit, habe jetzt auch in den 
längern Loops überall ein yield() eingebaut um sicher zu gehen dass es 
nicht an zuwenig Rechenressourcen für die firmware liegt.

Steve van de Grens schrieb:
> Eventuell dauert die Ausgabe zu lange oder du hast die String Klasse
> (unbewusst) auf eine Weise verwendet, die den Speicher fragmentiert.

Hmmm.....einfach nochmal für mein Verständnis zum Thema string:
Ich nehme jetzt nochmal willkürlich eine Funktion aus meinen Code raus:
1
String SSEWrapper::toStringIp(IPAddress ip) {
2
  String res = "";
3
  for (int i = 0; i < 3; i++){
4
    res += String((ip >> (8 * i)) & 0xFF) + ".";
5
  }
6
  res += String(((ip >> 8 * 3)) & 0xFF);
7
  DEBUG_SERIAL.print("toStringIP: ");
8
  DEBUG_SERIAL.println(res);
9
  return res;
10
}

Ich muss ja mit den String "res" am Ende der Funktion nichts mehr machen 
vor "return" oder doch?

Warum frage ich das: Ich hatte mal ein Thema auf einen WindowsCE 
basierten HMI wo von seitens Support eine definitve Anweisung gekommen 
ist ich muss lokale Variablen am Ende einer Funktion immer "Bewusst" 
zerstören um hier den Speicher freizugeben!

von Monk (roehrmond)


Lesenswert?

Johannes R. schrieb:
> Ich nehme jetzt nochmal willkürlich eine Funktion aus meinen Code raus:

Ich kann nicht einschätzen, ob dein Code den Speicher fragmentiert. Das 
hängt ganz stark davon ab, wie der Speicher vor dem Aufruf der Funktion 
aussah (kann der belegte Speicher vom String vergrößert werden, oder ist 
ein neuer Block nötig?) und was danach mit dem String gemacht wird.

Ich wollte nur darauf hinweisen, dass das ein möglicher Fehler ist. 
Wirklich herausfinden wirst du es nur, wenn du den Heap zur Laufzeit 
analysierst. Der ESP8266 hat aber leider keinen Debugger-Anschluss.

von Johannes R. (johannes_r981)


Lesenswert?

Ja OK danke dir für den Input!
Das der keinen Debugger nutzen kann nervt mich mittlerweile total!

Steve van de Grens schrieb:
> Ich kann nicht einschätzen, ob dein Code den Speicher fragmentiert.

Wie würde den so etwas aussehen? Ich habe jetzt sämtliche malloc // free 
Befehle entfernt.

von Michael D. (nospam2000)


Lesenswert?

Johannes R. schrieb:
> Das der keinen Debugger nutzen kann nervt mich mittlerweile total!

Einer der Vorteile des ESP32, den kann man debuggen :-)

  Michael

von Kutte R. (kutte)


Lesenswert?

Johannes R. schrieb:
> Liternei
Fremdwörter nur verwenden, wenn man weiß wie sie geschrieben werden, 
sonst wirds peinlich
https://www.dwds.de/wb/Litanei

von Monk (roehrmond)


Lesenswert?

Johannes R. schrieb:
> Wie würde den so etwas aussehen?

Ich bin jetzt unsicher, ob ich deine Frage richtig verstanden habe. Die 
Erklärung wie das aussieht war schon in dem verlinkten Artikel:

https://www.mikrocontroller.net/articles/Heap-Fragmentierung

Ich vermeide die funktions-übergreifende Nutzung von String Variablen.

Die Standard C Bibliothek enthält genug alternative Funktionen, um auf 
Strings verzichten zu können und stattdessen char[] zu benutzen. Das ist 
zwar umständlicher, aber dann hast du die Speicherverwaltung besser 
unter Kontrolle. Denn die Standard C Funktionen für char[] allokieren 
nicht im Hintergrund Speicher, wie es die String Klasse tut.

Ohne die String Klasse kannst du allerdings nicht mehr ganz so einfach 
einen String (bzw eine Zeichenkette) zurück geben. Ich würde dem Muster 
der C Bibliothek folgen, zum Beispiel wie bei snprintf(). Sprich: Der 
Aufrufer von SSEWrapper::toStringIp() müsste einen Puffer bereitstellen, 
der dann von der Methode gefüllt wird. Etwa so:
1
void SSEWrapper::toStringIp(char* buffer, int maxLen, IPAddress ipAddress) {
2
...
3
}
4
5
void aufrufer() {
6
  IPAddress ipAddress = ...;
7
  char buffer[20];
8
  sseWrapper.toStringIp(buffer, sizeof(buffer), ipAddress);
9
10
  // buffer contains the IP address now 
11
}

So entfällt die dynamische Nutzung des Heap. Die Variable ipStr gehört 
zum Stack der aufrufenden Funktion und wird von ihr (beim Verlassen) 
auch wieder freigegeben.

Nachtrag: falschen Link korrigiert

: Bearbeitet durch User
von Michael D. (nospam2000)


Lesenswert?

Johannes R. schrieb:
> Ich muss ja mit den String "res" am Ende der Funktion nichts mehr machen
> vor "return" oder doch?

Das sollte aus C++ Sicht so passen, sofern die String-Klasse damit 
korrekt umgeht. Es

> Warum frage ich das: Ich hatte mal ein Thema auf einen WindowsCE
> basierten HMI wo von seitens Support eine definitve Anweisung gekommen
> ist ich muss lokale Variablen am Ende einer Funktion immer "Bewusst"
> zerstören um hier den Speicher freizugeben!

Für C++ Objekte welche in ihrem Destruktor den von ihnen allokierten 
Speicher korrekt freigeben musst du das nicht machen.

Beim Suchen nach der Fehlermeldung "Fatal exception 
29(StoreProhibitedCause):" habe ich nur Beispiele mit 
Speicher-Überläufen gefunden, z.B. folgenden:
https://stackoverflow.com/questions/76030246/calling-a-routine-on-esp8266-decreases-progressively-the-free-heap

Du verwendest nicht zufällig wifi_softap_get_station_info() oder 
ähnliche Funktionen deren Rückgabewert explizit freigegeben werden muss?

Da wir den kompletten Code nicht sehen, ist das nur ein Blick in die 
Glaskugel.

  Michael

von Johannes R. (johannes_r981)


Lesenswert?

Steve van de Grens schrieb:
> void SSEWrapper::toStringIp(char* buffer, int maxLen, IPAddress
> ipAddress) {
> ...
> }
> void aufrufer() {
>   IPAddress ipAddress = ...;
>   char buffer[20];
>   sseWrapper.toStringIp(buffer, sizeof(buffer), ipAddress);
>   // buffer contains the IP address now
> }

Ich bin nun dazu übergegangen und habe so ziemlich jede String operation 
durch ein char Puffer ersetzt bzw. ersetzen können. Ich stelle jetzt 
global 3 Puffer zur Verfügung mit denen ich arbeite. Das Programm hat 
sich vom Sketch Size her fast gar nicht geändert. Die Stabilität hat 
sich wenn ihr mich fragt verbessert - die Responsezeit von einem SSE 
Reqeuest allerdings etwas verringert aber damit kann ich leben! Nach wie 
vor erhalte ich abstürze beim umschalten vom STA Mode -->> AP Mode -->> 
STA Mode des ESP!

Michael D. schrieb:
> Du verwendest nicht zufällig wifi_softap_get_station_info() oder
> ähnliche Funktionen deren Rückgabewert explizit freigegeben werden muss?

Hmm....nicht das ich wüsste!
Ich Scanne nach Erreichbaren Netzwerken beim Umschalten vom STA Mode auf 
den AP Mode und nutze die WiFi.scanNetworks(true, true); Methode sowie 
die WiFi.scanDelete(); Methode sollten die Elemente nicht mehr gebraucht 
werden.

von Johannes R. (johannes_r981)


Lesenswert?

Mir ist noch etwas anderes in den Sinn gekommen:

Könnte es sein, dass ich mir mit der Verwendung von Preferences.h den 
Speicher Zustelle?

Ich nutze die Funktion zum Speichern von Parametern
1
preferences.putInt(RED_KEY, systemParameters.r);
2
preferences.putInt(GREEN_KEY, systemParameters.g);
3
preferences.putInt(BLUE_KEY, systemParameters.b);

könnte dies Dazu führen dass ich Elemente überschreibe und mir so die 
WiFi Funktion "unnutzbar" mache?

Generell nochmal die Frage: Kann ich für diese Preferences eine Partiton 
einrichten wo die Datenliegen? Ich komm da aber nciht ganz weiter wie 
ich eine Custom Partition Tabelle einrichte wo ich einerseits die .html 
File Speichere für den Webserver und anderer Seits die NVS Partiton 
anlege für die preferences sowie Ota Funktionalität nutzen möchte 
(Between: neue Flash Chips mit 4MB sind bestellt damit ich genug speiche 
habe für das Testen!)

von Dieter S. (hotsystems)


Lesenswert?

Johannes R. schrieb:
> Könnte es sein, dass ich mir mit der Verwendung von Preferences.h den
> Speicher Zustelle?

Normalerweise nicht, da du diese Daten in einem anderen Bereich 
(LittleFS) speicherst, als deinen Sketch.
Wenn du mit der Arduino IDE arbeitest, kannst du auch die 
Speicherzuordnung anpassen.
Bei anderen Systemen musst du schauen.

von Johannes R. (johannes_r981)


Lesenswert?

Dieter S. schrieb:
> Normalerweise nicht, da du diese Daten in einem anderen Bereich
> (LittleFS) speicherst, als deinen Sketch.
> Wenn du mit der Arduino IDE arbeitest, kannst du auch die
> Speicherzuordnung anpassen.
> Bei anderen Systemen musst du schauen.

Hm, ja stimmt.
Unter PlatformIO nutzt man hier die Linker Scripts um die 
Speicherzuordnung festzulegen. Dabei nutze ich das derzeit noch das 
"esp8266.flash.1m128.ld" Linkerskript. (Wird geändert wenn ich den 4MB 
Flash Chip setze!)

Wobei mir hier immer noch Schleierhaft ist wo die Daten welche ich 
in/aus dem NVS Storage beziehe dann "rauskommen"? Ist das die eeprom 
Partition dann mit 20KB?

Ich glaube ja mittlerweile generell, dass ich ein falsches Linkerskript 
verwende oder? Wo wird denn in diesem Linkerskript der OTA Speicher 
reserviert? Ich weiß bei Arduino gibt es eine Auswahl mit OTA und 
LittleFS size auszuwählen...
1
/* Flash Split for 1M chips */
2
/* sketch 871KB */
3
/* spiffs 128KB */
4
/* eeprom 20KB */
5
6
MEMORY
7
{
8
  dport0_0_seg :                        org = 0x3FF00000, len = 0x10
9
  dram0_0_seg :                         org = 0x3FFE8000, len = 0x14000
10
  iram1_0_seg :                         org = 0x40100000, len = 0x8000
11
  irom0_0_seg :                         org = 0x40201010, len = 0xd9ff0
12
}
13
14
PROVIDE ( _SPIFFS_start = 0x402DB000 );
15
PROVIDE ( _SPIFFS_end = 0x402FB000 );
16
PROVIDE ( _SPIFFS_page = 0x100 );
17
PROVIDE ( _SPIFFS_block = 0x1000 );
18
19
INCLUDE "esp8266.flash.common.ld"

von Johannes R. (johannes_r981)


Lesenswert?

So, habe jetzt ewig probiert.
Memory Fragmentation kann ich definitiv ausschließen, da ich jetzt alles 
umgebaut habe auf char[] Array's und keine Strings mehr verwende.

Das Problem besteht nun ganz klar darin, dass im AP Mode nach Neustart 
des ESP8266 ein komplett unerwartetes Verhalten auftritt wo der AP nicht 
mehr ersichtlich ist.

Wenn ich zur Laufzeit hin im STA-Mode Starte -->> Umschalte auf den 
AP-Mode und dann wieder auf den STA-Mode schalte funktioniert das ganze 
OHNE Probleme!

Die WiFi Funktion ist:
1
uint8_t WiFiSetup(uint8_t _variant, bool* _switchMode){
2
3
  if(*_switchMode){
4
    ESPDebuggingFunction();
5
6
    DEBUG_SERIAL.println("[WiFi] Mode Changing!");
7
    WiFi.disconnect(true);  // Dicsonnect and start "from the Beginning"
8
    dnsServer.stop();       // Stop DNS Service
9
    DEBUG_SERIAL.println("[WiFi] Services close");
10
11
    // Connecting ESP8266 as Station Mode
12
    if(_variant == ConnectWiFiSTAMode){
13
      DEBUG_SERIAL.println("[WiFi] STA Mode!");
14
      WiFi.mode(WIFI_STA);
15
      WiFi.persistent(false);
16
      //WiFi.setHostname(myHostname);
17
      WiFi.begin(systemParameters.ssid, systemParameters.password);
18
      WiFi.config(IPAddress(0, 0, 0, 0), IPAddress(0, 0, 0, 0), IPAddress(0, 0, 0, 0),
19
                      IPAddress(AP_IP_ADDRESS), IPAddress(DNS_IP_ADDRESS));
20
21
      // Retry Connectiong ESP8266 in STA Mode, if it fails start Fallback AP mode
22
      for(uint8_t _i = 0; _i< 10; _i++) {
23
        if (WiFi.status() == WL_CONNECTED) {
24
          WiFi.setAutoReconnect(true);
25
          WiFi.scanDelete();
26
          DEBUG_SERIAL.print("[WiFi] IP address: ");
27
          DEBUG_SERIAL.println(WiFi.localIP());
28
29
          dnsServer.setErrorReplyCode(DNSReplyCode::NoError);
30
          dnsServer.start(53, "*", WiFi.softAPIP());
31
32
          MDNS.notifyAPChange();     //restart MDNS Service
33
34
          DEBUG_SERIAL.println("[WiFi] Services restarted");
35
36
          *_switchMode = false;
37
          ESPDebuggingFunction();
38
          return StationModeStarted; // Successfull connected -->> return!
39
        }
40
        DEBUG_SERIAL.println(_i + 1);
41
        for (unsigned long start = millis(); millis() - start < 2000UL;) {
42
          yield(); // "yield()-based-break for 2seconds between reconnect"
43
        }      
44
      }
45
46
      if(WiFi.status() != WL_CONNECTED){
47
        DEBUG_SERIAL.println("[WiFi] STA not possible - starting AP!");
48
        WiFi.disconnect(true);
49
        _variant = StartWiFiAPMode;
50
      }
51
    }
52
    // Connecting/starting ESP8266 as/in AccessPointMode
53
    if (_variant == StartWiFiAPMode) {
54
      DEBUG_SERIAL.println("[WiFi] AP Mode!");
55
56
      WiFi.mode(WIFI_AP);
57
      WiFi.persistent(false);
58
      WiFi.softAPConfig(IPAddress(AP_IP_ADDRESS),IPAddress(AP_IP_ADDRESS),IPAddress(SUBNET_MASK));
59
      WiFi.softAP(APSSID, APPSK);
60
      WiFi.scanDelete();
61
62
      DEBUG_SERIAL.print("[WiFi] IP Address: ");
63
      DEBUG_SERIAL.print(IPAddress(WiFi.softAPIP()));
64
      DEBUG_SERIAL.print("\n");
65
      DEBUG_SERIAL.print(WiFi.softAPSSID());
66
      DEBUG_SERIAL.print("\t");
67
      DEBUG_SERIAL.print(WiFi.softAPPSK());
68
      DEBUG_SERIAL.print("\n");
69
      DEBUG_SERIAL.print("Channel: ");
70
      DEBUG_SERIAL.print(WiFi.channel());
71
      DEBUG_SERIAL.print("\t Physical Mode: ");
72
      DEBUG_SERIAL.print(WiFi.getPhyMode());
73
      //WiFi.printDiag(DEBUG_SERIAL);
74
75
      // Startinng DNSServer on Port 53
76
      dnsServer.setErrorReplyCode(DNSReplyCode::NoError);
77
      dnsServer.start(53, "*", WiFi.softAPIP());
78
79
      MDNS.notifyAPChange();     //restart MDNS Service
80
81
      DEBUG_SERIAL.println("[WiFi] Services restarted");
82
83
      *_switchMode = false;
84
      ESPDebuggingFunction();
85
      return  AccessPointModeStarted;
86
87
    };
88
  };

Diese Wird im Setup ganz am Ende 1x aufgerufen und anschließend in der 
Loop geprüft ob sich der WiFi State changed. Hat jemand eine Idee? 
Manchmal kann ich beim crash auch beobachten, dass ein mac 684 Error 
kommt gefolgt von einen wdt Reset was aber NICHT IMMER der fall ist!

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.