Introduction
In this blog post, we will explore how to establish a connection to your ESP32 PLC from a computer or a mobile device using Ethernet communication. We will explain how to create an Ethernet web server on your ESP32 PLC which will be accessible by all devices on the same sub-net. Using the following codes, you will be able to easily learn how to control your ESP32 PLC from another device, without relying on WiFi connections.
Web Server example
The following code describes a basic Ethernet server which handles requests from a web page in order to control a LED.
We'll be using the Ethernet.h and WebServer.h libraries.
Code:
#include <Ethernet.h>
#include <WebServer.h>
EthernetServer server(80);
byte mac[] = {
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
};
IPAddress ip(10, 42, 0, 21);
bool ledStatus = LOW;
void header_page(EthernetClient client, int request_status = 200){ // The first half of the common PHP file
client.println("HTTP/1.1 "+String(request_status)+" Not found");
client.println("Content-Type: text/html");
client.println("Connection: close"); // the connection will be closed after completion of the response
client.println("Refresh: 20"); // refresh the page automatically every 5 sec
client.println();
client.println("<!DOCTYPE HTML>");
client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\"><title>Control LED</title><style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}body{margin-top: 50px;} h1 {color: #444444;margin: 50px auto 30px;} h3 {color: #444444;margin-bottom: 50px;}.button {display: block;width: 80px;background-color: #3498db;border: none;color: white;padding: 13px 30px;text-decoration: none;font-size: 25px;margin: 0px auto 35px;cursor: pointer;border-radius: 4px;}.button-on {background-color: #3498db;}.button-on:active {background-color: #2980b9;}.button-off {background-color: #34495e;}.button-off:active {background-color: #2c3e50;}p {font-size: 14px;color: #888;margin-bottom: 10px;}</style></head>");
client.println("<html><h1>ESP32 Web Server</h1><h3>Using Station Mode</h3>");
}
void footer_page(EthernetClient client){ // The closing lines of every PHP file
client.println("</html>");
}
void handle_OnConnect(EthernetClient client) {
header_page(client);
ledStatus = LOW;
client.println("<a class=\"button button-on\" href=\"/ledOn\">LOW</a>");
footer_page(client);
Serial.println("Connection!\nQ: OFF");
}
void handle_ledOn(EthernetClient client) {
header_page(client);
ledStatus = HIGH;
client.println("<a class=\"button button-on\" href=\"/ledOff\">HIGH</a>");
footer_page(client);
Serial.println("Q: ON");
}
void handle_ledOff(EthernetClient client) {
header_page(client);
ledStatus = LOW;
client.println("<a class=\"button button-on\" href=\"/ledOn\">LOW</a>");
footer_page(client);
Serial.println("Q: OFF");
}
void handle_NotFound(EthernetClient client, String url) {
header_page(client,400);
client.println("<a>The path "+url+" doesn't exist</a>");
Serial.println ("Error, unrecognised path");
}
void setup() {
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {;}
// start the Ethernet connection and the server:
Ethernet.begin(mac, ip);
// Check for Ethernet hardware
if (Ethernet.hardwareStatus() == EthernetNoHardware) {
Serial.println("Ethernet shield was not found.");
while (true) {
delay(1); // do nothing, no point running without Ethernet hardware
}
}
if (Ethernet.linkStatus() == LinkOFF) {
Serial.println("Ethernet cable is not connected.");
}
// start the server
server.begin();
Serial.print("Server is at ");
Serial.println(Ethernet.localIP());
}
void loop() {
// listen for incoming clients
EthernetClient client = server.available();
if (client) {
//Serial.println("new client");
String client_message = "";
int argument_reading = 0;
// An http request ends with a blank line
boolean currentLineIsBlank = true;
while (client.connected()) {
if (client.available()) {
char c = client.read();
// get arguments. note: path arguments must not have any blank spaces
if (String(c) == " " || String(c) == "?")argument_reading++;
if(argument_reading==1 && String(c)!=" ")client_message = client_message + c;
// check end of request
if (c == '\n' && currentLineIsBlank) {
// Send response
// handle arguments
if (client_message == "/")handle_OnConnect(client);
else if (client_message == "/ledOn")handle_ledOn(client);
else if (client_message == "/ledOff")handle_ledOff(client);
else handle_NotFound(client,client_message);
break;
}
if (c == '\n') {
// you're starting a new line
currentLineIsBlank = true;
} else if (c != '\r') {
// you've gotten a character on the current line
currentLineIsBlank = false;
//Serial.write("We're here");
}
}
}
// give the web browser time to receive the data
delay(1);
// close the connection:
client.stop();
}
// Led control
if (ledStatus) {
digitalWrite(Q0_0, HIGH);
}
else
{
digitalWrite(Q0_0, LOW);
}
}
By running this code you will have set up a web server that can be accessed by any web browser on a device that's on the same network as the PLC. This example will establish a connection between your computer and the webserver hosted on the ESP32, allowing you to interact with the HTTP code implemented on it and control the on/off status of a LED on your ESP32 PLC.
If everything is correctly set up, you should be able to see the following webpage:
Clicking on the blue button will alternate between LOW and HIGH, appropiately enabling and disabling one of the PLC's LEDs.
Limitations:
This code recognises URL queries, but it is not able to handle GET or POST requests.
Any GET request will cut the url at the first question mark it encounters, and POST requests will not be handled at all.
Creating a Web Server with ESP32 PLC using the Ethernet protocol