Как автоматически подключить ESP32 к самой сильной сети Wi-Fi
Одна из важнейших задач при использовании ESP32 — обеспечить его подключение к самой сильной доступной сети Wi-Fi. Это критически важно для поддержания оптимальной производительности и надёжности, особенно в средах с несколькими точками доступа (AP) и колеблющейся мощностью сигнала.
Существует два метода для достижения этой цели:
Базовый подход с RSSI
Использование библиотеки WiFiMulti (рекомендуется)
В этой статье мы подробно рассмотрим каждый метод, чтобы понять, как они работают и как вы можете реализовать их, чтобы ваш ESP32 всегда подключался к самой сильной доступной сети Wi-Fi.
Давайте начнём!
Метод 1 — Базовый подход с RSSI
В этом подходе ESP32 сканирует все доступные сети Wi-Fi в радиусе действия. Для каждой найденной сети ESP32 определяет индикатор уровня принимаемого сигнала (RSSI). Это показатель силы сигнала. RSSI — это отрицательное значение; чем ближе к 0, тем сильнее сигнал. ESP32 сравнивает значения RSSI всех сетей, выбирая сеть с самым сильным сигналом. После определения ESP32 пытается подключиться к выбранной сети.
Ниже приведён фрагмент кода для реализации этого метода.
Но прежде чем загружать его на ESP32, обязательно замените SSID-заполнители и пароли на ваши реальные учётные данные Wi-Fi.
// Replace with your network credentials
const char* ssidList[] = {"Network_1", "Network_2", "Network_3"};
const char* passwordList[] = {"password1", "password2", "password3"};
После внесения этих изменений загрузите код.
#include "WiFi.h"
// Replace with your network credentials
const char* ssidList[] = {"Network_1", "Network_2", "Network_3"};
const char* passwordList[] = {"password1", "password2", "password3"};
void setup() {
Serial.begin(115200);
WiFi.mode(WIFI_STA);
WiFi.disconnect();
delay(100);
Serial.println("Scanning for Wi-Fi networks...");
int n = WiFi.scanNetworks();
if (n == 0) {
Serial.println("No networks found.");
return;
}
int maxRSSI = -1000; // Initialize with a very low RSSI value
int bestNetworkIndex = -1;
for (int i = 0; i < n; ++i) {
int rssi = WiFi.RSSI(i);
Serial.printf("%d: %s, RSSI: %d\n", i + 1, WiFi.SSID(i).c_str(), rssi);
for (int j = 0; j < sizeof(ssidList)/sizeof(ssidList[0]); ++j) {
if (WiFi.SSID(i) == ssidList[j] && rssi > maxRSSI) {
maxRSSI = rssi;
bestNetworkIndex = j;
}
}
}
if (bestNetworkIndex == -1) {
Serial.println("No known networks found.");
} else {
Serial.printf("Connecting to the strongest network: %s\n", ssidList[bestNetworkIndex]);
WiFi.begin(ssidList[bestNetworkIndex], passwordList[bestNetworkIndex]);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\nConnected!");
Serial.printf("IP Address: %s\n", WiFi.localIP().toString().c_str());
}
}
void loop() {
// Nothing to do here
}
После загрузки откройте монитор порта на скорости 115200 бод и нажмите кнопку EN.
Вы увидите список ближайших сетей и соответствующие значения RSSI, отображённые в мониторе порта. ESP32 автоматически выберет и подключится к сети с самым сильным сигналом, на что указывает наибольшее (наименее отрицательное) значение RSSI в списке.
Объяснение кода
Код начинается с подключения библиотеки WiFi.h, которая необходима для работы с Wi-Fi на ESP32. Далее определяются два массива: ssidList и passwordList. Эти массивы хранят имена (SSID) и пароли сетей Wi-Fi, к которым вы хотите подключить ESP32. Обязательно замените значения-заполнители на ваши реальные учётные данные сети.
#include "WiFi.h"
// Replace with your network credentials
const char* ssidList[] = {"Network_1", "Network_2", "Network_3"};
const char* passwordList[] = {"password1", "password2", "password3"};
Функция setup() — это место, где происходит основное действие. Она инициализирует последовательную связь, позволяя вам видеть сообщения в мониторе порта, и устанавливает ESP32 в режим станции (STA), указывая, что он будет работать как Wi-Fi клиент, подключающийся к существующей сети. Затем код отключается от любого предыдущего соединения для чистого старта.
Serial.begin(115200);
WiFi.mode(WIFI_STA);
WiFi.disconnect();
Затем ESP32 начинает сканирование доступных сетей Wi-Fi в радиусе действия. Если сети не найдены, он просто выводит сообщение и останавливается. Если сети найдены, код входит в цикл для поиска самой сильной. Он измеряет RSSI (уровень сигнала) каждой сети и сравнивает его с переменной maxRSSI, которая начинается с очень низкого значения. Код отслеживает сеть с самым высоким RSSI среди указанных вами сетей.
int n = WiFi.scanNetworks();
if (n == 0) {
Serial.println("No networks found.");
return;
}
int maxRSSI = -1000; // Initialize with a very low RSSI value
int bestNetworkIndex = -1;
for (int i = 0; i < n; ++i) {
int rssi = WiFi.RSSI(i);
Serial.printf("%d: %s, RSSI: %d\n", i + 1, WiFi.SSID(i).c_str(), rssi);
for (int j = 0; j < sizeof(ssidList)/sizeof(ssidList[0]); ++j) {
if (WiFi.SSID(i) == ssidList[j] && rssi > maxRSSI) {
maxRSSI = rssi;
bestNetworkIndex = j;
}
}
}
После сканирования, если ни одна из ваших предпочтительных сетей не найдена, код выводит сообщение. В противном случае он выводит имя самой сильной сети и пытается подключиться, используя соответствующие учётные данные из массивов. ESP32 продолжает попытки подключения, отображая точки для индикации процесса, пока не подключится успешно или не истечёт время ожидания. После подключения выводится сообщение «Connected!» вместе с назначенным IP-адресом.
if (bestNetworkIndex == -1) {
Serial.println("No known networks found.");
} else {
Serial.printf("Connecting to the strongest network: %s\n", ssidList[bestNetworkIndex]);
WiFi.begin(ssidList[bestNetworkIndex], passwordList[bestNetworkIndex]);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\nConnected!");
Serial.printf("IP Address: %s\n", WiFi.localIP().toString().c_str());
}
Функция loop() в данном случае пуста, так как основная задача подключения к Wi-Fi выполняется в функции setup().
void loop() {
// Nothing to do here
}
Метод 2 — Использование библиотеки WiFiMulti (рекомендуется)
Во втором подходе мы используем библиотеку WiFiMulti. Эта библиотека упрощает управление несколькими сетями Wi-Fi. Вы добавляете учётные данные (SSID и пароли) ваших предпочтительных сетей в объект WiFiMulti. Когда вы вызываете wifiMulti.run(), он автоматически сканирует доступные сети и пытается подключиться к самой сильной из вашего списка. Если подключение не удаётся, он безшовно пробует следующую лучшую сеть, обеспечивая более надёжное соединение.
Ниже приведён фрагмент кода для реализации этого метода.
Не забудьте заменить SSID-заполнители и пароли на ваши реальные учётные данные сети перед загрузкой кода на ESP32.
#include <WiFi.h>
#include <WiFiMulti.h>
WiFiMulti wifiMulti;
// WiFi connect timeout per AP. Increase when connecting takes longer.
const uint32_t connectTimeoutMs = 10000;
void setup(){
Serial.begin(115200);
delay(10);
WiFi.mode(WIFI_STA);
// Add list of wifi networks
wifiMulti.addAP("ssid_1", "password_1");
wifiMulti.addAP("ssid_2", "password_2");
wifiMulti.addAP("ssid_3", "password_3");
// WiFi.scanNetworks will return the number of networks found
int n = WiFi.scanNetworks();
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(WiFi.SSID(i));
Serial.print(" (");
Serial.print(WiFi.RSSI(i));
Serial.print(")");
Serial.println((WiFi.encryptionType(i) == WIFI_AUTH_OPEN)?" ":"*");
delay(10);
}
}
// Connect to Wi-Fi using wifiMulti (connects to the SSID with strongest connection)
Serial.println("Connecting Wifi...");
if(wifiMulti.run() == WL_CONNECTED) {
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
}
void loop(){
//if the connection to the stongest hotstop is lost, it will connect to the next network on the list
if (wifiMulti.run(connectTimeoutMs) == WL_CONNECTED) {
Serial.print("WiFi connected: ");
Serial.print(WiFi.SSID());
Serial.print(" ");
Serial.println(WiFi.RSSI());
}
else {
Serial.println("WiFi not connected!");
}
delay(1000);
}
После загрузки откройте монитор порта на скорости 115200 бод и нажмите кнопку EN.
Вы увидите список ближайших сетей и соответствующие значения RSSI, отображённые в мониторе порта. ESP32 автоматически выберет и подключится к сети с самым сильным сигналом.
Но настоящая магия WiFiMulti заключается в способности адаптироваться. Если соединение с самой сильной сетью по какой-либо причине теряется, библиотека плавно переключается на следующую по силе сеть в вашем списке, обеспечивая подключение ESP32 даже в условиях нестабильного окружения.
Объяснение кода
Код начинается с подключения библиотек WiFi.h и WiFiMulti.h, которые необходимы для управления Wi-Fi соединениями на ESP32. Затем создаётся объект WiFiMulti, который будет использоваться для хранения и управления учётными данными нескольких сетей Wi-Fi.
#include <WiFi.h>
#include <WiFiMulti.h>
WiFiMulti wifiMulti;
Функция setup() устанавливает ESP32 в режим станции (STA) и добавляет список сетей Wi-Fi (пары SSID и пароль), к которым ESP32 должен пытаться подключиться, с помощью функции wifiMulti.addAP(). После этого выполняется сканирование доступных сетей Wi-Fi в окрестности. Если сети не найдены, выводится соответствующее сообщение. Однако если сети найдены, отображаются их данные, включая имена, уровни сигнала (RSSI) и типы защиты.
WiFi.mode(WIFI_STA);
// Add list of wifi networks
wifiMulti.addAP("ssid_1", "password_1");
wifiMulti.addAP("ssid_2", "password_2");
wifiMulti.addAP("ssid_3", "password_3");
// WiFi.scanNetworks will return the number of networks found
int n = WiFi.scanNetworks();
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(WiFi.SSID(i));
Serial.print(" (");
Serial.print(WiFi.RSSI(i));
Serial.print(")");
Serial.println((WiFi.encryptionType(i) == WIFI_AUTH_OPEN)?" ":"*");
delay(10);
}
}
После сканирования ESP32, используя функцию wifiMulti.run(), автоматически сканирует доступные сети и пытается подключиться к самой сильной из вашего списка. Если подключение успешно, выводится подтверждающее сообщение вместе с IP-адресом, назначенным ESP32 сетью.
if(wifiMulti.run() == WL_CONNECTED) {
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
Функция loop() — это место, где находится логика непрерывного мониторинга и переподключения. Она проверяет, подключён ли ESP32 к самой сильной сети. Если да, отображается имя текущей подключённой сети и уровень сигнала. Если соединение потеряно, автоматически выполняется попытка подключения к следующей по силе сети в вашем списке. Этот процесс повторяется непрерывно, обеспечивая, что ваш ESP32 всегда старается поддерживать наилучшее возможное соединение Wi-Fi.
void loop(){
//if the connection to the stongest hotstop is lost, it will connect to the next network on the list
if (wifiMulti.run(connectTimeoutMs) == WL_CONNECTED) {
Serial.print("WiFi connected: ");
Serial.print(WiFi.SSID());
Serial.print(" ");
Serial.println(WiFi.RSSI());
}
else {
Serial.println("WiFi not connected!");
}
delay(1000);
}
Какой метод выбрать?
В заключение, базовый подход с RSSI — это хорошая отправная точка. Однако если вам нужно более надёжное и гибкое решение, которое может автоматически подключаться к самой сильной сети из нескольких вариантов, выбирайте библиотеку WiFiMulti.