Esp8266 WebServer using STM32 HAL
I already covered How to manage multiple UARTs using ring buffer in STM32. You must have a knowledge of that, if you want to understand this one. Better take a look at that tutorial first.
Today, in this tutorial, we will use the ring buffer to manage a Esp8266 Webserver using STM32 HAL library. Basically, we will blink a LED using WiFi, by creating a webserver.
Below is the CubeMX setup. Two UARTs are being used. One is connected to the ESP8266, and another is connected to the computer.
Connection & Configuration
Below is the connection between the ESP8266 and the STM32.
Some Insight into the CODE
Let’s see some of the functions, that we are going to use
void ESP_Init (char *SSID, char *PASSWD)
{
char data[80];
Ringbuf_init();
Uart_sendstring("AT+RST\r\n", wifi_uart);
Uart_sendstring("RESETTING.", pc_uart);
for (int i=0; i<5; i++)
{
Uart_sendstring(".", pc_uart);
HAL_Delay(1000);
}
/********* AT **********/
Uart_sendstring("AT\r\n", wifi_uart);
while(!(Wait_for("AT\r\r\n\r\nOK\r\n", wifi_uart)));
Uart_sendstring("AT---->OK\n\n", pc_uart);
/********* AT+CWMODE=1 **********/
Uart_sendstring("AT+CWMODE=1\r\n", wifi_uart);
while (!(Wait_for("AT+CWMODE=1\r\r\n\r\nOK\r\n", wifi_uart)));
Uart_sendstring("CW MODE---->1\n\n", pc_uart);
/********* AT+CWJAP="SSID","PASSWD" **********/
Uart_sendstring("connecting... to the provided AP\n", pc_uart);
sprintf (data, "AT+CWJAP=\"%s\",\"%s\"\r\n", SSID, PASSWD);
Uart_sendstring(data, wifi_uart);
while (!(Wait_for("WIFI GOT IP\r\n\r\nOK\r\n", wifi_uart)));
sprintf (data, "Connected to,\"%s\"\n\n", SSID);
Uart_sendstring(data,pc_uart);
/********* AT+CIFSR **********/
Uart_sendstring("AT+CIFSR\r\n", wifi_uart);
while (!(Wait_for("CIFSR:STAIP,\"", wifi_uart)));
while (!(Copy_upto("\"",buffer, wifi_uart)));
while (!(Wait_for("OK\r\n", wifi_uart)));
int len = strlen (buffer);
buffer[len-1] = '\0';
sprintf (data, "IP ADDR: %s\n\n", buffer);
Uart_sendstring(data, pc_uart);
Uart_sendstring("AT+CIPMUX=1\r\n", wifi_uart);
while (!(Wait_for("AT+CIPMUX=1\r\r\n\r\nOK\r\n", wifi_uart)));
Uart_sendstring("CIPMUX---->OK\n\n", pc_uart);
Uart_sendstring("AT+CIPSERVER=1,80\r\n", wifi_uart);
while (!(Wait_for("OK\r\n", wifi_uart)));
Uart_sendstring("CIPSERVER---->OK\n\n", pc_uart);
Uart_sendstring("Now Connect to the IP ADRESS\n\n", pc_uart);
}
ESP_Init (“SSID”, “PASSWD”) Initialises the ESP8266. Its parameter are the SSID and PASSWD of the Access point that you want to connect to. This function sends some AT commands in a sequence, and than waits for the expected response after every command. These commands are given below
- AT –> to check if the ESP is responding
- AT+CWMODE=1 –> to set the ESP into the station mode
- AT+CWJAP=”SSID”, “PASSWD” –> Join the access point with the SSID, and PASSWD
- AT+CIFSR –> Queries for the IP address of the ESP
- AT+CIPMUX=1 –> Set the multiple connection as TRUE
- AT+CIPSERVER=1,80 –> Starts a server at port 80
All the above information can be seen on the Serial console. Once the ESP gets the IP address, it will also be printed on the console as shown below
Next, we will connect to this IP address, but make sure the device and the ESP should be connected to the same network.
void Server_Start (void)
{
char buftocopyinto[64] = {0};
char Link_ID;
while (!(Get_after("+IPD,", 1, &Link_ID, wifi_uart)));
Link_ID -= 48;
while (!(Copy_upto(" HTTP/1.1", buftocopyinto, wifi_uart)));
if (Look_for("/ledon", buftocopyinto) == 1)
{
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, 1);
Server_Handle("/ledon",Link_ID);
}
else if (Look_for("/ledoff", buftocopyinto) == 1)
{
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, 0);
Server_Handle("/ledoff",Link_ID);
}
else if (Look_for("/favicon.ico", buftocopyinto) == 1);
else
{
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, 0);
Server_Handle("/ ", Link_ID);
}
}
Server_Start() checks the incoming connection, and look for the request made by the browser. If the request is about ledon, or ledoff, or the root. Once identified, it will call the Server_Handle to handle that request
If the request is made for the root, or ledoff the following will be displayed on the browser
Note that the LED on board is OFF right now. There is a option displayed on the web browser to turn this LED ON.
If we tap this ON button, a ledon request will be sent to the ESP, and the Server_Start will call Server_Hnadle to handle this ledon request.
Now the LED is ON, and there is a OFF button to turn it OFF.
The web page source code is divided into 3 categories
- Initial part, where the basic stuff will load
- Button and Status part, which will depend on what request is being processed
- Ending part, which will close the tags
/**** Initial Part ****/
char *Basic_inclusion = "<!DOCTYPE html> <html>\n<head><meta name=\"viewport\"\
content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n\
<title>LED CONTROL</title>\n<style>html { font-family: Helvetica; \
display: inline-block; margin: 0px auto; text-align: center;}\n\
body{margin-top: 50px;} h1 {color: #444444;margin: 50px auto 30px;}\
h3 {color: #444444;margin-bottom: 50px;}\n.button {display: block;\
width: 80px;background-color: #1abc9c;border: none;color: white;\
padding: 13px 30px;text-decoration: none;font-size: 25px;\
margin: 0px auto 35px;cursor: pointer;border-radius: 4px;}\n\
.button-on {background-color: #1abc9c;}\n.button-on:active \
{background-color: #16a085;}\n.button-off {background-color: #34495e;}\n\
.button-off:active {background-color: #2c3e50;}\np {font-size: 14px;color: #888;margin-bottom: 10px;}\n\
</style>\n</head>\n<body>\n<h1>ESP8266 LED CONTROL</h1>\n";
/**** Button and Status Part ****/
char *LED_ON = "<p>LED Status: ON</p><a class=\"button button-off\" href=\"/ledoff\">OFF</a>";
char *LED_OFF = "<p>LED1 Status: OFF</p><a class=\"button button-on\" href=\"/ledon\">ON</a>";
/**** Ending Part ****/
char *Terminate = "</body></html>";
To make this entire thing work, all you have to do is as shown below
/* USER CODE BEGIN Includes */
#include "ESP8266_HAL.h"
int main(void)
{
.....
.....
.....
ESP_Init("S9","12345678");
while (1)
{
Server_Start();
}
}
In case you are using a microcontroller, which gave you error on Uart_isr function. Errors like DR and SR are not present, replace the Uart_isr code with the following file Uart_isr.c
Result