Обзор
В этом руководстве вы узнаете о способе ручной настройки Wi-Fi ESP 8266, без необходимости прописывания учетных данных в скетче. Таким образом вы сможете подключать ваш ESP8266 к различным сетям WiFi без необходимости его перепрошивки. Для этих целей будет использована библиотека EEPROM. Альтернативой данному способу является библиотека ESP8266 Wifi-Manager, но здесь мы попробуем написать свою альтернативу, занимающую меньше памяти и подробно рассмотрим алгоритм ее работы.
Все продукты IoT работают по схожему алгоритму. Изначально они запускаются в режиме точки доступа. Затем вам нужно подключить свой телефон или компьютер к ней. После подключения , переходите к определенному IP-адресу (192.168.4.1), а затем вводите учетные данные Wifi, после чего устройство автоматически подключится к домашнему маршрутизатору или Wi-Fi. Таким образом, большинство устройств IoT построены с использованием ESP8266, который позволяет настраивать конфигурацию сети (например, SSID и пароль маршрутизатора WiFi) через форму и сохранять ее в памяти.
ESP8266 Ручная настройка WiFi с помощью EEPROM
Здесь мы создадим IoT устройство , используя ESP8266, которое позволит вам настроить конфигурацию сети (например, SSID и пароль WiFi-маршрутизатора) через форму и сохранить ее в памяти EEPROM. Это немного сложнее сделать, чем на платах Arduino. ESP8266 на самом деле не имеет EEPROM, как у всех настоящих плат Arduino. Вот почему большинству из нас трудно использовать библиотеку EEPROM с ESP8266.
Используя эту функцию, вам больше не нужно прописывать свои сетевые учетные данные (SSID и пароль) в скетче. Ваш ESP автоматически подключится к известной сети или настроит точку доступа, которую вы можете использовать для настройки сетевых учетных данных. Вот как работает этот процесс:
1. Когда ваш ESP8266 загружается, он настраивается в режиме станции и пытается подключиться к ранее сохраненной точке доступа (известная комбинация SSID и пароля).
2. Если этот процесс завершается неудачей, ESP переводится в режим точки доступа;
3. Используя любое устройство с поддержкой Wi-Fi и браузером, подключитесь к вновь созданной точке доступа.
4. После установления соединения с вновь созданной точкой доступа вы можете перейти на IP-адрес по умолчанию 192.168.4.1, чтобы открыть веб-страницу, которая позволяет настроить ваш SSID и пароль.
5. После установки новых SSID и пароля ESP перезагружается и пытается подключиться.
6. Если соединение установлено, процесс успешно завершен. В противном случае он будет настроен как точка доступа.
Что такое точка доступа?
Точка доступа - это устройство, которое создает беспроводную локальную сеть. Или WLAN, обычно в офисе или большом здании. Иногда точка доступа подключается к проводному маршрутизатору, коммутатору или концентратору через кабель Ethernet и проецирует сигнал Wi-Fi в выделенную область. Он также используется пользователями для настройки IoT устройств для первого использования или смены пароля.
Разбор программы и описание работы
Для начала мы рассмотрим, как записывать данные в память ESP8266.
Запись значений, отличных от целых чисел, в память ESP8266 может быть проблематичной. Основная причина заключается в том, что стандартная библиотека EEPROM не работает, потому что ESP8266 не имеет EEPROM. Библиотека, которую мы используем, просто эмулирует EEPROM, но в реальной жизни мы записываем данные во ФЛЭШ-память.
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <ESP8266WebServer.h>
#include <EEPROM.h>
//Variables
int i = 0;
int statusCode;
const char* ssid = "text";
const char* passphrase = "text";
String st;
String content;
//Function Decalration
bool testWifi(void);
void launchWeb(void);
void setupAP(void);
//Establishing Local server at port 80 whenever required
ESP8266WebServer server(80);
Все, что мы записываем в память ESP8266, должно быть строкой, и мы можем записывать их по одному символу за раз. Сначала мы объявляем строковую переменную с именем st и content, а также несколько целых чисел и const char * .
Затем мы объявим три разные функции как:
bool testWifi(void);
void launchWeb(void);
void setupAP(void);
Serial.begin(115200); //Initialising if(DEBUG)Serial Monitor
Serial.println();
Serial.println("Disconnecting previously connected WiFi");
WiFi.disconnect();
EEPROM.begin(512); //Initialasing EEPROM
delay(10);
pinMode(LED_BUILTIN, OUTPUT);
Serial.println();
Serial.println();
Serial.println("Startup");
Сначала запускается функция EEPROM с помощью EEPROM.begin(512) и устанавливается объем памяти в 512 ячеек. Следующий цикл по строковому значению.
String esid;
for (int i = 0; i < 32; ++i)
{
esid += char(EEPROM.read(i));
}
Serial.println();
Serial.print("SSID: ");
Serial.println(esid);
Serial.println("Reading EEPROM pass");
String epass = "";
for (int i = 32; i < 96; ++i)
{
epass += char(EEPROM.read(i));
}
Serial.print("PASS: ");
Serial.println(epass);
WiFi.begin(esid.c_str(), epass.c_str());
if (testWifi())
{
Serial.println("Succesfully Connected!!!");
return;
}
else
{
Serial.println("Turning the HotSpot On");
launchWeb();
setupAP();// Setup HotSpot
}
Serial.println();
Serial.println("Waiting.");
while ((WiFi.status() != WL_CONNECTED))
{
Serial.print(".");
delay(100);
server.handleClient();
}
Изначально ESP8266 настраивается в режиме станции и пытается подключиться к ранее сохраненной точке доступа из памяти EEPROM. Если точка доступа и сеть найдены, он подключится к ней.
Если этот процесс завершается неудачно, ESP8266 переводится в режим точки доступа и создается точка доступа.
void loop() {
if ((WiFi.status() == WL_CONNECTED))
{
for (int i = 0; i < 10; i++)
{
digitalWrite(LED_BUILTIN, HIGH);
delay(1000);
digitalWrite(LED_BUILTIN, LOW);
delay(1000);
}
}
else
{
}
В этом разделе вы можете добавить свой собственный код, какое бы действие вы ни хотели выполнить. На данный момент здесь просто мигание светодиодом.
void createWebServer()
{
{
server.on("/", []() {
IPAddress ip = WiFi.softAPIP();
String ipStr = String(ip[0]) + '.' + String(ip[1]) + '.' + String(ip[2]) + '.' + String(ip[3]);
content = "<!DOCTYPE HTML<\r\n<html<Hello from ESP8266 at ";
content += "<form action=\"/scan\" method=\"POST\"<<input type=\"submit\" value=\"scan\"<</form<";
content += ipStr;
content += "<p<";
content += st;
content += "</p<<form method='get' action='setting'<<label<SSID: </label<<input name='ssid' length=32<<input name='pass' length=64<<input type='submit'<</form<";
content += "</html<";
server.send(200, "text/html", content);
});
server.on("/scan", []() {
//setupAP();
IPAddress ip = WiFi.softAPIP();
String ipStr = String(ip[0]) + '.' + String(ip[1]) + '.' + String(ip[2]) + '.' + String(ip[3]);
content = "<!DOCTYPE HTML<\r\n<html<go back";
server.send(200, "text/html", content);
});
Используя любое устройство с поддержкой Wi-Fi и браузером, подключитесь к вновь созданной точке доступа. После установления соединения с вновь созданной точкой доступа вы можете перейти на IP-адрес по умолчанию 192.168.4.1, чтобы открыть веб-страницу, которая позволяет вам настроить свой SSID и пароль.
После установки нового SSID и пароля ESP перезагружается и пытается подключиться. Если он устанавливает соединение, процесс успешно завершен. В противном случае он будет настроен как точка доступа.
Полный код программы
Полный код программы находится здесь. С помощью этого кода ESP8266 Ручная настройка Wi-Fi с помощью EEPROM завершена.
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <ESP8266WebServer.h>
#include <EEPROM.h>
//Variables
int i = 0;
int statusCode;
const char* ssid = "text";
const char* passphrase = "text";
String st;
String content;
//Function Decalration
bool testWifi(void);
void launchWeb(void);
void setupAP(void);
//Establishing Local server at port 80 whenever required
ESP8266WebServer server(80);
void setup()
{
Serial.begin(115200); //Initialising if(DEBUG)Serial Monitor
Serial.println();
Serial.println("Disconnecting previously connected WiFi");
WiFi.disconnect();
EEPROM.begin(512); //Initialasing EEPROM
delay(10);
pinMode(LED_BUILTIN, OUTPUT);
Serial.println();
Serial.println();
Serial.println("Startup");
//---------------------------------------- Read EEPROM for SSID and pass
Serial.println("Reading EEPROM ssid");
String esid;
for (int i = 0; i < 32; ++i)
{
esid += char(EEPROM.read(i));
}
Serial.println();
Serial.print("SSID: ");
Serial.println(esid);
Serial.println("Reading EEPROM pass");
String epass = "";
for (int i = 32; i < 96; ++i)
{
epass += char(EEPROM.read(i));
}
Serial.print("PASS: ");
Serial.println(epass);
WiFi.begin(esid.c_str(), epass.c_str());
if (testWifi())
{
Serial.println("Succesfully Connected!!!");
return;
}
else
{
Serial.println("Turning the HotSpot On");
launchWeb();
setupAP();// Setup HotSpot
}
Serial.println();
Serial.println("Waiting.");
while ((WiFi.status() != WL_CONNECTED))
{
Serial.print(".");
delay(100);
server.handleClient();
}
}
void loop() {
if ((WiFi.status() == WL_CONNECTED))
{
for (int i = 0; i < 10; i++)
{
digitalWrite(LED_BUILTIN, HIGH);
delay(1000);
digitalWrite(LED_BUILTIN, LOW);
delay(1000);
}
}
else
{
}
}
//-------- Fuctions used for WiFi credentials saving and connecting to it which you do not need to change
bool testWifi(void)
{
int c = 0;
Serial.println("Waiting for Wifi to connect");
while ( c < 20 ) {
if (WiFi.status() == WL_CONNECTED)
{
return true;
}
delay(500);
Serial.print("*");
c++;
}
Serial.println("");
Serial.println("Connect timed out, opening AP");
return false;
}
void launchWeb()
{
Serial.println("");
if (WiFi.status() == WL_CONNECTED)
Serial.println("WiFi connected");
Serial.print("Local IP: ");
Serial.println(WiFi.localIP());
Serial.print("SoftAP IP: ");
Serial.println(WiFi.softAPIP());
createWebServer();
// Start the server
server.begin();
Serial.println("Server started");
}
void setupAP(void)
{
WiFi.mode(WIFI_STA);
WiFi.disconnect();
delay(100);
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) == ENC_TYPE_NONE) ? " " : "*");
delay(10);
}
}
Serial.println("");
st = "<ol>";
for (int i = 0; i < n; ++i)
{
// Print SSID and RSSI for each network found
st += "<li>";
st += WiFi.SSID(i);
st += " (";
st += WiFi.RSSI(i);
st += ")";
st += "(WiFi.encryptionType(i) == ENC_TYPE_NONE) ? " " : "*";
st += "</li>";
}
st += "</ol>";
delay(100);
WiFi.softAP("how2electronics", "");
Serial.println("softap");
launchWeb();
Serial.println("over");
}
void createWebServer()
{
{
server.on("/", []() {
IPAddress ip = WiFi.softAPIP();
String ipStr = String(ip[0]) + '.' + String(ip[1]) + '.' + String(ip[2]) + '.' + String(ip[3]);
content = "<!DOCTYPE HTML>\r\n<html>Hello from ESP8266 at ";
content += "<form action=\"/scan\" method=\"POST\"><input type=\"submit\" value="scan\"></form>";
content += ipStr;
content += "<p>";
content += st;
content += "</p><form method='get' action='setting'><label>SSID: </label><input name='ssid' type='text' length=32><input name='pass' type='text' length=64><input type='submit'></form>";
content += "</html>";
server.send(200, "text/html", content);
});
server.on("/scan", []() {
//setupAP();
IPAddress ip = WiFi.softAPIP();
String ipStr = String(ip[0]) + '.' + String(ip[1]) + '.' + String(ip[2]) + '.' + String(ip[3]);
content = "<!DOCTYPE HTML>\r\n<html>go back";
server.send(200, "text/html", content);
});
server.on("/setting", []() {
String qsid = server.arg("ssid");
String qpass = server.arg("pass");
if (qsid.length() > 0 && qpass.length() > 0) {
Serial.println("clearing eeprom");
for (int i = 0; i < 96; ++i) {
EEPROM.write(i, 0);
}
Serial.println(qsid);
Serial.println("");
Serial.println(qpass);
Serial.println("");
Serial.println("writing eeprom ssid:");
for (int i = 0; i < qsid.length(); ++i)
{
EEPROM.write(i, qsid[i]);
Serial.print("Wrote: ");
Serial.println(qsid[i]);
}
Serial.println("writing eeprom pass:");
for (int i = 0; i < qpass.length(); ++i)
{
EEPROM.write(32 + i, qpass[i]);
Serial.print("Wrote: ");
Serial.println(qpass[i]);
}
EEPROM.commit();
content = "{\"Success\":\"saved to eeprom... reset to boot into new wifi\"}";
statusCode = 200;
ESP.reset();
} else {
content = "{\"Error\":\"404 not found\"}";
statusCode = 404;
Serial.println("Sending 404");
}
server.sendHeader("Access-Control-Allow-Origin", "*");
server.send(statusCode, "application/json", content);
});
}
}