Establish WiFi connection to AP with strongest radio signal

Thomas Peter
Posts: 5
Joined: Tue Jan 12, 2021 11:04 pm

Establish WiFi connection to AP with strongest radio signal

Postby Thomas Peter » Tue Jan 12, 2021 11:23 pm

Dear all,

I started a week ago with ESP32-Camera module (AI Thinker) and the application should send a photo by eMail every once in a while. The code is generally working, however, I have huge problems with the WiFi connection.

We live an a large farmers house with barns ad I need fife AP (all with the same SSID) to get good coverage of the property. The network is set up with a FritzBox using Fritz Mesh. It works perfect with all our mobile devices ...

I have a simple code basically unsing WiFi.begin(SSID, PWD) to connect to WiFi.

What I discover is, that the ESP32 connects in an unpredictable way to any on the APs and most often to those far away. This leads to very poor network speed and often, connection is lost during eMial sending.

I googled a lot and found that people frequently report such issues since years but I did not find any working solution. I even tried to Connect with WiFi.begin(SSID, pwd, 0, Bssid) and selected the Bssid of the AP which was just two meters away - this did not get any connection at all.

Does anybody know a working solution for a networks with several AP with the same SSID and getting the ESP32 connecting automatically to the strongest AP or is it known the the ESP32 with the WiFi.h lib is useless in such a network?

Thanks al lot for a working solution,

Thomas

Radu79
Posts: 29
Joined: Tue Nov 17, 2020 9:50 pm

Re: Establish WiFi connection to AP with strongest radio signal

Postby Radu79 » Wed Jan 13, 2021 9:51 am

I have the same module, and like others I am experiencing wifi issues even with the board a few feet from the router (the only router).
I think it is a hardware issue, because other boards, like the m5stack camera board works fine.

Thomas Peter
Posts: 5
Joined: Tue Jan 12, 2021 11:04 pm

Re: Establish WiFi connection to AP with strongest radio signal

Postby Thomas Peter » Wed Jan 13, 2021 10:47 am

Hi Radu79,

thanks - does this mean that other ESP32 boards do actually connect automatically to the strongest AP at a given SSID? It is hard for me to think of an hardware issue as connecting to the strongest AP needs the implementation of a proper algorithm to 1st scan the network for all available APs and then connect to the one with highest signal strength.

As a side note: I downloaded a short sketch that does a scan and it shows all available APs with SSID and signal strength. So, the Module „Sees“ the APs, but it does not connect to the strongest AP.

Unfortunately, I was unable to get the BSSID of the different APs in this scan. And even when knowing the BSSID of a specific AP, I was unable to connect to that particular AP. WiFi.begin(SSID, Password, 0, Bssid) did not work at all.

If someone knows how to scan the wlan for all APs including the BSSIDs and then connecting to a specific BSSID, I could easily write the algorithm that finds the strongest and connect. However, I am completely stuck now:

- the ESP32 does not automatically to the strongest AP
- I can scan the network and I find all APs, but I get only the SSID and Signal strength, but no BSSID, so, I can’t distinguish between the different APs (with identical SSID but different location and therefore different signal strength)
- even if I know the BSSID from the router, I can’t connect to that AP by using the BSSID.

So many great things work easily with ESP32 but I am surprised that such a simple thing like connecting to the strongest AP in a network with several APs with identical SSID dies not simply work ...

Thomas Peter
Posts: 5
Joined: Tue Jan 12, 2021 11:04 pm

Re: Establish WiFi connection to AP with strongest radio signal

Postby Thomas Peter » Wed Jan 13, 2021 3:35 pm

I checked the WiFi connection now with an ESP32 dev board, no camera. Same problem, so, not linked to the camera. I checked with the following code and from the results one can see:

As one can see:
- I want to connect to Laengenau network
- there are 5 AP with this SSID visible
- one with 100% is only 2 m away from the ESP
- the other fife are much further away and have only a weak signal
- the ESP almost never connects to the strongest one right next to it, it chooses one of the weaker APs
- I don’t get the BSSID and I can’t connect to anspecific AP using the BSSID

  1.  
  2. #include <WiFi.h>
  3.  
  4. #include "TD_Credentials.h"
  5.  
  6. byte bssid[] = {0x32, 0xC9, 0x29, 0xAB, 0x91, 0x4E}; // Repeater FeWo, 2.4 GHz
  7. //byte bssid[] = {0x4E, 0x91, 0xAB, 0x29, 0xC9, 0x32}; // Repeater FeWo, 2.4 GHz
  8.  
  9. void setup()
  10. {
  11.  
  12.   int i = 0;
  13.   Serial.begin(115200);
  14.   Serial.println("----------------- Start Setup --------------");
  15.  
  16.   scanNetwork();
  17.  
  18.   WiFi.begin(ssid, password);
  19.   //WiFi.begin(ssid, password, 0, bssid); // was hoping to connect die an AP with defined BSSID - dies not work ...
  20.  
  21.   Serial.print("Connecting ");
  22.   while ((WiFi.status() != WL_CONNECTED) && (i < 500)) {
  23.     delay(500);
  24.     Serial.print(".");
  25.     i++;
  26.   }
  27.  
  28.   Serial.println("!");
  29.  
  30.   Serial.println();
  31.  
  32.   Serial.print(WiFi.SSID());
  33.   Serial.print(" (");
  34.   Serial.print(WiFi.RSSI());
  35.   Serial.print("dBm, ");
  36.   Serial.print(constrain(2 * (WiFi.RSSI() + 100), 0, 100));
  37.   Serial.print("%)      ");
  38.   Serial.println();
  39.  
  40.   // shoud print the MAC address of the router you're attached to, does not work!!!!
  41.   byte bssid[6];
  42.   WiFi.BSSID(*bssid);
  43.   Serial.print("BSSID: ");
  44.   Serial.print(bssid[5], HEX);
  45.   Serial.print(":");
  46.   Serial.print(bssid[4], HEX);
  47.  Serial.print(":");
  48.   Serial.print(bssid[3], HEX);
  49.   Serial.print(":");
  50.   Serial.print(bssid[2], HEX);
  51.   Serial.print(":");
  52.   Serial.print(bssid[1], HEX);
  53.   Serial.print(":");
  54.   Serial.println(bssid[0], HEX);
  55.   Serial.println("----------------- End Setup --------------");
  56. }
  57.  
  58. void scanNetwork()
  59. {
  60.   Serial.println("scan start");
  61.   byte bssid[6];
  62.   int n = WiFi.scanNetworks(); // WiFi.scanNetworks will return the number of networks found
  63.   Serial.println("scan done");
  64.   if (n == 0) {
  65.     Serial.println("no networks found");
  66.   } else {
  67.     Serial.print(n);
  68.     Serial.println(" networks found");
  69.     for (int i = 0; i < n; ++i) {
  70.       // Print SSID and RSSI for each network found
  71.       Serial.print(i + 1);
  72.       Serial.print(": ");
  73.       Serial.print(WiFi.SSID(i));
  74.       Serial.print(" (");
  75.       Serial.print(WiFi.RSSI(i));
  76.       Serial.print("dBm, ");
  77.       Serial.print(constrain(2 * (WiFi.RSSI(i) + 100), 0, 100));
  78.       Serial.print("%)      ");
  79.  
  80.       WiFi.BSSID(*bssid);
  81.       Serial.print("BSSID: ");
  82.       Serial.print(bssid[5], HEX);
  83.       Serial.print(":");
  84.       Serial.print(bssid[4], HEX);
  85.       Serial.print(":");
  86.       Serial.print(bssid[3], HEX);
  87.       Serial.print(":");
  88.       Serial.print(bssid[2], HEX);
  89.       Serial.print(":");
  90.       Serial.print(bssid[1], HEX);
  91.       Serial.print(":");
  92.       Serial.print(bssid[0], HEX);
  93.       Serial.println((WiFi.encryptionType(i) == WIFI_AUTH_OPEN) ? " open" : " encrypted");
  94.       delay(10);
  95.     }
  96.   }
  97.   Serial.println("");
  98.  
  99.  
  100. }
  101. void loop () {}
  102.  
I get the following result:
  1.  
  2. ----------------- Start Setup --------------
  3. scan start
  4. scan done
  5. 10 networks found
  6. 1: Laengenau (-46dBm, 100%)      BSSID: 0:0:0:0:0:0 encrypted
  7. 2: Dennerguest (-47dBm, 100%)      BSSID: 0:0:0:0:0:0 encrypted
  8. 3: Laengenau (-74dBm, 52%)      BSSID: 0:0:0:0:0:0 encrypted
  9. 4: Dennerguest (-75dBm, 50%)      BSSID: 0:0:0:0:0:0 encrypted
  10. 5: Laengenau (-85dBm, 30%)      BSSID: 0:0:0:0:0:0 encrypted
  11. 6: Dennerguest (-87dBm, 26%)      BSSID: 0:0:0:0:0:0 encrypted
  12. 7: Laengenau (-88dBm, 24%)      BSSID: 0:0:0:0:0:0 encrypted
  13. 8: Dennerguest (-89dBm, 22%)      BSSID: 0:0:0:0:0:0 encrypted
  14. 9: Dennerguest (-90dBm, 20%)      BSSID: 0:0:0:0:0:0 encrypted
  15. 10: Laengenau (-93dBm, 14%)      BSSID: 0:0:0:0:0:0 encrypted
  16.  
  17. Connecting .!
  18.  
  19. Laengenau (-74dBm, 52%)    
  20. BSSID: 0:0:0:0:0:0
  21.  
  22. ----------------- End Setup --------------
  23.  

Any help much appreciated.

felmue
Posts: 68
Joined: Mon Nov 16, 2020 2:55 pm

Re: Establish WiFi connection to AP with strongest radio signal

Postby felmue » Wed Jan 13, 2021 4:40 pm

Hello Thomas

I don't have a ready made solution, but if you look at https://github.com/espressif/arduino-es ... WiFiScan.h you'll see the WiFi API, eg.

Code: Select all

String BSSIDstr(uint8_t networkItem);

And calling

Code: Select all

WiFi.BSSIDstr(i);
should give you the BSSID string of the scanned AP whereas

Code: Select all

WiFi.BSSID(i);
gives you the BSSID pointer needed for

Code: Select all

WiFi.begin()
Cheers
Felix

Thomas Peter
Posts: 5
Joined: Tue Jan 12, 2021 11:04 pm

Re: Establish WiFi connection to AP with strongest radio signal

Postby Thomas Peter » Fri Jan 15, 2021 5:57 am

Hi Felix,

thanks for the help - I got it working now and I will post the solution here after some cleanup.

Thomas

cerealkillers
Posts: 1
Joined: Sat Feb 06, 2021 9:22 pm

Re: Establish WiFi connection to AP with strongest radio signal

Postby cerealkillers » Sat Feb 06, 2021 9:24 pm

I'm very interested to see your implementation. Thanks :)

Thomas Peter
Posts: 5
Joined: Tue Jan 12, 2021 11:04 pm

Re: Establish WiFi connection to AP with strongest radio signal

Postby Thomas Peter » Sun Feb 07, 2021 2:24 pm

Hi there,

I am happy to share my solution, not as a complete sketch but with two procedures that are useful. There are some #definitions needed which I hope speak for themselves.

connect2nearestAP does hat it says: scanning the network for all available SSIDs on all APs (the list is fortunately sorted from stronest to weakest) and connects to the first/strongest with matching SSID.

checkWiFi is helpful if the ESP is moving around and the nearest AP is changing. This routine should be called on a regular basis and/or if highest thruput is needed (e.g. you want to send an eMail with attachments). This routine checks if the strengths is above a certain tresold - if not, it calls connect2nearestAP.

The code looks awkward in many places - one reason ist that I started programming in C only a few month ago The other is, that there are many flaws in the ESP WiFi realization, especially in the ESP-CAM-Module. So, when I call routines again and agian, make delays, ... than this is the distillation of things I found in different discussions about the unreliable ESP32 WiFi ... with all these things it works now mostly reliable on three ESP32-CAM. And yes, my three ESP32-CAM modules do not behave in the same way. One connects to WiFi only every second reboot, one has a significantly lower signal strength than the other two. But if you google around, it seems to be normal ...


Code: Select all


#define MaxSecWiFi 30       // max time in s for WiFi setup, function will return WiFiErrorCode if WiFi was not successful.
#define WiFiErrorCode 1000  // see above
#define SaveDisconnectTime 1000 // Time im ms for save disconnection, needed to avoid that WiFi works only evey secon boot: https://github.com/espressif/arduino-esp32/issues/2501
#define WiFiTime 10    // Max time in s for successful WiFi connection.
#define WiFiOK 0       // WiFi connected
#define WiFiTimedOut 1 // WiFi connection timed out
#define WiFiNoSSID 2   // The SSID was not found during network scan
#define WiFiRSSI -75   // Min. required signal strength for a good WiFi cennection. If lower, new scan is initiated in checkWiFi()

int connect2nearestAP()
{

  // this routine disconnects from WiFi, scans the network for the strongest AP at the defined SSID and tries to connect. returns WiFiOK, WiFiTimedOut, or WiFiNoSSID

  int n;
  int i = 0;

  // the following awkward code seems to work to avoid the following bug in ESP32 WiFi connection: https://github.com/espressif/arduino-esp32/issues/2501
  WiFi.disconnect(true); // delete old config
  WiFi.persistent(false); //Avoid to store Wifi configuration in Flash
  WiFi.mode(WIFI_OFF);
  WiFi.mode(WIFI_STA);
  WiFi.disconnect(true); // delete old config
  WiFi.setHostname(HostName);
  WiFi.begin();
  delay(SaveDisconnectTime); // 500ms seems to work in most cases, may depend on AP
  WiFi.disconnect(true); // delete old config

  Serial.println("scan start");
  n = WiFi.scanNetworks(); // WiFi.scanNetworks will return the number of networks found
  Serial.println("scan done");

  if (n == 0) {
    Serial.println("no networks found");
  } else {
    Serial.print(n);
    Serial.println(" networks found");
    for (int i = 0; i < n; ++i) {
      // Print SSID and RSSI for each network found
      Serial.print(i + 1);
      Serial.print(": ");
      Serial.print("BSSID: ");
      Serial.print(WiFi.BSSIDstr(i));
      Serial.print("  ");
      Serial.print(WiFi.RSSI(i));
      Serial.print("dBm, ");
      Serial.print(constrain(2 * (WiFi.RSSI(i) + 100), 0, 100));
      Serial.print("% ");
      Serial.print((WiFi.encryptionType(i) == WIFI_AUTH_OPEN) ? "open       " : "encrypted  ");
      Serial.println(WiFi.SSID(i));
      delay(10);
    }
  }
  Serial.println();

  //  while ( !strcmp(ssid, &WiFi.SSID(i)) && (i < n)) {
  while ( String(ssid) != String(WiFi.SSID(i)) && (i < n)) {
    i++;
  }

  if (i == n) {
    Serial.print("No network with SSID ");
    Serial.println(ssid);
    Serial.print(" found!");
    return WiFiNoSSID;
  }

  Serial.print("SSID match found at: ");
  Serial.println(i + 1);

  WiFi.setHostname(HostName);
  WiFi.begin(ssid, password, 0, WiFi.BSSID(i));
  i = 0;
  Serial.print("Connecting ");
  while ((WiFi.status() != WL_CONNECTED) && (i < WiFiTime * 10)) {
    delay(100);
    Serial.print(".");
    i++;
  }

  Serial.println();

  if (WiFi.status() != WL_CONNECTED) {
    Serial.print("Connection to ");
    Serial.print(ssid);
    Serial.println(" timed out! ");
    return WiFiTimedOut;
  }


  Serial.print("Connected to BSSID: ");
  Serial.print(WiFi.BSSIDstr());
  Serial.print("  ");
  Serial.print(WiFi.RSSI());
  Serial.print("dBm, ");
  Serial.print(constrain(2 * (WiFi.RSSI() + 100), 0, 100));
  Serial.print("% ");
  Serial.print(WiFi.SSID());
  Serial.print(" IP: ");
  Serial.println(WiFi.localIP());

  return (WiFiOK);
}

void checkWiFi() { // Check the signal strength of the connection - if too low, reconnect to the strongest AP; good if the ESP is moving around and reconnection to the nearest AP makes sense
  int i = 1;
  if ((WiFi.status() == WL_CONNECTED) && (WiFi.RSSI() > WiFiRSSI) && (WiFi.RSSI() < -25)) { // good connection
    Serial.print("Connection good: ");
    Serial.print(WiFi.RSSI());
    Serial.print("dBm, ");
    Serial.print(constrain(2 * (WiFi.RSSI() + 100), 0, 100));
    Serial.print("% ");
    Serial.println(" ... keep geoing");
    return;
  }
  while (connect2nearestAP() != WiFiOK) {
    Serial.print("connect2nearestAP was called #");
    Serial.println(i);
    delay(1000);
    i++;
    if (i > 10) {
      Serial.println("Rebooting cause WiFi setup failes");
      ESP.restart();
    }
  }
}


FluxGS
Posts: 21
Joined: Sun Mar 18, 2018 7:01 am

Re: Establish WiFi connection to AP with strongest radio signal

Postby FluxGS » Mon Aug 08, 2022 5:25 pm

Hello and I am glad that your solution is working.
May I suggest our solution as an alternative.
We have a situation where there are many AP's throughout our facility with the same SSID.
It is important for our esp32 device to connect to the strongest AP with the appropriate SSID.

To accomplish this we simply set the sort method for AP selection to WIFI_CONNECT_AP_BY_SIGNAL
See below.
We also found it important to select ALL_CHANNEL_SCAN so it did not stop on the first match, which may nbot be the strongest signal.

wifi_config_t sta_config = {
.sta = {
.ssid = CONNECT_TO_SSID,
.password = CONNECT_TO_PW,
.scan_method = WIFI_ALL_CHANNEL_SCAN,
.sort_method = WIFI_CONNECT_AP_BY_SIGNAL,
.bssid_set = false
}

I hope this may also help.
Regards
};

kristian32
Posts: 2
Joined: Sat Mar 06, 2021 7:14 pm

Re: Establish WiFi connection to AP with strongest radio signal

Postby kristian32 » Tue Sep 20, 2022 8:48 am

@FluxGS we have also tried this method, but it is still connecting to AP with a weaker RSSI value. Do you have any clue why is that? We are using esp-idf version 4.4.2.

Any help would be much appreciated!

Thank you,

Best regards

S

Who is online

Users browsing this forum: No registered users and 15 guests