Creating a Web Server with ESP32 PLC using the Ethernet protocol

January 16, 2024 by
Creating a Web Server with ESP32 PLC using the Ethernet protocol
Boot & Work Corp. S.L., Francesc Nosas


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.


#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("<!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
void handle_OnConnect(EthernetClient client) {
  ledStatus = LOW;
  client.println("<a class=\"button button-on\" href=\"/ledOn\">LOW</a>");
  Serial.println("Connection!\nQ: OFF");

void handle_ledOn(EthernetClient client) {
  ledStatus = HIGH;
  client.println("<a class=\"button button-on\" href=\"/ledOff\">HIGH</a>");
  Serial.println("Q: ON");

void handle_ledOff(EthernetClient client) {
  ledStatus = LOW;
  client.println("<a class=\"button button-on\" href=\"/ledOn\">LOW</a>");
  Serial.println("Q: OFF");

void handle_NotFound(EthernetClient client, String url) {
  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:
  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
  Serial.print("Server is at ");

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 =;

        // 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);
        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
    // close the connection:

  // Led control
  if (ledStatus) {
    digitalWrite(Q0_0, HIGH);
    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.


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.

​Search in our Blog

Creating a Web Server with ESP32 PLC using the Ethernet protocol
Boot & Work Corp. S.L., Francesc Nosas January 16, 2024
Share this post

Looking for your ideal Programmable Logic Controller?

Take a look at this product comparison with other industrial controllers Arduino-based. 

We are comparing inputs, outputs, communications and other features with the ones of the relevant brands.

Industrial PLC comparison >>>