带存储和重置功能的 WiFiConFig
现在,让我们为这个示例添加更多功能,使其变得更加可靠。
在这个项目中,我们会将接收到的 Wi-Fi 凭据存储在 EEPROM/闪存中。因此,我们不需要每次都配置 ESP。
接下来,我们将添加一个小检查,例如 ESP 打开时;它将检索存储的 Wi-Fi 凭据并连接到 Wi-Fi 网络。
如果连接成功,则跳过进入 SmartConfig 模式。
此外,我们将使用启动按钮作为重置按钮。它将清除存储的 Wi-Fi 凭据并重新启动 ESP 以进行新配置。
需要长按开机键3秒以上再松开,重置配置成功。
这是完整的项目代码。
/*
Date: 11-08-21
Code is written by: Dharmik
Configure ESP32 Wi-Fi parameters using SmartConfig
Find more on www.TechTOnions.com
*/
#include "WiFi.h"
#include "EEPROM.h"
#define LENGTH(x) (strlen(x) + 1) // length of char string
#define EEPROM_SIZE 200 // EEPROM size
#define WiFi_rst 0 //WiFi credential reset pin (Boot button on ESP32)
String ssid; //string variable to store ssid
String pss; //string variable to store password
unsigned long rst_millis;
void setup() {
Serial.begin(115200); //Init serial
pinMode(WiFi_rst, INPUT);
if (!EEPROM.begin(EEPROM_SIZE)) { //Init EEPROM
Serial.println("failed to init EEPROM");
delay(1000);
}
else
{
ssid = readStringFromFlash(0); // Read SSID stored at address 0
Serial.print("SSID = ");
Serial.println(ssid);
pss = readStringFromFlash(40); // Read Password stored at address 40
Serial.print("psss = ");
Serial.println(pss);
}
WiFi.begin(ssid.c_str(), pss.c_str());
delay(3500); // Wait for a while till ESP connects to WiFi
if (WiFi.status() != WL_CONNECTED) // if WiFi is not connected
{
//Init WiFi as Station, start SmartConfig
WiFi.mode(WIFI_AP_STA);
WiFi.beginSmartConfig();
//Wait for SmartConfig packet from mobile
Serial.println("Waiting for SmartConfig.");
while (!WiFi.smartConfigDone()) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("SmartConfig received.");
//Wait for WiFi to connect to AP
Serial.println("Waiting for WiFi");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("WiFi Connected.");
Serial.print("IP Address: ");
Serial.println(WiFi.localIP());
// read the connected WiFi SSID and password
ssid = WiFi.SSID();
pss = WiFi.psk();
Serial.print("SSID:");
Serial.println(ssid);
Serial.print("PSS:");
Serial.println(pss);
Serial.println("Store SSID & PSS in Flash");
writeStringToFlash(ssid.c_str(), 0); // storing ssid at address 0
writeStringToFlash(pss.c_str(), 40); // storing pss at address 40
}
else
{
Serial.println("WiFi Connected");
}
}
void loop() {
// put your main code here, to run repeatedly:
rst_millis = millis();
while (digitalRead(WiFi_rst) == LOW)
{
// Wait till boot button is pressed
}
// check the button press time if it is greater than 3sec clear wifi cred and restart ESP
if (millis() - rst_millis >= 3000)
{
Serial.println("Reseting the WiFi credentials");
writeStringToFlash("", 0); // Reset the SSID
writeStringToFlash("", 40); // Reset the Password
Serial.println("Wifi credentials erased");
Serial.println("Restarting the ESP");
delay(500);
ESP.restart(); // Restart ESP
}
}
void writeStringToFlash(const char* toStore, int startAddr) {
int i = 0;
for (; i < LENGTH(toStore); i++) {
EEPROM.write(startAddr + i, toStore[i]);
}
EEPROM.write(startAddr + i, '\0');
EEPROM.commit();
}
String readStringFromFlash(int startAddr) {
char in[128]; // char array of size 128 for reading the stored data
int i = 0;
for (; i < 128; i++) {
in[i] = EEPROM.read(startAddr + i);
}
return String(in);
}
代码如何工作
首先,我们将包含该项目所需的所有库。
- WiFi.h 库将处理所有与 wifi 相关的任务,例如连接到您的 Wi-Fi 和 SmartConfig。
- EEPROM.h 库需要将数据存储到 ESP32 的 EEPROM/闪存中。
#include “WiFi.h”
#include “EEPROM.h”
定义自定义函数 LENGTH(x) 将为我们提供一个增量为 char 字符串的长度。稍后我们将使用此功能。
并将所需的 EEPROM 大小定义为 EEPROM_SIZE。
#define LENGTH(x) (strlen(x) + 1) // length of char string
#define EEPROM_SIZE 200 // EEPROM size
我们正在使用 ESP32 板的启动按钮来重置 Wi-Fi 凭据设置。ESP32 板上的开机按钮与 GPIO0 引脚相连,并带有上拉电阻。
因此,我们将 WiFi_rst 定义为 0。如果您使用任何其他引脚作为重置按钮,则需要将该 GPIO 编号添加到 WiFi_rst 变量中。
#define WiFi_rst 0 //WiFi credential reset pin (Boot button on ESP32)
我们正在定义用于检索 SSID 和密码的字符串变量。
此外,我们将使用 rst_millis 变量来计算按下重置按钮的时间。
String ssid; //string variable to store ssid
String pss; //string variable to store password
unsigned long rst_millis;
设置()
我们将使用所需的波特率初始化串行通信。
Serial.begin(115200); //Init serial
将 WiFi_rst 引脚设置为输入引脚。
pinMode(WiFi_rst, INPUT);
现在,使用预定义的 EEPROM_SIZE 初始化 EEPROM。
初始化后,我们将分别在地址 0 和 40 处将存储的 SSID 和密码读取为字符串。
我们使用名为 readStringFromFlash() 的用户定义函数从 EEPROM/闪存中读取字符串。
if (!EEPROM.begin(EEPROM_SIZE)) { //Init EEPROM
Serial.println(“failed to init EEPROM”);
delay(1000);
}
else
{
ssid = readStringFromFlash(0); // Read SSID stored at address 0
Serial.print(“SSID = “);
Serial.println(ssid);
pss = readStringFromFlash(40); // Read Password stored at address 40
Serial.print(“psss = “);
Serial.println(pss);
}
使用 Wi-Fi.begin 功能连接到 Wi-Fi 网络。我们将 Wi-Fi 凭据作为字符串变量传递;因此,我们将需要使用 c_str(),它将返回一个指向以空字符结尾的字符串的 const char*。
我们将添加一点延迟,以便 ESP 可以连接到 Wi-Fi 网络。
WiFi.begin(ssid.c_str(), pss.c_str());
delay(3500); // Wait for a while till ESP connects to WiFi
延迟之后,我们将检查 ESP32 是否连接到 Wi-Fi。
如果 ESP 连接到 Wi-Fi,那么我们将跳过 if 条件中的 SmartConfig 代码。
如果它与 Wi-Fi 连接失败,我们将启动 Wi-Fi Station 模式和 SmartConfig,与前面的示例类似。
if (WiFi.status() != WL_CONNECTED) // if WiFi is not connected
{
//Init WiFi as Station, start SmartConfig
WiFi.mode(WIFI_AP_STA);
WiFi.beginSmartConfig();
使用while 循环等待 SmartConfig 数据到达 。网络凭据到达后,它将尝试连接到该 Wi-Fi 网络。
//Wait for SmartConfig packet from mobile
Serial.println(“Waiting for SmartConfig.”);
while (!WiFi.smartConfigDone()) {
delay(500);
Serial.print(“.”);
}
Serial.println(“”);
Serial.println(“SmartConfig received.”);
//Wait for WiFi to connect to AP
Serial.println(“Waiting for WiFi”);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(“.”);
}
Serial.println(“WiFi Connected.”);
Serial.print(“IP Address: “);
Serial.println(WiFi.localIP());
连接 Wi-Fi 后,我们将通过以下函数读取连接的 Wi-Fi SSID 和密码。
ssid = WiFi.SSID();
pss = WiFi.psk();
Serial.print(“SSID:”);
Serial.println(ssid);
Serial.print(“PSS:”);
Serial.println(pss);
我们将使用另一个用户定义的函数 writeStringToFlash() 来存储新凭据。 我们只需要传递字符串数据和地址。
Serial.println(“Store SSID & PSS in Flash”);
writeStringToFlash(ssid.c_str(), 0); // storing ssid at address 0
writeStringToFlash(pss.c_str(), 40); // storing pss at address 40
环形()
在循环函数内部,我们将当前的millis()值存储在 rst_millis 变量中,因为当有人按下 Wi-Fi 重置按钮时,我们将使用该值作为开始时间。
rst_millis = millis();
当我们按下 Boot 按钮时, while 循环 条件就满足了。因此,代码被困在循环中,直到按钮被释放。
while (digitalRead(WiFi_rst) == LOW)
{
// Wait till boot button is pressed
}
当按钮立即松开时,我们将检查我们按下按钮的时间,如果时间大于 3000mS, 则满足if 条件 。
if (millis() – rst_millis >= 3000)
现在我们将通过将空白值传递给 writeStringToFlash() 函数来擦除地址 0 和 40 处存储的 Wi-Fi 凭据。
Serial.println(“Reseting the WiFi credentials”);
writeStringToFlash(“”, 0); // Reset the SSID
writeStringToFlash(“”, 40); // Reset the Password
Serial.println(“Wifi credentials erased”);
最后,我们将使用以下命令触发对 ESP32 的软件复位。
Serial.println(“Restarting the ESP”);
delay(500);
ESP.restart(); // Restart ESP
writeStringToFlash(const char* toStore, int startAddr)
该用户自定义函数将字符串或字符数组指针存储在 ESP32 的 EEPROM/Flash 存储器中。
我们需要将其存储在非易失性存储器中;因此即使电源关闭,存储的数据也不会被删除。
如果我们仔细看这个函数的代码,它只是一个 for 循环。 它根据 LENGTH() 函数输入执行,如前所述,它将提供字符串的长度。
我们将使用 EEPROM.write() 函数将字符串的每个字节存储到传递的特定地址,并且地址保持递增。
一旦 执行了 for 循环 ,我们将保存一个 ‘\0’ 作为字符串终止符。并将提交更改,以便将它们全部存储在内存中。
void writeStringToFlash(const char* toStore, int startAddr) {
int i = 0;
for (; i < LENGTH(toStore); i++) {
EEPROM.write(startAddr + i, toStore[i]);
}
EEPROM.write(startAddr + i, ‘\0’);
EEPROM.commit();
}
字符串 readStringFromFlash(int startAddr)
此用户定义函数从 EEPROM/闪存中的所需地址读取存储的字符串。
这里我们将char数组名初始化为 in[128] ,它的大小为128,这意味着它只能处理小于128的字符串长度。如果需要处理更大的字符串,可以增加大小。
与存储函数类似,它也适用于 for 循环。它将从startAddr (起始地址)开始 一个接一个地读取所有字符 。
最后,我们将以字符串的形式返回它。
String readStringFromFlash(int startAddr) {
char in[128]; // char array of size 128 for reading the stored data
int i = 0;
for (; i < 128; i++) {
in[i] = EEPROM.read(startAddr + i);
}
return String(in);
}
包起来
我们已经看到 SmartConfig 是在我们基于 ESP32 的物联网项目或设备中配置网络凭据的一种非常有效且直接的方法。
对于配置,ESP32 不需要 Wi-Fi 管理器所需的任何连接的 Wi-Fi 网络。
我们已经使用标准 Wi-Fi 路由器测试了 SmartConfig,它的工作原理非常棒。
- 本文固定链接: http://iprocessing.cn/2022/05/14/3047/
- 转载请注明: 卡萨布兰卡 于 Processing编程艺术 发表