Arduino - WebSocket

In this guide, we'll explore what WebSocket is, why it's useful for controlling Arduino effectively, and how to implement WebSocket with Arduino. Through a hands-on example, we'll demonstrate how to build a chat application that connects a web browser with Arduino, enabling you to:

Arduino websocket

Hardware Required

1×Arduino UNO R4 WiFi
1×USB Cable Type-C
1×(Recommended) Screw Terminal Block Shield for Arduino UNO R4
1×(Recommended) Breadboard Shield For Arduino UNO R4
1×(Recommended) Enclosure For Arduino UNO R4

Or you can buy the following sensor kits:

1×DIYables Sensor Kit (30 sensors/displays)
1×DIYables Sensor Kit (18 sensors/displays)
Please note: These are Amazon affiliate links. If you buy the components through these links, We will get a commission at no extra cost to you. We appreciate it.

What is Arduino Websocket?

You might be wondering, "What is WebSocket?" It's quite straightforward: WebSocket is a technology that enables a web browser to communicate directly with a web server in real time.

  • Without WebSocket, you would need to refresh the webpage to see new updates. This isn't very practical.
  • With WebSocket, the webpage remains continuously connected to the server. This allows them to exchange information instantly without needing to refresh the page.

You likely encounter WebSocket technology regularly in everyday web applications such as online games, instant messaging, and stock market updates.

Why we need WebSocket to smoothly control Arduino?

Imagine you want to control your remote-controlled car using a web interface on your phone or computer. Without WebSocket, each time you want to change the car's direction or speed, you'd need to refresh the web page. It's like having to press a "reload" button every time you issue a command to the car.

With WebSocket, however, it's as if there is a continuous and direct connection between your phone or computer and the car. You don't need to refresh the page to steer the car or change its speed. It’s as though the car constantly listens to your commands in real-time, without any delays caused by having to reload the page.

Overall, WebSocket facilitates:

  • Sending data from the web browser to Arduino without needing to reload the webpage.
  • Sending data from Arduino back to the web browser without refreshing the page.

This enables smooth two-way communication in real-time.

Benefits of WebSocket with Arduino:

  • Real-Time Control: WebSocket enables instant communication with the Arduino, ensuring quick responses to commands for a seamless user experience.
  • Persistent Connection: Maintain a continuous link without refreshing the control page, creating an always-ready line of communication for immediate instructions.
  • Efficiency: Experience prompt responses without the need for constant page reloading, enhancing overall user enjoyment and efficiency.

Web Chat with Arduino via WebSocket

The webpage's content (HTML, CSS, JavaScript) are stored separately on an index.h file. So, we will have two code files on Arduino IDE:

  • An .ino file that is Arduino code, which creates a web sever and WebSocket server
  • An .h file, which contains the webpage's content.

Quick Steps

  • If this is the first time you use Arduino Uno R4, see how to setup environment for Arduino Uno R4 on Arduino IDE.
  • Connect the Arduino board to your PC via a micro USB cable
  • Open Arduino IDE on your PC.
  • Select the right Arduino board (Arduino Uno R4 WiFi) and COM port.
  • Open the Library Manager by clicking on the Library Manager icon on the left navigation bar of Arduino IDE.
  • Search “mWebSockets”, then find the mWebSockets created by Dawid Kurek.
  • Click Install button to install mWebSockets library.
Arduino mWebSockets library
  • On Arduino IDE, create new sketch, Give it a name, for example, ArduinoGetStarted.com.ino
  • Copy the below code and open with Arduino IDE
/* * Created by ArduinoGetStarted.com * * This example code is in the public domain * * Tutorial page: https://arduinogetstarted.com/tutorials/arduino-websocket */ #include <WiFiS3.h> #include <WebSocketServer.h> #include "index.h" using namespace net; WebSocketServer wss(81); WiFiServer server(80); const char ssid[] = "YOUR_WIFI_SSID"; // change your network SSID const char pass[] = "YOUR_WIFI_PASSWORD"; // change your network password int status = WL_IDLE_STATUS; void setup() { //Initialize serial and wait for port to open: Serial.begin(9600); String fv = WiFi.firmwareVersion(); if (fv < WIFI_FIRMWARE_LATEST_VERSION) Serial.println("Please upgrade the firmware"); // attempt to connect to WiFi network: while (status != WL_CONNECTED) { Serial.print("Attempting to connect to SSID: "); Serial.println(ssid); // Connect to WPA/WPA2 network. Change this line if using open or WEP network: status = WiFi.begin(ssid, pass); // wait 4 seconds for connection: delay(4000); } // print your board's IP address: Serial.print("IP Address: "); Serial.println(WiFi.localIP()); server.begin(); wss.onConnection([](WebSocket &ws) { const auto protocol = ws.getProtocol(); if (protocol) { Serial.print(F("Client protocol: ")); Serial.println(protocol); } ws.onMessage([](WebSocket &ws, const WebSocket::DataType dataType, const char *message, uint16_t length) { switch (dataType) { case WebSocket::DataType::TEXT: Serial.print(F("Received: ")); Serial.println(message); break; case WebSocket::DataType::BINARY: Serial.println(F("Received binary data")); break; } String reply = "Received: " + String((char *)message); ws.send(dataType, reply.c_str(), reply.length()); }); ws.onClose([](WebSocket &, const WebSocket::CloseCode, const char *, uint16_t) { Serial.println(F("Disconnected")); }); Serial.print(F("New WebSocket Connnection from client: ")); Serial.println(ws.getRemoteIP()); const char message[]{ "Hello from Arduino server!" }; ws.send(WebSocket::DataType::TEXT, message, strlen(message)); }); wss.begin(); } void loop() { wss.listen(); // listen for incoming clients WiFiClient client = server.available(); if (client) { // read the HTTP request header line by line while (client.connected()) { if (client.available()) { String HTTP_header = client.readStringUntil('\n'); // read the header line of HTTP request if (HTTP_header.equals("\r")) // the end of HTTP request break; Serial.print("<< "); Serial.println(HTTP_header); // print HTTP request to Serial Monitor } } // send the HTTP response header client.println("HTTP/1.1 200 OK"); client.println("Content-Type: text/html"); client.println("Connection: close"); // the connection will be closed after completion of the response client.println(); // the separator between HTTP header and body String html = String(HTML_CONTENT); client.println(html); client.flush(); // give the web browser time to receive the data delay(50); // close the connection: client.stop(); } }
  • Modify the WiFi information (SSID and password) in the code to match your own network credentials.
  • Create the index.h file On Arduino IDE by:
    • Either click on the button just below the serial monitor icon and choose New Tab, or use Ctrl+Shift+N keys.
    Arduino IDE 2 adds file
    • Give the file's name index.h and click OK button
    Arduino IDE 2 adds file index.h
    • Copy the below code and paste it to the index.h.
    /* * Created by ArduinoGetStarted.com * * This example code is in the public domain * * Tutorial page: https://arduinogetstarted.com/tutorials/arduino-websocket */ const char *HTML_CONTENT = R"=====( <!DOCTYPE html> <html> <head> <title>Arduino WebSocket</title> <meta name="viewport" content="width=device-width, initial-scale=0.7, maximum-scale=0.7"> <link rel="icon" href="https://diyables.io/images/page/diyables.svg"> <style> /* Add some basic styling for the chat window */ body { background-color: #E1EFEF; font-size: 20px; line-height: 1.3; } button, input { font-size: 20px; line-height: 1.3; } .chat-container { margin: 0 auto; padding: 10px; } .chat-messages { height: 250px; overflow-y: auto; padding: 5px; margin-bottom: 5px; } .user-input { display: flex; margin-bottom: 20px; } .user-input input { flex: 1; border: 1px solid #444; padding: 5px; } .user-input button { margin-left: 5px; background-color: #007bff; color: #fff; border: none; padding: 5px 10px; cursor: pointer; } .websocket { display: flex; align-items: center; margin-bottom: 5px; } .websocket button { background-color: #007bff; color: #fff; border: none; padding: 5px 10px; cursor: pointer; } .websocket .label { margin-left: auto; } .message-sent { border-radius: 25px; background-color: #d35400; float: right; width: fit-content; padding: 10px 20px; margin: 0; } .message-received { border-radius: 25px; background-color: white; float: left; width: fit-content; padding: 10px 20px; margin: 0; } </style> <script> var ws; var wsm_max_len = 4096; /* bigger length causes uart0 buffer overflow with low speed smart device */ function update_text(text) { var chat_messages = document.getElementById("chat-messages"); chat_messages.innerHTML += '<div style="width:100%;overflow: auto;">' + text + '</div>'; chat_messages.scrollTop = chat_messages.scrollHeight; } function send_onclick() { if(ws != null) { var message = document.getElementById("message").value; if (message) { document.getElementById("message").value = ""; ws.send(message + "\n"); update_text('<p class="message-sent">' + message + '</p>'); // You can send the message to the server or process it as needed } } } function connect_onclick() { if(ws == null) { ws = new WebSocket("ws://" + window.location.host + ":81"); document.getElementById("ws_state").innerHTML = "CONNECTING"; ws.onopen = ws_onopen; ws.onclose = ws_onclose; ws.onmessage = ws_onmessage; } else ws.close(); } function ws_onopen() { document.getElementById("ws_state").innerHTML = "<span style='color:blue'>CONNECTED</span>"; document.getElementById("bt_connect").innerHTML = "Disconnect"; document.getElementById("chat-messages").innerHTML = ""; } function ws_onclose() { document.getElementById("ws_state").innerHTML = "<span style='color:gray'>CLOSED</span>"; document.getElementById("bt_connect").innerHTML = "Connect"; ws.onopen = null; ws.onclose = null; ws.onmessage = null; ws = null; } function ws_onmessage(e_msg) { e_msg = e_msg || window.event; // MessageEvent console.log(e_msg.data); update_text('<p class="message-received">' + e_msg.data + '</p>'); } </script> </head> <body> <div class="chat-container"> <h2>Arduino WebSocket</h2> <div class="websocket"> <button class="connect-button" id="bt_connect" onclick="connect_onclick()">Connect</button> <span class="label">WebSocket: <span id="ws_state"><span style="color:blue">CLOSED</span></span></span> </div> <div class="chat-messages" id="chat-messages"></div> <div class="user-input"> <input type="text" id="message" placeholder="Type your message..."> <button onclick="send_onclick()">Send</button> </div> <div class="sponsor">Sponsored by <a href="https://amazon.com/diyables">DIYables</a></div> </div> </body></html> )=====";
    • Now you have the code in two files: ArduinoGetStarted.com.ino and index.h
    • Click Upload button on Arduino IDE to upload code to Arduino.

    You will see an error like below:

    In file included from c:\Users\YOU_ACCOUNT\Documents\Arduino\libraries\mWebSockets\src/utility.h:3:0, from c:\Users\YOU_ACCOUNT\Documents\Arduino\libraries\mWebSockets\src/WebSocket.h:5, from c:\Users\YOU_ACCOUNT\Documents\Arduino\libraries\mWebSockets\src/WebSocketServer.h:5, from C:\Users\YOU_ACCOUNT\Documents\Arduino\ArduinoGetStarted.com\ArduinoGetStarted.com.ino:2: C:\Users\YOU_ACCOUNT\Documents\Arduino\libraries\mWebSockets\src/platform.h:54:12: fatal error: Ethernet.h: No such file or directory # include <Ethernet.h> ^~~~~~~~~~~~ compilation terminated. exit status 1

    To fix this error:

    • Go to C:\Users\YOU_ACCOUNT\Documents\Arduino\libraries\mWebSockets\src/ directory.
    • Find the config.h file and open it by a text editor.
    • Look at the line 26, you will see it like below:
    #define NETWORK_CONTROLLER ETHERNET_CONTROLLER_W5X00
    • Change this line to the below and save it:
    #define NETWORK_CONTROLLER NETWORK_CONTROLLER_WIFI
    • Click Upload button on Arduino IDE to upload code to Arduino.
    • Open the Serial Monitor
    • Check out the result on Serial Monitor.
    COM6
    Send
    Connecting to WiFi... Connected to WiFi Arduino Web Server's IP address IP address: 192.168.0.2
    Autoscroll Show timestamp
    Clear output
    9600 baud  
    Newline  
    • Take note of the IP address displayed, and enter this address into the address bar of a web browser on your smartphone or PC.
    • You will see the webpage it as below:
    Arduino websocket web browser
    • Click the CONNECT button to connect the webpage to Arduino via WebSocket.
    • Type some words and send them to Arduino.
    • You will see the response from Arduino.
    Arduino websocket chat server

    ※ NOTE THAT:

    • If you modify the HTML content in the index.h and does not touch anything in ArduinoGetStarted.com.ino file, when you compile and upload code to Arduino, Arduino IDE will not update the HTML content.
    • To make Arduino IDE update the HTML content in this case, make a change in the ArduinoGetStarted.com.ino file (e.g. adding empty line, add a comment....)

    Line-by-line Code Explanation

    The above Arduino code contains line-by-line explanation. Please read the comments in the code!

How the System Works

The Arduino code operates by setting up both a web server and a WebSocket server. Here’s how it works:

  • When you enter the Arduino's IP address into a web browser, it requests the webpage (User Interface) from the Arduino.
  • The Arduino’s web server then sends the content of the webpage (HTML, CSS, JavaScript) to your browser.
  • Your web browser displays the webpage.
  • Upon clicking the CONNECT button on the webpage, the JavaScript code within the page initiates a WebSocket connection with the WebSocket server on the Arduino.
  • Once the WebSocket connection is active, if you type something and hit the SEND button, the JavaScript sends your text to the Arduino via the WebSocket connection in the background.
  • After receiving your input, the WebSocket server on the Arduino sends a response back to your webpage.

You can learn other Arduino WebSocket examples below:

The Best Arduino Starter Kit

※ OUR MESSAGES