This work is my insight into the ESP32 board and deals with a creation of a not complex but non trivial application where an Asynchronous WEB Server can produce pages based on an internal File system and the control of the application by serial link runs in separate core.
Introduction
In the article is highlighted the ease with which one can create a complex application using the Asynchronous WEB Server, how and where to store the necessary files (JavaScript sources, style sheets, images, ...) and how to take advantage of the dual core board.
The WEB Server can be accessed by any device that has a browser, this application, in particular, was created with cell phone access in mind.
You can also get the sources from my site.
| |
Background
The user must be practical in using Arduino IDE and programming in C ++.
The article assumes that the user has installed some components, however in a dedicated paragraph, it can find the necessary references to be able to use the application.
The user accesses the application which sends to the browser a form in which it is possible to change the time on the board, request the humidity and temperature values (DHT22 sensor)1) and view the contents of the File system.
Note for Arduino IDE
If the IDE isn't able to associate COM
port this means the lack of the appropriate driver, below the procedure I followed to solve.
- I have identified the USB to serial converter chip on my ESP32 board:
- on Windows device manager appears under
Other devices
the chip name, (my is CP2102 USB to UART Bridge Controller
), - I downloaded the
.zip
file that contains the chip driver from the manufacturer's website;
- I installed the driver acting with the right mouse button on the
silabser.inf
file and choosing install
.
Using the Code
The source included is a folder with all data needed. When it is installed on ESP32 board, you must activate the Sermig_Condor
WiFi service and access the IP address 192.168.1.1
by a browser.
Eventually, some commands can be sent to the board via the serial port.
The main components are:
- The asynchronous WEB Server
- The SPIFFS (SPI Flash File Storage) file system is hosted in Flash memory. The File System contains all files needed to the application:
- index.html
- formgen.js a script for generating forms (see my article A JavaScript Form Generator)
- formgen.css a style sheet for the generated form
- image files
- The use of both ESP32 board processor cores.
WEB Server Creation and Behavior
...
#include <WiFi.h>
#include <AsyncTCP.h>
#include "ESPAsyncWebServer.h"
...
const char* ssid = "Sermig_Condor";
const char* password = "";
IPAddress local_ip(192, 168, 1, 1);
IPAddress gateway(192, 168, 1, 1);
IPAddress subnet(255, 255, 255, 0);
AsyncWebServer server(80); ---
void setup() {
...
WiFi.softAP(ssid, password);
delay(2000); WiFi.softAPConfig(local_ip, gateway, subnet);
Serial.printf("Connect to Access Point: %s\n",ssid);
server.on("/", HTTP_ANY, [](AsyncWebServerRequest *request) {
...
});
server.onNotFound([](AsyncWebServerRequest *request){request->send(404);});
server.serveStatic("/", SPIFFS, "/");
server.begin();
...
}
void loop() {
}
In the above fragment, note the required sources, the setting of the access parameters (name, IP address, etc.) and the processing of requests.
The dealing of the requests is on:
server.on(...
where the first parameters is the resource request in the example is the root, the second parameter tells what type of request is accepted, HTTP_ANY
is both HTTP_GET
and HTTP_PUT
. This means that the eventual parameters of a request can be in the inline form ?key=value
as in a submitted form; the third parameter is the function which will process the request. server.on
must be present for each request that needs special processing. server.onNotFound(...
for deals with unknown resource requested. server.serveStatic("/", SPIFFS, "/");
this tells WEB Server to send the files request by the browser that are contained in the SPIFFS
Filesystem such as images, style sheets, JavaScript sources, etc. This means we don't have to deal with mime types of files requested.
The choice for interacting with the board has been to put the request directly after the address:
server.on("/", HTTP_ANY, [](AsyncWebServerRequest *request) {
if(request->hasArg("fnz")) {
String type = request->arg("fnz");
AsyncResponseStream *response = request->beginResponseStream("text/html");
if (type == "Dir") { response->print(dir());
request->send(response);
} else if (type == "Clock") { setTime(toSeconds(request->arg("time").c_str()));
response->printf("New time: %s", getTime());
request->send(response);
} else if (type == "Temp") { response->printf("%s %s",getTime(),getTemperature());
request->send(response);
}
} else request->send(SPIFFS, "/index.html");
The fragment above handles the request that has the form /[GET data]
the object request exposes methods for getting the parameters and for sending the responses, if no parameters are found, it is sent the initial page, i.e., the file index.html; so the requests and responses can be:
192.168.1.1 | The form is sent (index.html) |
192.168.1.1/fnz=Clock&time=hh:mm:ss | An internal clock is updated |
192.168.1.1/fnz=Dir | The content of Filesystem is sent |
192.168.1.1/fnz=Temp | The humidity and temperature values are sent |
The data for the requests are sent as plain text but can contain HTML tags like the function below that shows the Filesystem
contents:
String dir(void) {
String x = "<table>";
File root = SPIFFS.open("/");
if(!root) {
return "Failed to open directory";
}
if(!root.isDirectory()) {
return "Not a directory";
}
File file = root.openNextFile();
while(file) {
x += "<tr><td>"+String(file.name());
if(file.isDirectory()){
x += "<td>DIR";
} else {
x += "<td style='text-align:right'>"+String(file.size());
}
file = root.openNextFile();
}
x += "<tr><td>Occupied space<td style='text-align:right'>"+String(SPIFFS.usedBytes());
x += "<tr><td>Total space<td style='text-align:right'>"+String(SPIFFS.totalBytes());
return x+"</table>";
}
It is possible to interact with the board by Serial link sending the commands:
d[ir]
for displaying the contents of the FileSystem
r
resets the board t
for seeing humidity and temperature
The serial listener runs in core 0, in the fragment below, it is shown how this is realized.
void serialListener( void * pvParameters ) { Serial.print("Serial Listener running on core ");
Serial.println(xPortGetCoreID());
delay(100);
for(;;){
while (Serial.available() > 0) {
char cmd = Serial.read() | 0b00100000;
switch (cmd) {
case 100: dir_ls();
break;
case 114: Serial.print("\nReset board\n");
delay(200);
ESP.restart();
break;
case 116: sprintf(workBuffer, "%s %s", getTime(),getTemperature());
Serial.println(workBuffer);
break;
}
}
vTaskDelay(150 / portTICK_PERIOD_MS); }
}
void setup() {
...
xTaskCreatePinnedToCore (
serialListener,
"WiFi-WEBServer",
10000,
NULL,
1,
NULL,
0);
}
Notes on Components
Asynchronous WEB Server
Documentation: https://github.com/me-no-dev/ESPAsyncWebServer
We need the two libraries below:
and unzip under the Arduino libraries folder taking care to delete the suffix -master
from the folder name.
SPIFFS Filesystem
SPIFFS Filesystem
is useful but has certain limitations see here the documentation.
- It has a flat structure, i.e., it does not support directories.
- For now, it does not detect or handle bad blocks.
- The flash memory is limited to 10,000 write cycles.
- File name with extension is limited to 31 characters.
Installation (from this tutorial):
- Create a folder named data in the sketch folder where put the "site" files.
- Download the file ESP32FS-1.0.zip.
- Unzip the downloaded .zip folder to the Arduino Tools folder (if is locate in
...\ArduinoData\packages
and if it not exists must be created).
If the installation is successful in the IDE menu Tools
appears the item ESP32 Sketch Data Upload
that it permits to upload the contents of the folder data into the SPIFFS File system.2)
We can see the File system dimension by Tools −> Partition Scheme.
Conclusion
The Asynchronous WEB Server together with a File system allows to build non-trivial applications where the developer only has to worry about the logic of the application.
Notes
1) The application however can run without this sensor.
2) The upload uses the serial port so close any serial monitor.
History
- 27th April, 2021: Initial version