Forum: Mikrocontroller und Digitale Elektronik ESP32 - Mit WLAN Verbinden unzuverlässig?


von Jens (Gast)


Lesenswert?

Hallo,
ich hab hier einen ESP32 (ESP32 Thing von Sparkfun), den ich mit 
PlatformIO/Arduino Framework programmiere.

Beim Start soll sich der ESP32 mit meinem WLAN (Fritzbox/1750E Repeater 
Mesh) verbinden, und eine E-Mail versenden (danach geht er in den Deep 
Sleep, bis er wieder von Extern resetted wird).

Das funktioniert leider nur in 70% der Fälle. Ziemlich häufig bleibt der 
Controller beim Verbindungsaufbau hängen (es wird nicht mal ein Watchdog 
ausgelöst!). Oder er crasht dabei, und resetted sich.

Letzteres ist nicht wirklich schlimm, da es danach im zweiten Anlauf 
meist klappt. Aber wenn sich der Controller komplett aufhängt, ist das 
natürlich fatal. Das bekommt man von außen nicht mit und der Akku 
entleer sich rasend schnell (da der ESP nicht mehr in den DeepSleep 
kommt).

Nun meine Fragen dazu:
Ist das beim ESP32 "normal", dass die WLAN Verbindung so unzuverlässig 
ist?
Liegt es am Arduinio Framework (ist das IDF hier stabiler)?
Könnte es auch an der Fritzbox/dem Mesh liegen?

PS: Den Code habe ich gerade nicht griffbereit, ist aber nichts 
Besonderes (WiFi.begin()). Kann ich aber gerne nachliefern.

von Pete K. (pete77)


Lesenswert?

Ist denn die Spannungsversorgung stabil? Spendiere mal einen 100uF Elko, 
der scheint dem Board zu fehlen.
Welchen Akku benutzt Du?

Wir brauchen mehr Infos über die Schaltung und das Programm.

von Schorschi (Gast)


Lesenswert?

Außerdem wäre es interessant, ob du die onboard Antenne oder eine 
aufgesteckte benutzt. Die letzten ESP32 Boards waren bei mir immer so 
verdrahtet (Widerstand) dass eine externe Antenne angeschlossen werden 
musste.

Da hatte ich eine Weile auch mit WLAN gekämpft bis ich das bemerkte.

von Michael U. (amiga)


Lesenswert?

Hallo,

ich habe nur einen ESP32 mit Akkubetrieb hier laufen. Feste IP, da ich 
nicht auf den DHCP warten willl, kostet nur Zeit.
Mit DHCP unbedingt den Event abfragen, ob er eine aktuelle IP bekommen 
hat, Connect pausschal sagt nur, daß er mit dem AP verbunden ist.
Normalerweise ist er bei mir in ca. 1-2s mit AP und MQTT Broker 
verbunden. Manchmal dauert es aber auch bis zu 5s, keine Ahnung warum. 
Ich habe inen Timeout um die Verbindunsabfrage, wenn er nach 6s nicht 
sauber verbunden ist, geht er eben wieder schlafen. Stört hier auch 
nicht, ist nur ein Temp./Feuchte/Luftdruck-Sensor, der alle 5 Minuten 
die Daten schickt.
Spannungsversorgung ist eine LiFePO4 18650 Zelle mit 1500mAh, lebt 2 
Monate bis zum neu laden. Modul ein nackter ESP32 Wroom, 220uF am Modul 
über der Betriebsspannung.

Gruß aus Berlin
Michael

von Jens (Gast)


Lesenswert?

Hier ist der Code:
1
#include <Arduino.h>
2
#include "Mailing.h"
3
4
#define WIFI_SSID     "MySSID"
5
#define WIFI_PASSWORD   "MyPWD"
6
7
8
RTC_DATA_ATTR int gPersistentBootCount = 0; // Persistent even during deep sleep!!!
9
uint8_t gWifiConnectTryCounter = 0;
10
11
12
void SendMsg()
13
{
14
  Serial.println("Turning on radio");
15
  WiFi.mode(WIFI_STA);
16
17
  Serial.println("Trying to establishing connection to WiFi");
18
  WiFi.persistent(false);
19
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
20
21
  while ((WiFi.status() != WL_CONNECTED) && (gWifiConnectTryCounter < 10))
22
  {
23
    delay(1000);
24
    gWifiConnectTryCounter++;
25
    Serial.print(".");
26
  }
27
28
  if (WiFi.status() == WL_CONNECTED)
29
  {
30
    Serial.println("Connected successfully to wifi.");
31
    setupMailer();
32
    sendMail();
33
  }
34
  else
35
  {
36
    Serial.println("Counld NOT establish Connection to WiFi Network.");
37
  }
38
39
  Serial.println("Disconnecting wifi");
40
  WiFi.disconnect();
41
42
  Serial.println("Turning off Radio");
43
  WiFi.mode(WIFI_OFF);
44
}
45
46
void setup()
47
{
48
  Serial.begin(115200);
49
50
  ++gPersistentBootCount;
51
  Serial.println("Boot number: " + String(gPersistentBootCount));
52
  
53
  if (gPersistentBootCount == 1)
54
  {
55
    Serial.println("Sending mail...");
56
    SendMsg();
57
58
    Serial.println("Going to sleep now.");
59
    esp_sleep_enable_ext0_wakeup(GPIO_NUM_36, 1);
60
    esp_deep_sleep_start();
61
  }
62
  else
63
  {
64
    Serial.println("Rebooting...");
65
66
    // Restart the controller. Will send an E-Mail on next boot
67
    ESP.restart();
68
  }
69
}
70
71
void loop()
72
{
73
  // Loop is not required. All logic is handled in setup()
74
}

Versorgt wird der Controller über USB, die Antenne ist direkt auf dem 
Board.

von Pete K. (pete77)


Lesenswert?

Das delay(1000) funktioniert nicht gut mit des ESPs, damit blockierst Du 
den ESP, das hat er nicht so gerne. Nimm das mal raus.

von Jens (Gast)


Lesenswert?

Pete K. schrieb:
> Das delay(1000) funktioniert nicht gut mit des ESPs, damit blockierst Du
> den ESP, das hat er nicht so gerne. Nimm das mal raus.

Bist du da sicher? Der WIFi Stack läuft beim ESP32 ja auf Core 0, der 
User Code auf Core 1. Damit sollte sich da nichts blockieren. Oder bin 
ich da falsch informiert?

von DasTutWeh (Gast)


Lesenswert?

Jens schrieb:
> Ist das beim ESP32 "normal", dass die WLAN Verbindung so unzuverlässig
> ist?
> Liegt es am Arduinio Framework (ist das IDF hier stabiler)?
> Könnte es auch an der Fritzbox/dem Mesh liegen?

Ohne ins Detail zu gehen, alle genannten Quellen sind nicht richtig 
stabil!

Z.B. der Fritz Repeater hat ein FW Problem, WLAN stirbt regelmäßig bei 
mir bzw. friert ein auf Schneckentempo, nach Reset läuft alles wieder.

Es gibt auch einige Hinweise im Netz, wie man mit den ESP32 
Fehlversuchen umgehen muss, aber auch viel Unsinn dazu.

Das Framework hat nicht die Reife, wie das von ESP8266, wird aber jedes 
Jahr stabiler!

Ich kann MicroPython auf dem ESP32 empfehlen, das macht viel Freude!

von John P. (brushlesspower)


Lesenswert?

Jens schrieb:
> Der WIFi Stack läuft beim ESP32 ja auf Core 0, der
> User Code auf Core 1. Damit sollte sich da nichts blockieren. Oder bin
> ich da falsch informiert?

Das wäre mir neu.

Ich habe selber die ganzen WLAN/Server Routinen bei mir auf den 2. Core 
gelegt.
Unter Arduino läuft ALLES auf den 1. Core.

von Stefan F. (Gast)


Lesenswert?

Pete K. schrieb:
> Das delay(1000) funktioniert nicht gut mit des ESPs, damit
> blockierst Du
> den ESP, das hat er nicht so gerne. Nimm das mal raus.

Nein, das delay blockiert nicht. Es ruft wiederholt yield() auf, was der 
Firmware des ESP Zeit abgibt.

von Karo (Gast)


Lesenswert?

John P. schrieb:
> Unter Arduino läuft ALLES auf den 1. Core.

Das stimmt so nicht. Der Radio Stack läuft definitiv auf Core 0, der 
User Code auf Core 1.

"CPU 0 is also called Protocol CPU (PRO_CPU) and CPU 1 Application CPU 
(APP_CPU). The CPU 0 controls the WLAN, Bluetooth and other internal 
peripherals such as SPI, I2C, ADC, etc., while the CPU 1 is available to 
our user program. Skits that we write in the main loop and upload to the 
ESP are always executed on the CPU 1 without exception."

von Dirk B. (dirkbilland)


Lesenswert?

Falls es noch interessiert: ab ESP-IDF V3.3 dürften die 
Verbindungsprobleme behoben sein. Der Umstieg dürfte nicht allzu viele 
Änderungen an der Software erfordern.

von Stefan F. (Gast)


Lesenswert?

John P. schrieb:
> Unter Arduino läuft ALLES auf den 1. Core.

Wenn man die Version mit 2 Kernen vorliegen hat. Es gibt die ESP32 auch 
mit einem Kern.

von John Doe (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> Nein, das delay blockiert nicht. Es ruft wiederholt yield() auf, was der
> Firmware des ESP Zeit abgibt.

Schreib bitte keinen Unsinn, delay ruft vTaskDelay von FreeRTOS auf.
Einfach mal in den Quellcode schauen.
1
void delay(uint32_t ms)
2
{
3
    vTaskDelay(ms / portTICK_PERIOD_MS);
4
}

von Stefan F. (Gast)


Lesenswert?

John Doe schrieb:
> Schreib bitte keinen Unsinn,

Tu ich nicht. Ich zitiere aus der Datei core_esp8266_wiring.c vom Ardino 
ESP8266 Core in Version 2.3.0. Das ist die Version, mit der ich arbeite:
1
void delay(unsigned long ms) {
2
    if(ms) {
3
        os_timer_setfn(&delay_timer, (os_timer_func_t*) &delay_end, 0);
4
        os_timer_arm(&delay_timer, ms, ONCE);
5
    } else {
6
        esp_schedule();
7
    }
8
    esp_yield();       <---------- Da ist das yield
9
    if(ms) {
10
        os_timer_disarm(&delay_timer);
11
    }
12
}

Ok, das Wort "wiederholt" war hier falsch. Trotzdem wird die Zeit an das 
Betriebssystem abgegeben, so dass der Kern meiner Aussage richtig war.

Das ist übrigens Arduino Standard, siehe die Datei wiring.c aus dem AVR 
core:
1
void delay(unsigned long ms)
2
{
3
  uint32_t start = micros();
4
5
  while (ms > 0) {
6
    yield();    <---------- Da ist das yield
7
    while ( ms > 0 && (micros() - start) >= 1000) {
8
      ms--;
9
      start += 1000;
10
    }
11
  }
12
}

von John Doe (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> John Doe schrieb:
>> Schreib bitte keinen Unsinn,
>
> Tu ich nicht. Ich zitiere aus der Datei core_esp8266_wiring.c vom Ardino
> ESP8266 Core in Version 2.3.0. Das ist die Version, mit der ich arbeite:


Was an "ESP32" hast Du nicht verstanden?

von Stefan F. (Gast)


Lesenswert?

John Doe schrieb:
> Was an "ESP32" hast Du nicht verstanden?

Ja, das ist wohl der Knackpunkt. Ich bin im falschen Film.

Allerdings dient vTaskDelay() ebenfalls dazu, dem Betriebssystem zeit 
abzugeben. Meine Aussage "das delay blockiert nicht" ist daher immer 
noch richtig.

Muss auch so sein, weil diese Bilbiothek sonst nicht dem Arduino 
Standard entsprechen würde.

von John Doe (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> John Doe schrieb:
>> Was an "ESP32" hast Du nicht verstanden?
>
> Ja, das ist wohl der Knackpunkt. Ich bin im falschen Film.

Nix für ungut, Stefan, aber lies doch einfach in Zukunft die Posts 
gründlich durch. Ist ja fast schon die Regel, dass Du drauflos 
schreibst, bevor Du richtig gelesen hast. Möchtest Du Beispiele aus dem 
Forum hier haben?

> Allerdings dient vTaskDelay() ebenfalls dazu, dem Betriebssystem zeit
> abzugeben. Meine Aussage "das delay blockiert nicht" ist daher immer
> noch richtig.

Ändert aber nichts daran, dass yield() überhaupt nix mit dem ESP32 zu 
tun hat.

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.