WiFi.h library will take care of all wifi-related tasks like connecting to
your Wi-Fi and SmartConfig.
#include "WiFi.h"
setup()
Inside the setup function, we will first initialize serial communication to
observe data in a serial monitor.
We are using the default baud rate of 115200. But you can change it if you want.
Serial.begin( 115200 );
Start SmartConfig
Before starting SmartConfig, it is mandatory to put ESP into station mode.
Therefore setting Wi-Fi mode as WIFI_AP_STA.
WiFi.mode( WIFI_AP_STA );
Now, turn ON SmartConfig by using this command.
WiFi.beginSmartConfig();
And now we will be wait in while the loop until SmartConfig data is received. It
means that it will stay in an infinite loop until someone configures it again
with a mobile app. Therefore, making it a drawback of this particular example.
You will see a continuous dot in the serial monitor when ESP enters in this
while loop.
while( !WiFi.smartConfigDone() )
{
delay( 500 );
Serial.print( "." );
}
Serial.println( "" );
Serial.println( "SmartConfig received." );
Once you successfully configure Wi-Fi credentials, it will automatically try to
connect to the given Wi-Fi credentials.
It will enter in another while loop until it gets connected to Wi-Fi.
Serial.println( "Waiting for WiFi" );
while( WiFi.status() != WL_CONNECTED )
{
delay( 500 );
Serial.print( "." );
}
After connection, we will be serial printing the Wi-Fi connected message along
with the IP address.
Serial.println( "WiFi Connected." );
Serial.print( "IP Address: " );
Serial.println( WiFi.localIP() );
Wala! It is that simple now; I can configure my ESP within 5 seconds.
WiFiConFig With Storage and Reset
Now, let us add a few more functionality to this example so that it becomes more
reliable.
In this project, we will store the received Wi-Fi credentials in EEPROM/Flash
memory. Therefore, we do not need to configure ESP every time.
Next, we will add a little check like when ESP turns ON; it will retrieve the
stored Wi-Fi credentials and connect to the Wi-Fi network.
If it connects successfully, then skip entering into SmartConfig mode.
Additionally, we will use the boot button as a reset button. It will clear the
stored Wi-Fi credentials and restart ESP for a new configuration.
You need to press and hold the boot button for more than 3 seconds and release
it, and you have successfully reset the configuration.
Here is the complete project code.
/*H*******************************************************
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"
//************************* DEFINES ************************************
#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)
//************************* PROTOTYPES ************************************
void writeStringToFlash( const char* toStore, int startAddr );
String readStringFromFlash( int startAddr );
//************************* VARIABLES ************************************
String ssid; // STRING VARIABLE TO STORE SSID
String pss; // STRING VARIABLE TO STORE PASSWORD
unsigned long rst_millis;
/*F********************************************************************
*
**********************************************************************/
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 ADDR 0
Serial.print( "SSID = " );
Serial.println( ssid );
pss = readStringFromFlash( 40 ); // READ PASSWORD STORED AT ADDR 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
{
WiFi.mode( WIFI_AP_STA ); // INIT WiFi AS STATION, START SmartConfig
WiFi.beginSmartConfig();
Serial.println( "Waiting for SmartConfig." );
while( !WiFi.smartConfigDone() ) // Wait for SmartConfig packet
{
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" );
}
}
/*F********************************************************************
*
**********************************************************************/
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
}
}
/*F********************************************************************
*
**********************************************************************/
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();
}
/*F********************************************************************
*
**********************************************************************/
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 ));
}
How Code Works
First, we will include all necessary libraries for this project.
WiFi.h library will take care of all wifi-related tasks like connecting to
your Wi-Fi and SmartConfig.
EEPROM.h library will need to store data to EEPROM/Flash memory of ESP32.
#include "WiFi.h"
#include "EEPROM.h"
Defining custom function LENGTH( x ) will give us a length of a char string with
one incremental. We will use this function later.
And define the EEPROM size required as EEPROM_SIZE.
#define LENGTH( x ) ( strlen( x ) + 1 ) // length of char string
#define EEPROM_SIZE 200 // EEPROM size
We are using the Boot button of the ESP32 board for resetting the Wi-Fi
credential settings. The boot button on the ESP32 board is connected with a
GPIO0 pin and has a pullup resistor.
Therefore we will define WiFi_rst as 0. If you use any other pin for the reset
button, you need to add that GPIO number to the WiFi_rst variable.
#define WiFi_rst 0 // WiFi credential reset pin ( Boot button on ESP32)
We are defining String variables for retrieving SSID and Password.
Additionally, we will use the rst_millis variable for counting how long the
reset button is pressed.
String ssid; // STRING VARIABLE TO STORE SSID
String pss; // STRING VARIABLE TO STORE PASSWORD
unsigned long rst_millis;
setup()
We will initialize the serial communication with desired baud rate.
Serial.begin( 115200 ); // INIT SERIAL
Set the WiFi_rst pin as an input pin.
pinMode( WiFi_rst, INPUT );
Now, initialize the EEPROM with pre-defined EEPROM_SIZE.
Once it is initialized, we will read the stored SSID and Passwort as a String at
addresses 0 and 40, respectively.
We use a user-defined function named as readStringFromFlash() for reading a
string from EEPROM/flash memory.
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 );
}
Using Wi-Fi.begin function for connecting to the Wi-Fi network. We are passing
Wi-Fi credentials as a String variable; therefore, we will need to use c_str(),
which will returns a const char* that points to a null-terminated string.
We will add a slight delay so that ESP can connect to the Wi-Fi network.
WiFi.begin( ssid.c_str(), pss.c_str() );
delay( 3500 ); // WAIT FOR A WHILE TILL ESP CONNECTS TO WiFi
After that delay, we will check that ESP32 is connected to Wi-Fi or not.
If ESP connects to Wi-Fi, then we will skip the SmartConfig code inside the if
condition.
And if it fails to connect with the Wi-Fi, we will init the Wi-Fi Station mode
and SmartConfig similarly done in previous example.
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 data to be arrived with while loop. Once network
credentials have arrived, it will try to connect to that Wi-Fi network.
// 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() );
After Wi-Fi is connected, we will read the connected Wi-Fi SSID and password
with the following function.
ssid = WiFi.SSID();
pss = WiFi.psk();
Serial.print( "SSID:" );
Serial.println( ssid );
Serial.print( "PSS:" );
Serial.println( pss );
And we will store the new credentials by using another user-defined function,
writeStringToFlash(). We only need to pass string data along with an address.
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
Loop()
Inside the loop function, we will store the current millis() value in the
rst_millis variable as we will use this value as a start time when someone
presses the Wi-Fi reset button.
rst_millis = millis();
When we press the Boot button, the while loop condition is satisfied. Hence, the
code is stuck inside the loop until the button is released.
while( digitalRead( WiFi_rst ) == LOW )
{
// Wait till boot button is pressed
}
When the button is released immediately, we will check how much time we have
pressed the button if time is greater than 3000mS, the if condition is satisfied.
if( millis() - rst_millis >= 3000 )
Now we will erase the stored Wi-Fi credentials at addresses 0 and 40 by passing
blank values to the writeStringToFlash() function.
Serial.println( "Reseting the WiFi credentials" );
writeStringToFlash( "", 0 ); // Reset the SSID
writeStringToFlash( "", 40 ); // Reset the Password
Serial.println( "Wifi credentials erased" );
And finally, we will trigger a software reset to the ESP32 with the following
command.
Serial.println( "Restarting the ESP" );
delay( 500 );
ESP.restart(); // Restart ESP
writeStringToFlash( const char* toStore, int startAddr )
This user-defined function stores string or character array pointer in
EEPROM/Flash storage of ESP32.
We need to store it in non-volatile memory; hence data stored is not erased even
after power is OFF.
If we look closely at the code of this function, it is simply a for loop. It is
executed as per the LENGTH() function input, and as discussed earlier, it will
provide the length of a character string.
And we will use EEPROM.write() function to store each byte of character string
to a particular address passed and address keep incremented.
Once for loop is executed, we will save a '\0' as a string termination. And will
commit the changes so that it stores them all in memory.
/*F********************************************************************
*
**********************************************************************/
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 )
This user-defined function reads stored character strings from the desired
address in EEPROM/Flash memory.
Here we are initializing the char array name as in[128] its size is 128, which
means it can only handle the string length lower than 128. you can increase the
size if you need to deal with bigger strings.
Similar to storing function, it also works with a for loop. It will read all
char byte one by one from the startAddr ( start address ).
And lastly, we will return it in the form of a String.
/*F********************************************************************
*
**********************************************************************/
String
readStringFromFlash( int startAddr )
{
char in[128]; // CHAR ARRAY OF SIZE 128 FOR READING STORED DATA
int i = 0;
for( ; i < 128; i++ )
{
in[i] = EEPROM.read( startAddr + i );
}
return( String( in ) );
}
Wrapping Up
We have seen that SmartConfig is a very efficient and straightforward way to
configure network credentials in our ESP32 based IoT projects or devices.
And for configuration, ESP32 does not need any connected Wi-Fi network as the
Wi-Fi manager requires.
We have tested SmartConfig with a standard Wi-Fi router, and it worked like a
charm.
We have also tried this method using a mobile hotspot network, but unfortunately
, it does not work.
Therefore if any of the viewers have tried it with a mobile hotspot, leave a
comment below. And if you learned something new, then consider subscribing to
our weekly newsletter.