espressif / arduino-esp32

Arduino core for the ESP32
GNU Lesser General Public License v2.1
13.55k stars 7.39k forks source link

ESP32 WiFi.begin works only every second time - workaround #2501

Closed DIRR70 closed 2 years ago

DIRR70 commented 5 years ago

Hardware:

Board: ESP32-WROOM-32 Dev Module Core Installation version: 1.0.1 (installed using board manager feb/23) IDE name: Arduino IDE 1.88 CPU Frequency: 80MHz Flash Frequency: 40Mhz Flash Mode: QIO Flash Size: 2MB (16MB) Partition Scheme: Standard PSRAM enabled: no Upload Speed: 921600 Computer OS: Windows 10

Description:

With a portable device I need to ensure that WiFi connection is beeing established as soon as the router is in range. Also I need to do some stuff as soon the connection is established or lost (in my sketch below just a serial output).

I have the problem that "WiFi.begin(ssid, pass)" works only every second time. If it doesn't work, I have to press the reset button and then it works. If I press reset again it won't work. Pressing reset again and it works, and so on.

If it doesn't work I get the following output with Debug Level set to verbose: [W][WiFiGeneric.cpp:357] _eventCallback(): Reason: 202 - AUTH_FAIL

My router is a Fritz! Box 6490 cable and even though I've checked the router's options I can't find anything wrong. Regarding to familiar posts I even have tried with a regulated power supply at 5V (current limit 2.5A) - but no change.

I came up with a workaround with a task checking the connection and that works pretty well. In case of "WiFi.status" turns to "WL_CONNECT_FAILED" I need to call "WiFi.disconnect(true)" and a bit later "WiFi.begin" again.

About the whole working sketch below I have several questions:

  1. Is that "works/doesn't work" behaviour a firmware bug, a bug in arduino or this SDK or a router problem?
  2. In my sketch I'm using "xTaskCreatePinnedToCore" for the connection watching task. How large does the stack for that task need to be (seems to work with 8kB) and what priority does such a task need to have (I just took 3 to be higher than IDLE)?
  3. I never got "WL_CONNECTION_LOST" as Wifi status. Do I need to consider that? And if so, how?

Please advise! Thank's!

Sketch:

#include <WiFi.h>

const char* ssid = "...";
const char* password = "...";

bool myWiFiFirstConnect = true;

void myWiFiTask(void *pvParameters) {
  wl_status_t state;

  while (true) {
    state = WiFi.status();
    if (state != WL_CONNECTED) {  // We have no connection
      if (state == WL_NO_SHIELD) {  // WiFi.begin wasn't called yet
        Serial.println("Connecting WiFi");

        WiFi.mode(WIFI_STA);
        WiFi.begin(ssid, password);

      } else if (state == WL_CONNECT_FAILED) {  // WiFi.begin has failed (AUTH_FAIL)
        Serial.println("Disconnecting WiFi");

        WiFi.disconnect(true);

      } else if (state == WL_DISCONNECTED) {  // WiFi.disconnect was done or Router.WiFi got out of range
        if (!myWiFiFirstConnect) {  // Report only once
          myWiFiFirstConnect = true;

          Serial.println("WiFi disconnected");
        }
      }

      vTaskDelay (250); // Check again in about 250ms

    } else { // We have connection
      if (myWiFiFirstConnect) {  // Report only once
        myWiFiFirstConnect = false;

        Serial.print("Connected to ");
        Serial.println(ssid);
        Serial.print("IP address: ");
        Serial.println(WiFi.localIP());
        Serial.println("");
      }

      vTaskDelay (5000); // Check again in about 5s
    }
  }
}

void setup() {
  delay(1000); // Power up

  Serial.begin(115200);

  // Create a connection task with 8kB stack on core 0
  xTaskCreatePinnedToCore(myWiFiTask, "myWiFiTask", 8192, NULL, 3, NULL, 0);
}

void loop() {
}

Debug Messages:

If WiFi.begin works:
[D][WiFiGeneric.cpp:342] _eventCallback(): Event: 0 - WIFI_READY
[D][WiFiGeneric.cpp:342] _eventCallback(): Event: 2 - STA_START
....[D][WiFiGeneric.cpp:342] _eventCallback(): Event: 4 - STA_CONNECTED
[D][WiFiGeneric.cpp:342] _eventCallback(): Event: 7 - STA_GOT_IP
[D][WiFiGeneric.cpp:385] _eventCallback(): STA IP: 192.168.178.21, MASK: 255.255.255.0, GW: 192.168.178.1

If it doesn't work:
[D][WiFiGeneric.cpp:342] _eventCallback(): Event: 0 - WIFI_READY
[D][WiFiGeneric.cpp:342] _eventCallback(): Event: 2 - STA_START
[D][WiFiGeneric.cpp:342] _eventCallback(): Event: 5 - STA_DISCONNECTED
[W][WiFiGeneric.cpp:357] _eventCallback(): Reason: 202 - AUTH_FAIL
asetyde commented 5 years ago

Also I confirm it , i use check every 5 seconds if is not connect, also sometimes passing char[] ssid and pass not work, i ve said many times but i never get a reply

BaaridunNasr commented 5 years ago

From my experience, it seems that a

WiFi.disconnect();

Seems to reset the configurations. To be clear, while closing a connection/disconnecting you need to clear the configurations to enable a clean connect the second time around. I've used this to ensure solid connects and reconnects with any network. Although this seems to fail regardless of settings when connecting to a Mobile Hotspot. I feel it has something to do with the mobile hotspots, though.

ImkereiWetzel commented 5 years ago

I trying to solve the exact same problem here - Test scenario: using example WifiClientEvents If I reset the board, only every other reboot gives me a Wifi connection.

Is there something I can do to help fix this problem?

timothy3001 commented 5 years ago

Facing the same issue here. If I capture the events via WiFi.on, i get the WiFiEvent_t number 5 which seems to be WIFI_REASON_ASSOC_TOOMANY.

When I keep resetting the board, this event is occuring every other time.

kireol commented 5 years ago

Also experiencing this issue. NodeMCU board with ESP-WROOM-32. Calling WiFi.disconnect did not help.

asetyde commented 5 years ago

with library 1.0.3 rc connection 1 of 3 go , with 1.0.2 at 2 of 3 connect

nouser2013 commented 5 years ago

I can confirm the issue with latest GIT. WiFi.disconnect() does not help, neither with true nor with false as argument.

goldwingman commented 5 years ago

I'm new to GitHub so please keep the flames low. I have duplicated the aforementioned "every other reset" issue on several ESP32 Wroom. I have also found a permanent solution to my problem. Not to suggest that this will address others problems but certainly worth the effort.
Arduino IDE 1.8.6 ESP32 1.0.2 I am running a fauxmoESP and Blynk app so not using WiFi.begin(). Just the same, only using WiFi.begin() without fauxmoESP and Blynk, always duplicated the "every other" reset condition.

I my case; ESP32 connected with RSSI levels of -70 or higher (even lower signal strength). After moving my project to final destination, RSSI levels of -50 or lower (higher signal strength) have been the expected normal. My ESP32 is connecting after every reset without any problem. So, signal quality appears to have EVERYTHING to do with my issue. I have not verified at what signal levels do things again become marginal.

Just to be clear: D][WiFiGeneric.cpp:342] _eventCallback(): Event: 0 - WIFI_READY [D][WiFiGeneric.cpp:342] _eventCallback(): Event: 2 - STA_START [D][WiFiGeneric.cpp:342] _eventCallback(): Event: 5 - STA_DISCONNECTED [W][WiFiGeneric.cpp:357] _eventCallback(): Reason: 202 - AUTH_FAIL

Followed after reset by: [D][WiFiGeneric.cpp:342] _eventCallback(): Event: 0 - WIFI_READY [D][WiFiGeneric.cpp:342] _eventCallback(): Event: 2 - STA_START ....[D][WiFiGeneric.cpp:342] _eventCallback(): Event: 4 - STA_CONNECTED [D][WiFiGeneric.cpp:342] _eventCallback(): Event: 7 - STA_GOT_IP [D][WiFiGeneric.cpp:385] _eventCallback(): STA IP: 192.X.X.X, MASK: 255.255.255.0, GW: 192.X.X.X

Results after every reset with RSSI at -50 or lower [D][WiFiGeneric.cpp:342] _eventCallback(): Event: 0 - WIFI_READY [D][WiFiGeneric.cpp:342] _eventCallback(): Event: 2 - STA_START ....[D][WiFiGeneric.cpp:342] _eventCallback(): Event: 4 - STA_CONNECTED [D][WiFiGeneric.cpp:342] _eventCallback(): Event: 7 - STA_GOT_IP [D][WiFiGeneric.cpp:385] _eventCallback(): STA IP: 192.X.X.X, MASK: 255.255.255.0, GW: 192.X.X.X

Hope this helps someone.

nouser2013 commented 5 years ago

Well, that may help pinpoint the bugs source code location. I did a different approach:

RTC_DATA_ATTR int bootCount;

void setup() {
  // ...
  // Reset Boot counter if reason was brownout or first power-on
  if (rtc_get_reset_reason(0) == 1 || rtc_get_reset_reason(0) == 15 || rtc_get_reset_reason(1) == 1 || rtc_get_reset_reason(1) == 15) { bootCount = 0; }
  bootCount++;
  // [Try to connect to WIFI here]
  if (WiFi.status() == WL_CONNECTED) {
    Serial.print("...WIFI is connected, local IP: ");
    Serial.println(WiFi.localIP());
  } else { 
    if (bootCount < 3) {
      Serial.println("...failed, REBOOT!");
      // Do not use ESP.restart! This would reset the RTC memory.
      esp_sleep_enable_timer_wakeup(10);
      esp_deep_sleep_start();
    } else {
      Serial.println("...finally failed.");
      Serial.println("Opening unprotected access point...");
      // Code to open WIFI AP
    }
  }
  // ...
}
barneyz commented 5 years ago

I had the same problem, the ESP.reboot() or esp_deep_sleep_start(); cannot proper reset the WiFi-Hardware, so every sencond time I got no Wifi connection. I extended the code from DIRR70, now I get a connection every new start...

else if (wifi_state == WL_DISCONNECTED) // WiFi.disconnect was done or Router.WiFi got out of range { if (!myWiFiFirstConnect) // Report only once { myWiFiFirstConnect = true; Serial.println("WiFi disconnected"); } Serial.println("No Connection -> Wifi Reset"); WiFi.persistent(false); WiFi.disconnect(); WiFi.mode(WIFI_OFF); WiFi.mode(WIFI_STA); // WiFi.config(ip, gateway, subnet); // Only for fix IP needed WiFi.begin(ssid, password); delay(3000); // Wait 3 Seconds, WL_DISCONNECTED is present until new connect! } vTaskDelay(250); // Check again in about 250ms

Sandotter commented 5 years ago

I can confirm this issue too with 2 different devices. @DIRR70 and @barneyz you made my day. The combination of your coding is a working workaround. Hopefully this issue will be solved. The above solution is not suitable for beginners.

kugelkopf123 commented 5 years ago

Same here... Its pretty annoying...


WiFi Event ID: 3
[D][WiFiGeneric.cpp:336] _eventCallback(): Event: 0 - WIFI_READY
[D][WiFiGeneric.cpp:336] _eventCallback(): Event: 2 - STA_START
[WiFi-event] event: 2
WiFi client started
[WiFi-event] event: 0
WiFi interface ready

.[D][WiFiGeneric.cpp:336] _eventCallback(): Event: 5 - STA_DISCONNECTED
[W][WiFiGeneric.cpp:351] _eventCallback(): Reason: 202 - AUTH_FAIL
202
kugelkopf123 commented 5 years ago

By the way another Solution: Based on @nouser2013 idea

  WiFiEventId_t eventID = WiFi.onEvent([](WiFiEvent_t event, WiFiEventInfo_t info) {
    Serial.print("WiFi lost connection. Reason: ");
    Serial.println(info.disconnected.reason);
    if (info.disconnected.reason == 202) {

      Serial.println("Connection failed, REBOOT/SLEEP!");
      esp_sleep_enable_timer_wakeup(10);
      esp_deep_sleep_start();
      delay(100);

    }
  }, WiFiEvent_t::SYSTEM_EVENT_STA_DISCONNECTED);
Informaticore commented 5 years ago

I had the same issue and it was fixed with calling WiFi.disconnect() before going into deep sleep.

maxdd commented 5 years ago

How come this problem is still present?!?! EPS32 is a mess like this. Can anyone please post a decent code? Also i can make it reboot and have it connected but why do we need to do this, how come it cannot work properly. Not to mention that i have this problem on 3 devices and they also DC during the day without reconnecting anymore!

kugelkopf123 commented 5 years ago

Another possibility is using wifimulti. But it takes longer.


#include <WiFi.h>
#include <WiFiMulti.h>

void setup() {
wifiMulti.addAP("SSID", "PASS");
if((wifiMulti.run() == WL_CONNECTED)) { 
Serial.println("Fantastic iam connected...");

}
}
schreibfaul1 commented 5 years ago

wifiMulti.run() works only at second time after reset

#include <WiFiMulti.h>
WiFiMulti wifiMulti;

void setup() {
    wifiMulti.addAP("Wolles-FRITZBOX", "xxxxxxxxx");
    wifiMulti.run();
    WiFi.disconnect(true);
    wifiMulti.run();
}

void loop() {
}

result:

[I][WiFiMulti.cpp:84] addAP(): [WIFI][APlistAdd] add SSID: Wolles-FRITZBOX
[I][WiFiMulti.cpp:114] run(): [WIFI] scan done
[I][WiFiMulti.cpp:119] run(): [WIFI] 7 networks found
[I][WiFiMulti.cpp:160] run(): [WIFI] Connecting BSSID: 08:96:D7:FB:72:65 SSID: Wolles-FRITZBOX Channal: 11 (-28)
[W][WiFiGeneric.cpp:353] _eventCallback(): Reason: 202 - AUTH_FAIL
[E][WiFiMulti.cpp:184] run(): [WIFI] Connecting Failed.
[I][WiFiMulti.cpp:114] run(): [WIFI] scan done
[I][WiFiMulti.cpp:119] run(): [WIFI] 7 networks found
[I][WiFiMulti.cpp:160] run(): [WIFI] Connecting BSSID: 08:96:D7:FB:72:65 SSID: Wolles-FRITZBOX Channal: 11 (-31)
[I][WiFiMulti.cpp:174] run(): [WIFI] Connecting done.
kugelkopf123 commented 5 years ago

wifiMulti.run() works only at second time after reset

#include <WiFiMulti.h>
WiFiMulti wifiMulti;

void setup() {
  wifiMulti.addAP("Wolles-FRITZBOX", "xxxxxxxxx");
  wifiMulti.run();
  WiFi.disconnect(true);
  wifiMulti.run();
}

void loop() {
}

result:

[I][WiFiMulti.cpp:84] addAP(): [WIFI][APlistAdd] add SSID: Wolles-FRITZBOX
[I][WiFiMulti.cpp:114] run(): [WIFI] scan done
[I][WiFiMulti.cpp:119] run(): [WIFI] 7 networks found
[I][WiFiMulti.cpp:160] run(): [WIFI] Connecting BSSID: 08:96:D7:FB:72:65 SSID: Wolles-FRITZBOX Channal: 11 (-28)
[W][WiFiGeneric.cpp:353] _eventCallback(): Reason: 202 - AUTH_FAIL
[E][WiFiMulti.cpp:184] run(): [WIFI] Connecting Failed.
[I][WiFiMulti.cpp:114] run(): [WIFI] scan done
[I][WiFiMulti.cpp:119] run(): [WIFI] 7 networks found
[I][WiFiMulti.cpp:160] run(): [WIFI] Connecting BSSID: 08:96:D7:FB:72:65 SSID: Wolles-FRITZBOX Channal: 11 (-31)
[I][WiFiMulti.cpp:174] run(): [WIFI] Connecting done.

Yes. But it doesnt reboot the ESP ;)

timothy3001 commented 5 years ago

Are there any news on this?

HendrikHo commented 4 years ago

Not fine, but this seems to work for me:

while (WiFi.status() != WL_CONNECTED) {
    WiFi.begin(c_wifi_ssid, c_wifi_psk);
    delay(1000);
    Serial.print(".")
ThePositronCode commented 4 years ago

WiFi.disconnect(); worked for me! Thank you so much @baaridunnasr

ElToberino commented 4 years ago

I'm also facing this annoying issue. Using the workaround with WiFi.begin() works for me, but that's not a really satisfying solution because I'd like to use the wifimanager library - that's not possible with this method.

The WiFi issue seems to depend on the router or AP the ESP32 connects to. I tested it with a "Netgear WN2000RPTv3" - the issue occurs and a connection is only established every second time. Connecting to an "Arcadyan ARV752DPW" shows a completely different result: the ESP32 always connects as expected and the issue doesn't occur at all.

I really hope someone will find the reason for this bug and find a solution !

bkgoodman commented 4 years ago

I too have this issue - but I am having much more difficult luck than most. It seems as though some combination of the disconnect, and deep-sleep reboot work - but sometimes it takes several reboots for that to happen. My AP is usually -70 to -50 dB.

I can't believe that this has gone on for SO LONG with so many people having connection issues...

BTW - BLE works flawlessly.

candelo commented 4 years ago

Using Wifi.disconnect() This works for me. Thanks.

void connectToNetwork() { uint8_t veces = 10; WiFi.begin(ssid, password); Serial.println("Establishing connection to WiFi.."); while (WiFi.status() != WL_CONNECTED) { delay(1000); Serial.println(veces); if (!veces--){ veces = 10; WiFi.disconnect(); Serial.println("Wifi reset..."); delay(1000); WiFi.begin(ssid, password); Serial.println("Establishing connection to WiFi.."); } } Serial.println("Connected to network"); }``

ElToberino commented 4 years ago

I'm not sure how ESP32 handles WiFi.begin(ssid, password) concerning the persistence of credentials. In former(!) ESP8266 versions this had been an issue there: Every time Wifi.begin() was called, the credentials were written to flash, even if they hadn't changed. Being not sure how ESP32 handles this I avoid writing the credentials into the sketch.

So I use the follwing code to handle both issues - the "only every second time connection" issue and the possible flash issue with WiFi.begin(ssid, password):

                                   // works on ESP8266 and ESP32 via  #ifdef ESP32

void wificonnect(){
   uint8_t  wifi_retry_count=0;                 // counter for connection attemps
  #ifdef ESP32
      while (WiFi.status() != WL_CONNECTED && wifi_retry_count < 3) {
  #else
      while (WiFi.waitForConnectResult() != WL_CONNECTED && wifi_retry_count < 3) {
  #endif
     Serial.print("Not yet connected...retrying - Attempt No. ");
     Serial.println(wifi_retry_count+1);
    WiFi.begin();
    delay(3000);                 // time between connection attemps - should be set according to situation 
    wifi_retry_count++;
    } 

    if(wifi_retry_count >= 3) {
        Serial.println("no connection, starting AP");
        WiFiManager wifiManager;                            // WiFiManager is used to write the credentials **once** 
        wifiManager.startConfigPortal("New_AP");
        Serial.println("AP started");
        }

    if (WiFi.waitForConnectResult() == WL_CONNECTED){
      Serial.println("Connected as");
      Serial.println(WiFi.localIP());
      }
  }

As you can see, I use WiFiManager to write the credentials once into the flash, so there's no need to write the credentials into the code. I use the development branch of WifiManager by tzapu which works fine for both, ESP8266 and ESP32.

hasenradball commented 4 years ago

Hello is there an final Solution for this topic?

muellerj commented 4 years ago

I can confirm that putting the WiFi.begin(...) inside the block bounded by while (WiFi.status() != WL_CONNECTED) works for me. Setup is similar to what the OP described with a Fritz!Box on the other end and hard-coded credentials.

1technophile commented 4 years ago

I confirm that making a loop on wifi.begin() with a short timer (500ms) works on OpenMQTTGateway, this loop is done just before the call to autoConnect call of WifiManager

ullix commented 4 years ago

I am also having this issue with all of my ESP32s (WROOM, WROVER, PICO). However, I think this is purely a router issue, and not enough attention is paid here for the type of router used. My router:

I had contacted FritzBox Support. They looked at the issue, and I tried a few Beta versions for the FritzBox7490 which they had provided, but nothing helped. Then support had given up on this. Today I installed latest FB firmware 07.19-77568 BETA, but also no improvement.

My work-around is to program a double-hitter for the WiFi: do a 1st begin(), then wait for ~1sec, then 2nd begin(). This also almost always works. But this can't be a serious solution to a modern device!

hasenradball commented 4 years ago

That is state of the art of the esp32 core!!! My proposal is that this wifi functionality should be updated to the wifi functionality to the state of the art of the esp8266 core.

rprimasta commented 4 years ago

Hi Guys, try this one, ESP32 will retry connecting after rising timeout about 10 seconds.

    Serial.begin(115200);
    pinMode(2,OUTPUT);
    digitalWrite(2,false);
    retry:  //<<<<<<<<<<<<<<<<<<<<<<<<<<< retry label added
    // Connect to wifi
    WiFi.begin(ssid, password);

    // Wait some time to connect to wifi, timeout 10 seconds
    for(int i = 0; i < 10 && WiFi.status() != WL_CONNECTED; i++) {
        Serial.print(".");
        delay(1000);
    }

    // Check if connected to wifi
    if(WiFi.status() != WL_CONNECTED) {
        Serial.println("No Wifi!");
        goto retry; //<<<<<<<<<<<<<<<<<<<<<<<< goto Retry if failed
    }
ElToberino commented 4 years ago

@rprimasta That isn't a new solution; it's just the same workaround described by many others in this topic: the repeated call of WiFi.begin().

A workaround like this shouldn't be necessary - WiFi.begin() should work at first attempt, regardless of the AP/router it connects to. Moreover, the autoconnect feature should even establish a connection before any call of WiFi.begin(), as it works flawlessly with an ESP8266.

All these workarounds here are nice and they work, but they significantly retard the connection process. Setting up the connection with an ESP32 does not work as intendend and it should be fixed; like some other annoying issues...

tablatronix commented 4 years ago

Have you all tried the following

I have been unable to reproduce this issue hence not found a solution or cause, which supports the claim that it is router involvement.

Also try disabling that multimedia thingy on the router, I forget the name if it.

1technophile commented 4 years ago

erase NVS

Yes

Disable sleep and test

Yes

Set Country code to proper country

No

Set STA and delay

Yes

It really depends on your router, a few weeks ago I was able to reproduce the issue with an Hitron router. Now that I have a netgear one it works flawlessly.

1technophile commented 4 years ago

I was asking myself if we should not put the workaround into WifiManager code. In my code I was able to handle all the restart case with the workaround, but when I use wifimanager web portal 1/2 times I need to reenter the credentials due to this issue (and I'm sure the credential are good each time).

kugelkopf123 commented 4 years ago

Anyone already tried the Countrycode idea?

tablatronix commented 4 years ago

There is a disconnect option, you can try that, its called cleanconnect, feel free to discuss in that issue linked above.

hasenradball commented 4 years ago

I dont know about the country code!

How to set it?

hasenradball commented 4 years ago

Question why is it not possible to do itcexactly like the ESP8266???

tablatronix commented 4 years ago

I think its, depends on your country, I am not seeing an example

https://github.com/espressif/arduino-esp32/blob/1977370e6fc069e93ffd8818798fbfda27ae7d99/tools/sdk/include/esp32/esp_wifi.h#L574-L598

/** @brief Structure describing WiFi country-based regional restrictions. */
typedef struct {
    char                  cc[3];   /**< country code string */
    uint8_t               schan;   /**< start channel */
    uint8_t               nchan;   /**< total channel number */
    int8_t                max_tx_power;   /**< This field is used for getting WiFi maximum transmitting power, call esp_wifi_set_max_tx_power to set the maximum transmitting power. */
    wifi_country_policy_t policy;  /**< country policy */
} wifi_country_t;
// how I do it in wm
// WIFI MUST BE INIT
const wifi_country_t WM_COUNTRY_US{"US",1,11,CONFIG_ESP32_PHY_MAX_TX_POWER,WIFI_COUNTRY_POLICY_AUTO};
bool ret = esp_wifi_set_country(&WM_COUNTRY_US) == ESP_OK;
tablatronix commented 4 years ago

fyi WMM is the wifi multimedia setting others have had issues with, it was brought up in other issues, it is a setting on some routers. That is all I know about it

tablatronix commented 4 years ago

Also since some of you actually enabled debugging

[W][WiFiGeneric.cpp:351] _eventCallback(): Reason: 202 - AUTH_FAIL

This is clearly something wrong with the SDK and handshaking, this is probably not user code or a bug, I mean its says AUTH FAIL!, without advanced wifi sniffing, I don't think anyone can hope to figure out analytically other than espressif.

hasenradball commented 4 years ago

And how looks it for Germany? Was is the effect of setting the country?

tablatronix commented 4 years ago

Country sets the wifi power and channels correctly for your country. Not sure how germany, but there are typically only a few variations.

const wifi_country_t WM_COUNTRY_US{"US",1,11,CONFIG_ESP32_PHY_MAX_TX_POWER,WIFI_COUNTRY_POLICY_AUTO};
const wifi_country_t WM_COUNTRY_CN{"CN",1,13,CONFIG_ESP32_PHY_MAX_TX_POWER,WIFI_COUNTRY_POLICY_AUTO};
const wifi_country_t WM_COUNTRY_JP{"JP",1,14,CONFIG_ESP32_PHY_MAX_TX_POWER,WIFI_COUNTRY_POLICY_AUTO};

This is a shot in the dark, but just wanted to make sure as it could be using channels that do not exist or something.

ullix commented 4 years ago

Germany allows 13 channels on 2.4GHz. This is a picture of current channel use on my router, a Fritz!box 7490, located in Germany. This is one of the trouble routers, that needs a double-hitter in order to connect ( but with the double hit does it reliably).

image

You see I am not even using channel 13, nor do I use channels 9, 10, 11, 12.

ullix commented 4 years ago

Out of curiosity I switched my router to channel 13. Was easily done, but my ESP32 had connection problems beyond double-hitter, did not connect, and crashed with stack-smashing. Must be something beyond the current issue?

Then I allowed the FB7490 to automatically chose the WiFi channel, and it choose channel 6: image The legend marks the light-blue channels 9...13 as "other radio signals". No idea what that means.

But on channel 6 I am back to the "reliable double-hitter" connection.

tablatronix commented 4 years ago

I was more interested in testing the esp code to see if it affected anything else, like rf cal etc. also some locale OS and routers will not allow or act differently since the client broadcasts its country as CN.

bkgoodman commented 4 years ago

Curious as to what people are using for hardware. I changed over to a completely different toolchain (Arduino vs. EspressIF) and my hardware, and didn't have this problem. Then when I changed back to the original hardware (with the new toolchain) - the problem came back, My theory is that it had to do with:

  1. The SparkFun ESP32 Thing board I was using - like a PCB, power or antenna issue
  2. The fact that the SparkFun ESP32 Thing used a 26MHz clock. (I saw some reference in ESP32 documentation that implied 40MHz was required for Wifi support). My working board used 40 MHz clock.

Does this possibly jive with anyone else's findings???

ullix commented 4 years ago

I hope to provide more insight with code which makes the double-hitting more efficient, and demonstrates that one-and-the-same code works bad on one router (FritzBox 7490), and fine on another (FritzBox 7272), and they are even from the same manufacturer AVM.

On my UECIDE IDE I've set the Debug level to verbose in order to catch WiFi messages. On my bad router I get this (some pseudo-code plus the Debug messages):

        // Bad router Fritz!Box 7490
            WiFi.begin(SSID, password);
            // loop checking Wifi.status()
        [D][WiFiGeneric.cpp:337] _eventCallback(): Event: 0 - WIFI_READY
        [D][WiFiGeneric.cpp:337] _eventCallback(): Event: 2 - STA_START
        [D][WiFiGeneric.cpp:337] _eventCallback(): Event: 5 - STA_DISCONNECTED
        [W][WiFiGeneric.cpp:353] _eventCallback(): Reason: 202 - AUTH_FAIL
            Check[ms:Status]: 0:6 100:6 200:6 300:6 400:6 500:6 600:6 700:6 800:4 Failed

            WiFi.begin(SSID, password);
            // loop checking Wifi.status()
        [D][WiFiGeneric.cpp:337] _eventCallback(): Event: 4 - STA_CONNECTED
        [D][WiFiGeneric.cpp:337] _eventCallback(): Event: 7 - STA_GOT_IP
        [D][WiFiGeneric.cpp:381] _eventCallback(): STA IP: 10.0.0.85, MASK: 255.255.255.0, GW: 10.0.0.1
            Check[ms:Status]: 0:4 100:4 200:4 300:4 400:4 500:4 600:4 700:4 800:3 Connected

After the first begin() I loop checking for WiFi.status() which is at 6 (WL_DISCONNECTED= 6) for 700ms, then changes to 4 (Failed). At this point I break out of the loop.

After the second begin() the status remains at Failed until 800ms, when it turns directly to 3 (Connected). This works almost-always, like 99 out of 100 times, and you can't go faster than that.

On the good router (though this one being too old for other reasons for being my main router) the very same code gives this:

        // Good router Fritz!Box 7272
            WiFi.begin(SSID, password);
            // loop checking Wifi.status()
        [D][WiFiGeneric.cpp:337] _eventCallback(): Event: 0 - WIFI_READY
        [D][WiFiGeneric.cpp:337] _eventCallback(): Event: 2 - STA_START
        [D][WiFiGeneric.cpp:337] _eventCallback(): Event: 4 - STA_CONNECTED
        [D][WiFiGeneric.cpp:337] _eventCallback(): Event: 7 - STA_GOT_IP
        [D][WiFiGeneric.cpp:381] _eventCallback(): STA IP: 192.168.188.32, MASK: 255.255.255.0, GW: 192.168.188.1
            Check[ms:Status]: 0:6 100:6 200:6 300:6 400:6 500:6 600:6 700:6 800:6 900:0 1000:3 Connected

After the first begin() the status is at 6 (Disconnected) for 800ms, then at 900ms changes to 0 (IDLE_STATUS), then at 1000ms is connected (3). No second round necessary. Again, it is almost-always like this using this router.

The relevant code used at both routers (without error checking) is this:

        // up to 5 rounds: 0, ..., 5
        WiFi.begin(SSID, password);
        while (true){
            uint16_t wifistatus = WiFi.status();
            if (wifistatus == WL_CONNECTED)                     {msg += "Connected"; success = true;  break;}
            if (wifistatus == WL_CONNECT_FAILED and round == 0) {msg += "Failed";    success = false; break;}
            delay(100);
        }

Where is the bug, in the routers or in the ESP32? Why is there a consistent Auth_fail in the bad example, when obviously the Auth info is correct?

The only difference I can see is that the good router goes through an Idle status, while the bad one goes directly to connect on the second attempt (which could be due to time resolution, but even when the time steps are made much smaller I have not seen an idle step, data not shown)

tablatronix commented 4 years ago

What happens if you instead of restarting, turn it off wait a bit then turn it back on everytime. I wonder if there is a timeout window on the router before the same client can reconnect.