Your cart is currently empty!
Maple Systems’ Web HMIs can connect to a web server hosted by a microcontroller like Arduino. Our Web HMI’s integrated browser is used as a means to control GPIO outputs of an off-the-shelf Arduino microcontroller and Arduino Ethernet Shield 2 module.
This article walks you through the process of connecting a Web HMI to an Arduino web server. We’ll also cover programming the Arduino to host a web server using custom code. You’ll find detailed wiring diagrams and program files at the end of the article to help you easily replicate the setup.
Connecting the Web HMI
Our WP4000 series Web HMIs provide an ideal way to interact with the Arduino Web Server. It’s easy to configure and deploy, offering a very bright physical touch screen for seamlessly viewing and controlling web applications.
Access the Configuration Screen
Firstly, power on the WP4000 series Web HMI and allow it to boot. A settings icon will appear after the device starts, alongside a countdown timer.
Click the settings icon before the system settings timer expires:

Open the Web App URL Menu
Then, navigate to the web app URL entry screen. Enter the device password if prompted:

Enter the IP Address of the Arduino
Enter the Arduino’s IP address into the URL selection screen. Our Arduino was assigned an IP address of 192.168.150.187 via DHCP, so we enter that below.
Once the IP address is added, hit “Save” to save the configuration:

Reboot and Access the Web Interface
After the HMI reboots, allow the settings timer to expire. The Web HMI will then load the index.htm file loaded onto the Arduino Ethernet Shield 2 board’s SD card. We’ll then be greeted by the interface provided by the web server:

Controlling the Arduino
The web interface enables users to control LED lights connected to digital GPIO pins on the Arduino from the Web HMI:

The Arduino is also able to report input to digital GPIO pins, displayed on the Web HMI:

Finally, the Arduino can report input to analog GPIO pins in real-time as they update:

The Arduino platform is a versatile tool for learning, prototyping, and developing small-scale applications. Although this demo focuses on interacting with small LED lights, buttons, and a dial, you can apply these same concepts to a wide range of other hardware and data sources, such as sensors or control relays.
Assembling the Hardware
The Web HMI
Our 7″ resistive touch-screen Web HMIs, the WP4070A, is used to connect to the Web Server hosted by the Arduino. The installation and deployment of the unit is very straight-forward and requires the least effort out of all the setup for this demonstration.

The touchscreen of the Web HMI provides the perfect interface for visualizing and controlling the Arduino’s GPIO once connected.
A small selection of off-the-shelf parts and the Maple Systems Web HMI were used to build this demonstration. The hardware selected requires no soldering, and can be assembled at an office desk.

Arduino Development Board
An official Arduino MEGA 2560 R3 is used for running the web server program. This development board features the ATMEGA2560 microcontroller, as well as all the necessary GPIO capabilities for controlling a variety of devices. In our demonstration, we use some LED lights and buttons.
Ethernet Module
Since the Arduino MEGA does not feature an ethernet interface, an additional daughterboard (known as a “shield”) is installed to the base board. The board selected for use is the Arduino Ethernet Shield 2.
The Ethernet Shield 2 is designed to be installed into the GPIO pins on top of an Arduino microcontroller board, fitting nicely above and providing additional ports as well as pass-through GPIO pins. The ethernet module is equipped with a Micro SD card slot, which can be used to store files accessed by the program running on the Arduino. In this demonstration, an SD card containing the HTML file will be used to serve a web page to clients connecting from the Web HMI.
Test Circuit
Alongside the Arduino board, a simple circuit was assembled on a solderless breadboard to provide a few LED lights, buttons, and a potentiometer. These will all be connected to the GPIO pins available on the Arduino.

The Arduino running the Web Server program will send signals to these components. The Web UI served up by the program allows users to control control the LED lights and view input information from the buttons and potentiometer knob.
Programming the Arduino
All of the programming for the Arduino including writing the code, downloading the program, and monitoring debug output is done using the Arduino IDE software. The code provided at the end of this article can be opened in Arduino IDE and downloaded to another Arduino board for recreating the demo!
Code Explanation
Our program is designed to perform a specific set of tasks, including setting up GPIO pins for the Arduino to use, initializing the ethernet interface and connecting it to a network, and serving up an HTML file to the Web HMI.
Initializing the Ethernet Shield
The SPI, Ethernet, and SD libraries are required in order to use the Arduino Ethernet Shield 2 network interface and SD card slot. Basic parameters like the device’s MAC address and IP address info that will be used must be defined.
#include <SPI.h>
#include <Ethernet.h>
#include <SD.h>
...
// Initialize MAC address of Ethernet Module in use. This must be changed if deploying on a different device!
byte mac[] = {0xA8, 0x61, 0x0A, 0xAE, 0x09, 0xEB};
// Initialize default network configurations should DHCP configuration fail
byte staticIP[] = {192, 168, 5, 20};
byte staticGateway[] = {192, 168, 5, 1};
byte staticDNS[] = {8, 8, 8, 8};
byte staticSubnetMask[] = {255, 255, 255, 0};
Code language: PHP (php)
Setting up the ethernet interface with a network configuration is as simple as invoking the Ethernet.begin()
method:
Ethernet.begin(mac, staticIP, staticDNS, staticGateway, staticSubnetMask);
Code language: CSS (css)
Note that the full program available at the end of this article uses the Ethernet.begin()
method to first get an IP address over DHCP, then defaults to the “static” values above.
Setting Up the SD Card
An HTML/CSS file must be served to any clients (web browsers) that connect to the web server. We load an “index.htm” file onto an SD card. This SD card can be installed into the Ethernet Shield 2. There is HTML code and CSS styling that the browser will use to display our control interface and transmit formatted information to the Arduino web server.

The file is loaded in our program using the SD.begin()
and SD.exists()
methods, paired with some logical statements to notify when the file can’t be found on the card:
// Initialize SD card with web server files
Serial.println("Initializing SD card...");
if (!SD.begin(4)) {
Serial.println("Error: SD card initialization failed!");
return; // Init failed
}
Serial.println("SD card initialized successfully.");
// check for index.htm file
if (!SD.exists("index.htm")) {
Serial.println("Error: Can't find index.htm file!");
return; // Can't find index file
}
Serial.println("Found index.htm file.");
Code language: JavaScript (javascript)
Later on, the server will provide the HTML file to a web browser client using the SD.open()
method:
...
// Send web page file stored on the SD card
webFile = SD.open("index.htm"); // open web page file
if (webFile) {
while(webFile.available()) {
client.write(webFile.read()); // send web page to client
}
webFile.close();
}
...
Code language: JavaScript (javascript)
Controlling GPIO Pins
Our program will provide a web UI to control and monitor the GPIO pins. They’ll be programmed to do the following:
- Turning 4 LEDs on and off
- Registering when any of 3 buttons are pressed
- Reading an analog value from a potentiometer dial
The Arduino program must include statements that initialize pins for usage as either inputs or outputs. This is done with the pinMode()
method:
// Initialize GPIO pins for hardware controlled by web server
// Pins 2, 3, and 5 for button inputs
pinMode(2, INPUT);
pinMode(3, INPUT);
pinMode(5, INPUT);
// Pins 6-9 for LED outputs
pinMode(6, OUTPUT);
pinMode(7, OUTPUT);
pinMode(8, OUTPUT);
pinMode(9, OUTPUT);
Code language: JavaScript (javascript)
The analog pin on the Arduino used in our test circuit, pin A2, is input-only, so there is no need for configuring it as an input or output.
Using the digitalWrite()
and digitalRead()
methods, our program can check the status of our button presses (on pins 2, 3, and 5) as well as turn our LEDs on/off (on pins 6-9):
// Read button states
for (count = 0; count < 3; count++) {
cl.print("<switch>");
if (digitalRead(sw_arr[count])) {
cl.print("ON");
}
else {
cl.print("OFF");
}
cl.println("</switch>");
}
...
for (count = 0; count < 4; count++) {
pin = count + 6; // Consecutive LED pin offset for pins 6-9
// Unique HTML text for turning individual LEDs on or off
on_string = "LED" + String(count + 1) + "=1";
off_string = "LED" + String(count + 1) + "=0";
// Convert strings to char arrays for use with StrContains()
on_string.toCharArray(on_message, 7);
off_string.toCharArray(off_message, 7);
if (StrContains(HTTP_req, on_message)) {
LED_state[count] = 1; // Save LED state as ON
digitalWrite(pin, HIGH);
}
else if (StrContains(HTTP_req, off_message)) {
LED_state[count] = 0; // Save LED state as OFF
digitalWrite(pin, LOW);
}
}
Code language: PHP (php)
Reading the analog value for pin A2 is done using the analogRead()
method:
// Read analog inputs
for (count = 2; count <= 5; count++) { // A2 to A5
analog_val = analogRead(count);
...
Code language: JavaScript (javascript)
Hosting the Web Server on the Ethernet Interface
Once the program assigns an IP address to the ethernet interface, it just needs to host the web server and listen for clients over ethernet. The GPIO pins that were initialized previously will allow the user to control the test circuit from the web server.
The EthernetServer and EthernetClient classes, provided with libraries for the Ethernet Shield, allow the program to define objects for the hosted server and client. The following statements host a server on the default HTTP port (TCP port 80) and listen for clients:
// Configure web server
EthernetServer server(80); // Web server hosted on port 80
...
// Watch for connection to web server
EthernetClient client = server.available();
...
Code language: JavaScript (javascript)
Finally, the main portion of our program is able to run. All of the above code is tied together with calls as individual methods in a large loop. The loop defines the web server and client interactions from start to finish:
void loop() {
// Continuously check if ethernet module is connected to a network
CheckEthernetConnection();
// Continuously maintain DHCP lease if it was configured successfully
if (using_DHCP) {
MaintainDHCPLease();
}
// Watch for connection to web server
EthernetClient client = server.available();
// When client connects, begin repeatedly polling entered data
if (client) {
boolean currentLineIsBlank = true;
while (client.connected()) {
if (client.available()) { // If client data is available to be read, read 1 byte (character) from the client
char c = client.read();
// Limit the size of the stored HTTP request from the client
// Buffer first part of the request in an array (string)
// Leave last element in array as 0 to null terminate string (REQ_BUF_SZ - 1)
if (req_index < (REQ_BUF_SZ - 1)) {
HTTP_req[req_index] = c; // Store HTTP request character
req_index++;
}
// The last line of the client request will always be blank and end with \n
// Only respond to the client after the last line is received
if (c == '\n' && currentLineIsBlank) {
// Send a standard HTTP response header
client.println("HTTP/1.1 200 OK");
// Send the remainder of the header, which differs depending on whether
// a web page or XML file is requested
// For an Ajax request, send the XML file:
if (StrContains(HTTP_req, "ajax_inputs")) {
client.println("Content-Type: text/xml");
client.println("Connection: keep-alive");
client.println();
SetLEDs();
// Send XML file containing input data
XML_response(client);
}
else { // For a web page request, send the HTML file"
client.println("Content-Type: text/html");
client.println("Connection: keep-alive");
client.println();
// Send web page file stored on the SD card
webFile = SD.open("index.htm"); // open web page file
if (webFile) {
while(webFile.available()) {
client.write(webFile.read()); // send web page to client
}
webFile.close();
}
}
// Output any HTTP requests on the serial port
Serial.print(HTTP_req);
// Reset the buffer index and all buffer elements to 0
req_index = 0;
StrClear(HTTP_req, REQ_BUF_SZ);
break;
}
// Every line of text received from the client will end with \r\n
if (c == '\n') {
// last character on line of received text
// starting new line with next character read
currentLineIsBlank = true;
}
else if (c != '\r') {
// a text character was received from client
currentLineIsBlank = false;
}
} // end if (client.available())
} // end while (client.connected())
delay(1); // give the web browser time to receive the data
client.stop(); // close the connection
} // end if (client)
}
Code language: PHP (php)
Running the Program
The program will execute automatically when downloaded to the Arduino. The code includes statements that initialize the serial console, allowing us to receive messages from the Arduino in Arduino IDE. This is used to get information like the IP address that’s been assigned to the device.

Building the Test Circuit
To pair with the Arduino program, we built a small circuit to connect the LEDs, buttons, and potentiometer knob to the appropriate GPIO pins:

- Pins 2, 3, and 5 connect to the outputs of switches that each connect to a pull-up resistor so that the pins are pulled HIGH when the buttons are pressed.
- Pins 6-9 connect to the positive leads of 4 LEDs. When the pins are set HIGH by the Arduino, the LED lights will turn on.
- Pin A2 connects to the wiper lead of a potentiometer knob. This will apply a variable resistance to the current running through the potentiometer to pin A2, which reflects on the final voltage read as an analog value on the Arduino. The resistance on the potentiometer can be adjusted by twisting the knob.
Conclusion
Maple Systems’ WP4000 series Web HMIs are versatile devices that offer the flexibility of a Web Browser that can be leveraged in a variety of ways. Check out our previous article on using a Web HMI with noVNC for remote-desktop access to a Raspberry Pi!
The files used for this demonstration including the source code for the Arduino program and index.htm are available for download here.
Please take the time to visit our product pages for more information on the HTML5 Web HMI series of devices, or contact us to see if Maple hardware is right for your application!

About the Author