ESP8266 - WiFi "stoppt" seinen Betrieb - kein Crash - keine Funktion mehr

OP #7497082
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
}
Gast #7497159
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.

OP #7497172
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

Angehängte Dateien:
#7497176
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

OP #7497179
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
}
(Firma: Funkenflug Industries) #7497217
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.

Gast #7497301
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.

Gast #7497305
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.

OP #7497313
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

Angehängte Dateien:
Gast #7497318
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.

#7497331
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.

OP #7497654
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🇩🇪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

OP #7497695
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!

Gast #7497714
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.

Gast #7497780
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

#7497824
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

OP #7498946
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.

OP #7498947
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!)

OP #7499607
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"
OP #7506038
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!

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren