{"id":104227,"date":"2021-06-02T09:30:42","date_gmt":"2021-06-02T09:30:42","guid":{"rendered":"https:\/\/randomnerdtutorials.com\/?p=104227"},"modified":"2025-03-17T10:56:56","modified_gmt":"2025-03-17T10:56:56","slug":"esp8266-nodemcu-web-server-websocket-sliders","status":"publish","type":"post","link":"https:\/\/randomnerdtutorials.com\/esp8266-nodemcu-web-server-websocket-sliders\/","title":{"rendered":"ESP8266 NodeMCU Web Server (WebSocket) with Multiple Sliders: Control LEDs Brightness (PWM)"},"content":{"rendered":"\n<p>This tutorial shows how to build a web server with the ESP8266 NodeMCU board that displays a web page with multiple sliders. The sliders control the duty cycle of different PWM signals to control the brightness of multiple LEDs. Instead of LEDs, you can use this project to control DC motors or other actuators that require a PWM signal. The communication between the clients and the ESP8266 is done using the WebSocket protocol. Additionally, whenever there&#8217;s a change, all clients update their slider values simultaneously.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" fetchpriority=\"high\" decoding=\"async\" width=\"1200\" height=\"675\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/05\/ESP8266-Multiple-Sliders-Web-Server-PWM-LEDs.jpg?resize=1200%2C675&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP8266 Web Server WebSocket with Multiple Sliders: Control LEDs Brightness PWM\" class=\"wp-image-104242\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/05\/ESP8266-Multiple-Sliders-Web-Server-PWM-LEDs.jpg?w=1280&amp;quality=100&amp;strip=all&amp;ssl=1 1280w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/05\/ESP8266-Multiple-Sliders-Web-Server-PWM-LEDs.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/05\/ESP8266-Multiple-Sliders-Web-Server-PWM-LEDs.jpg?resize=1024%2C576&amp;quality=100&amp;strip=all&amp;ssl=1 1024w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/05\/ESP8266-Multiple-Sliders-Web-Server-PWM-LEDs.jpg?resize=768%2C432&amp;quality=100&amp;strip=all&amp;ssl=1 768w\" sizes=\"(max-width: 1200px) 100vw, 1200px\" \/><\/figure><\/div>\n\n\n<p>You can also modify the code presented in this tutorial to add sliders to your projects to set threshold values or any other values you need to use in your code.<\/p>\n\n\n\n<p>For this project, the ESP8266 board will be programmed using the Arduino core. You can either use the <a href=\"https:\/\/randomnerdtutorials.com\/installing-esp8266-nodemcu-arduino-ide-2-0\/\" title=\"\">Arduino IDE<\/a>, <a href=\"https:\/\/randomnerdtutorials.com\/vs-code-platformio-ide-esp32-esp8266-arduino\/\">VS Code with PlatformIO<\/a>, or any other suitable IDE.<\/p>\n\n\n\n<p>To better understand how this project works, we recommend taking a look at the following tutorials:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp8266-pwm-arduino-ide\/\">ESP8266 NodeMCU PWM with Arduino IDE \u2013 Dim LED (Analog Output)<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp8266-nodemcu-websocket-server-arduino\/\">ESP8266 NodeMCU WebSocket Server: Control Outputs (Arduino IDE)<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp8266-nodemcu-web-server-slider-pwm\/\">ESP8266 NodeMCU Web Server with Slider: Control LED Brightness (PWM)<\/a>*<\/li>\n<\/ul>\n\n\n\n<p>* This project shows how to build a web server with one slider, but it uses HTTP requests\u2014in this tutorial, we&#8217;ll use WebSocket protocol.<\/p>\n\n\n\n<p>We have a similar tutorial for the ESP32 board:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-web-server-websocket-sliders\/\">ESP32 Web Server (WebSocket) with Multiple Sliders: Control LEDs Brightness (PWM)<\/a><\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Project Overview<\/h2>\n\n\n\n<p>The following image shows the web page we&#8217;ll build for this project:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" decoding=\"async\" width=\"745\" height=\"388\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/05\/ESP-Multiple-Sliders-Web-Server.png?resize=745%2C388&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP8266 NodeMCU Web Server WebSocket Project overview sliders PWM\" class=\"wp-image-103802\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/05\/ESP-Multiple-Sliders-Web-Server.png?w=745&amp;quality=100&amp;strip=all&amp;ssl=1 745w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/05\/ESP-Multiple-Sliders-Web-Server.png?resize=300%2C156&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 745px) 100vw, 745px\" \/><\/figure><\/div>\n\n\n<ul class=\"wp-block-list\">\n<li>The web page contains three cards;<\/li>\n\n\n\n<li>Each card has a paragraph to display the card title (<strong>Fader 1<\/strong>, <strong>Fader 2<\/strong>, <strong>Fader 3<\/strong>);<\/li>\n\n\n\n<li>There\u2019s a range slider in each card that you can move to set the brightness of the corresponding LED;<\/li>\n\n\n\n<li>In each card, another paragraph displays the current LED brightness (in percentage);<\/li>\n\n\n\n<li>When you set a new position for the slider, it updates all clients (if you have multiple web browser tabs opened (or multiple devices), they update almost simultaneously whenever there&#8217;s a change).<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">How does it work?<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The ESP hosts a web server that displays a web page with three sliders;<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li>When you set a new position for a slider, the client sends the slider number and slider value to the server via WebSocket protocol. For example, if you set slider number 3 to position number 40, it would send this message <span class=\"rnthl rntliteral\">3s40<\/span> to the server.<\/li>\n<\/ul>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" decoding=\"async\" width=\"851\" height=\"326\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/05\/ESP8266-Web-Server-Sliders-How-It-Works.png?resize=851%2C326&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP8266 NodeMCU Web Server Multiple Sliders How it Works\" class=\"wp-image-104228\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/05\/ESP8266-Web-Server-Sliders-How-It-Works.png?w=851&amp;quality=100&amp;strip=all&amp;ssl=1 851w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/05\/ESP8266-Web-Server-Sliders-How-It-Works.png?resize=300%2C115&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/05\/ESP8266-Web-Server-Sliders-How-It-Works.png?resize=768%2C294&amp;quality=100&amp;strip=all&amp;ssl=1 768w\" sizes=\"(max-width: 851px) 100vw, 851px\" \/><\/figure><\/div>\n\n\n<ul class=\"wp-block-list\">\n<li>The server (ESP) receives the slider number and corresponding value and adjusts the PWM duty cycle accordingly. Additionally, it also notifies all the other clients with the new current slider values\u2014this allows us to have all clients updated almost instantaneously.<\/li>\n<\/ul>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"751\" height=\"703\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/05\/ESP8266-Slider-Web-Server-Notify-All-Clients-Websocket.png?resize=751%2C703&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP8266 NodeMCU Slider Web Server Notify All Clients Websocket\" class=\"wp-image-104229\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/05\/ESP8266-Slider-Web-Server-Notify-All-Clients-Websocket.png?w=751&amp;quality=100&amp;strip=all&amp;ssl=1 751w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/05\/ESP8266-Slider-Web-Server-Notify-All-Clients-Websocket.png?resize=300%2C281&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 751px) 100vw, 751px\" \/><\/figure><\/div>\n\n\n<ul class=\"wp-block-list\">\n<li>The ESP8266 outputs the PWM signal with the corresponding duty cycle to control the LED brightness. A duty cycle of 0% means the LED is completely off, a duty cycle of 50% means the LED is half-lit, and a duty cycle of 100% means the LED is lit;<\/li>\n<\/ul>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"865\" height=\"441\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/05\/ESP32-Brightness-Duty-Cycle-Web-Server_Brightness-duty-cycle.png?resize=865%2C441&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP8266 NodeMCU Brightness duty cycle web server PWM example\" class=\"wp-image-103816\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/05\/ESP32-Brightness-Duty-Cycle-Web-Server_Brightness-duty-cycle.png?w=865&amp;quality=100&amp;strip=all&amp;ssl=1 865w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/05\/ESP32-Brightness-Duty-Cycle-Web-Server_Brightness-duty-cycle.png?resize=300%2C153&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/05\/ESP32-Brightness-Duty-Cycle-Web-Server_Brightness-duty-cycle.png?resize=768%2C392&amp;quality=100&amp;strip=all&amp;ssl=1 768w\" sizes=\"(max-width: 865px) 100vw, 865px\" \/><\/figure><\/div>\n\n\n<ul class=\"wp-block-list\">\n<li>Whenever you open a new web browser window (this is when a new client connects), it will send a message to the ESP8266 (also through WebSocket protocol) with the message <span class=\"rnthl rntliteral\">getValues<\/span>. When the ESP8266 gets this message, it sends the current slider values. This way, whenever you open a new tab, it always shows the current and updated values.<\/li>\n<\/ul>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"751\" height=\"210\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/05\/ESP8266-Multiple-Sliders-Web-Server-New-Client-Update-Values.png?resize=751%2C210&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP8266 NodeMCU Multiple Sliders Web Server New Client Update Values\" class=\"wp-image-104230\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/05\/ESP8266-Multiple-Sliders-Web-Server-New-Client-Update-Values.png?w=751&amp;quality=100&amp;strip=all&amp;ssl=1 751w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/05\/ESP8266-Multiple-Sliders-Web-Server-New-Client-Update-Values.png?resize=300%2C84&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 751px) 100vw, 751px\" \/><\/figure><\/div>\n\n\n<h2 class=\"wp-block-heading\">Prerequisites<\/h2>\n\n\n\n<p>Before proceeding with this tutorial, make sure you check all the following prerequisites.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">1) Parts Required<\/h3>\n\n\n\n<p>To follow this project you need:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/makeradvisor.com\/tools\/esp8266-esp-12e-nodemcu-wi-fi-development-board\/\" target=\"_blank\" rel=\"noreferrer noopener\">ESP8266 NodeMCU Board<\/a> &#8211; read <a href=\"https:\/\/makeradvisor.com\/best-esp8266-wi-fi-development-board\/\" target=\"_blank\" rel=\"noreferrer noopener\">Best ESP8266 Wi-Fi Development Board \u2013 Buying Guide<\/a><\/li>\n\n\n\n<li>3x <a href=\"https:\/\/makeradvisor.com\/tools\/3mm-5mm-leds-kit-storage-box\/\" target=\"_blank\" rel=\"noreferrer noopener\">LEDs<\/a><\/li>\n\n\n\n<li>3x <a href=\"https:\/\/makeradvisor.com\/tools\/resistors-kits\/\" target=\"_blank\" rel=\"noreferrer noopener\">220Ohm resistors<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/makeradvisor.com\/tools\/mb-102-solderless-breadboard-830-points\/\" target=\"_blank\" rel=\"noreferrer noopener\">Breadboard<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/makeradvisor.com\/tools\/jumper-wires-kit-120-pieces\/\" target=\"_blank\" rel=\"noreferrer noopener\">Jumper wires<\/a><\/li>\n<\/ul>\n\n\n\n<p>You don&#8217;t need three LEDs to test this project, you can simply see the results in the Serial Monitor or use other actuators that required a PWM signal to operate.<\/p>\n\n\n<p>You can use the preceding links or go directly to <a href=\"https:\/\/makeradvisor.com\/tools\/?utm_source=rnt&utm_medium=post&utm_campaign=post\" target=\"_blank\">MakerAdvisor.com\/tools<\/a> to find all the parts for your projects at the best price!<\/p><p style=\"text-align:center;\"><a href=\"https:\/\/makeradvisor.com\/tools\/?utm_source=rnt&utm_medium=post&utm_campaign=post\" target=\"_blank\"><img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2017\/10\/header-200.png?w=1200&#038;quality=100&#038;strip=all&#038;ssl=1\"><\/a><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2) Arduino IDE and ESP8266 Boards Add-on<\/h3>\n\n\n\n<p>We\u2019ll program the ESP8266 using Arduino IDE. So, you must have the ESP8266 add-on installed. Follow the next tutorial if you haven\u2019t already:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/installing-esp8266-nodemcu-arduino-ide-2-0\/\" title=\"\">Installing ESP8266 Board in Arduino IDE<\/a><\/li>\n<\/ul>\n\n\n\n<p>If you want to use VS Code with the PlatformIO extension, follow the next tutorial instead to learn how to program the ESP8266:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/vs-code-platformio-ide-esp32-esp8266-arduino\/\">Getting Started with VS Code and PlatformIO IDE for ESP32 and ESP8266 (Windows, Mac OS X, Linux Ubuntu)<\/a><\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">3) Filesystem Uploader Plugin<\/h3>\n\n\n\n<p>To upload the HTML, CSS, and JavaScript files needed to build this project to the ESP8266 flash memory (LittleFS), we\u2019ll use a plugin for Arduino IDE:&nbsp;<strong>LittleFS Filesystem uploader<\/strong>. Follow the next tutorial to install the filesystem uploader plugin if you haven&#8217;t already:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/arduino-ide-2-install-esp8266-littlefs\/\" title=\"\">Install ESP8266 NodeMCU LittleFS Filesystem Uploader in Arduino IDE<\/a><\/li>\n<\/ul>\n\n\n\n<p>If you\u2019re using VS Code with the PlatformIO extension, read the following tutorial to learn how to upload files to the filesystem:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp8266-nodemcu-vs-code-platformio-littlefs\/\">ESP8266 NodeMCU with VS Code and PlatformIO: Upload Files to Filesystem (LittleFS)<\/a><\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">4) Libraries<\/h3>\n\n\n\n<p>To build this project, you need to install the following libraries:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a style=\"font-size: inherit;\" href=\"https:\/\/github.com\/arduino-libraries\/Arduino_JSON\" target=\"_blank\" rel=\"noreferrer noopener\">Arduino_JSON library by Arduino version 0.1.0<\/a><span style=\"font-size: inherit;\">&nbsp;(Arduino Library Manager)<\/span><\/li>\n\n\n\n<li><a href=\"https:\/\/github.com\/ESP32Async\/ESPAsyncWebServer\" target=\"_blank\" rel=\"noopener\" title=\"\">ESPAsyncWebServer by ESP32Async<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/github.com\/ESP32Async\/ESPAsyncTCP\" title=\"\">ESPAsyncTCP&nbsp;by ESP32Async<\/a><\/li>\n<\/ul>\n\n\n\n<p>You can install these libraries using the Arduino Library Manager. Go to&nbsp;<strong>Sketch&nbsp;<\/strong>&gt;&nbsp;<strong>Include Library<\/strong>&nbsp;&gt;&nbsp;<strong>Manage Libraries<\/strong>&nbsp;and search for the libraries&#8217; names.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Schematic Diagram<\/h2>\n\n\n\n<p>Wire three LEDs to the ESP8266. We&#8217;re using GPIOs 12 (D6), 13 (D7), and 14 (D5). You can use any other suitable GPIOs.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"570\" height=\"778\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/05\/ESP8266-three-LEDs-schematic-diagram.png?resize=570%2C778&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP8266 NodeMCU connected to three LEDs Schematic diagram wiring circuit\" class=\"wp-image-104232\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/05\/ESP8266-three-LEDs-schematic-diagram.png?w=570&amp;quality=100&amp;strip=all&amp;ssl=1 570w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/05\/ESP8266-three-LEDs-schematic-diagram.png?resize=220%2C300&amp;quality=100&amp;strip=all&amp;ssl=1 220w\" sizes=\"(max-width: 570px) 100vw, 570px\" \/><\/figure><\/div>\n\n\n<p class=\"rntbox rntclblue\">Recommended reading:&nbsp;<a href=\"https:\/\/randomnerdtutorials.com\/esp8266-pinout-reference-gpios\/\">ESP8266 Pinout Reference: Which GPIO pins should you use?<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Organizing Your Files<\/h2>\n\n\n\n<p>To keep the project organized and make it easier to understand, we\u2019ll create four files to build the web server:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong><a href=\"#arduino\" title=\"#arduino\">Arduino sketch<\/a><\/strong> that handles the web server;<\/li>\n\n\n\n<li><strong><a href=\"#html-f\" title=\"#html-f\">index.html<\/a><\/strong>: to define the content of the web page;<\/li>\n\n\n\n<li><strong><a href=\"#css-f\">sytle.css<\/a><\/strong>: to style the web page;<\/li>\n\n\n\n<li><strong><a href=\"#js-f\" title=\"#js-f\">script.js<\/a><\/strong>: to program the behavior of the web page\u2014handle what happens when you move the slider, send, receive and interpret the messages received via WebSocket protocol.<\/li>\n<\/ul>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"601\" height=\"358\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/05\/ESP8266-Organizing-Folders_organizing-files.png?resize=601%2C358&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP8266 NodeMCU organizing your Files arduino sketch index html style css script js\" class=\"wp-image-104233\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/05\/ESP8266-Organizing-Folders_organizing-files.png?w=601&amp;quality=100&amp;strip=all&amp;ssl=1 601w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/05\/ESP8266-Organizing-Folders_organizing-files.png?resize=300%2C179&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 601px) 100vw, 601px\" \/><\/figure><\/div>\n\n\n<p>You should save the HTML, CSS, and JavaScript files inside a folder called&nbsp;<em><strong>data<\/strong>&nbsp;<\/em>inside the Arduino sketch folder, as shown in the previous diagram. We\u2019ll upload these files to the ESP8266 filesystem (LittleFS).<\/p>\n\n\n\n<p><strong>You can download all project files:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong><a href=\"https:\/\/github.com\/RuiSantosdotme\/Random-Nerd-Tutorials\/raw\/master\/Projects\/ESP8266\/ESP8266_Multiple_Sliders_Web_Server\/ESP8266_Multiple_Sliders_Web_Server.zip\" target=\"_blank\" rel=\"noreferrer noopener\">Download All the Arduino Project Files<\/a><\/strong><\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"html-f\">HTML File<\/h2>\n\n\n\n<p>Copy the following to the <span class=\"rnthl rntliteral\">index.html<\/span> file.<\/p>\n\n\n<pre style=\"max-height: 40em; margin-bottom: 20px;\"><code class=\"language-html\">&lt;!-- Complete project details: https:\/\/randomnerdtutorials.com\/esp8266-nodemcu-web-server-websocket-sliders\/ --&gt;\r\n\r\n&lt;!DOCTYPE html&gt;\r\n&lt;html&gt;\r\n&lt;head&gt;\r\n    &lt;title&gt;ESP IOT DASHBOARD&lt;\/title&gt;\r\n    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot;&gt;\r\n    &lt;link rel=&quot;icon&quot; type=&quot;image\/png&quot; href=&quot;favicon.png&quot;&gt;\r\n    &lt;link rel=&quot;stylesheet&quot; type=&quot;text\/css&quot; href=&quot;style.css&quot;&gt;\r\n&lt;\/head&gt;\r\n&lt;body&gt;\r\n    &lt;div class=&quot;topnav&quot;&gt;\r\n        &lt;h1&gt;Multiple Sliders&lt;\/h1&gt;\r\n    &lt;\/div&gt;\r\n    &lt;div class=&quot;content&quot;&gt;\r\n        &lt;div class=&quot;card-grid&quot;&gt;\r\n            &lt;div class=&quot;card&quot;&gt;\r\n                &lt;p class=&quot;card-title&quot;&gt;Fader 1&lt;\/p&gt;\r\n                &lt;p class=&quot;switch&quot;&gt;\r\n                    &lt;input type=&quot;range&quot; onchange=&quot;updateSliderPWM(this)&quot; id=&quot;slider1&quot; min=&quot;0&quot; max=&quot;100&quot; step=&quot;1&quot; value =&quot;0&quot; class=&quot;slider&quot;&gt;\r\n                &lt;\/p&gt;\r\n                &lt;p class=&quot;state&quot;&gt;Brightness: &lt;span id=&quot;sliderValue1&quot;&gt;&lt;\/span&gt; &amp;percnt;&lt;\/p&gt;\r\n            &lt;\/div&gt;\r\n            &lt;div class=&quot;card&quot;&gt;\r\n                &lt;p class=&quot;card-title&quot;&gt; Fader 2&lt;\/p&gt;\r\n                &lt;p class=&quot;switch&quot;&gt;\r\n                    &lt;input type=&quot;range&quot; onchange=&quot;updateSliderPWM(this)&quot; id=&quot;slider2&quot; min=&quot;0&quot; max=&quot;100&quot; step=&quot;1&quot; value =&quot;0&quot; class=&quot;slider&quot;&gt;\r\n                &lt;\/p&gt;\r\n                &lt;p class=&quot;state&quot;&gt;Brightness: &lt;span id=&quot;sliderValue2&quot;&gt;&lt;\/span&gt; &amp;percnt;&lt;\/p&gt;\r\n            &lt;\/div&gt;\r\n            &lt;div class=&quot;card&quot;&gt;\r\n                &lt;p class=&quot;card-title&quot;&gt; Fader 3&lt;\/p&gt;\r\n                &lt;p class=&quot;switch&quot;&gt;\r\n                    &lt;input type=&quot;range&quot; onchange=&quot;updateSliderPWM(this)&quot; id=&quot;slider3&quot; min=&quot;0&quot; max=&quot;100&quot; step=&quot;1&quot; value =&quot;0&quot; class=&quot;slider&quot;&gt;\r\n                &lt;\/p&gt;\r\n                &lt;p class=&quot;state&quot;&gt;Brightness: &lt;span id=&quot;sliderValue3&quot;&gt;&lt;\/span&gt; &amp;percnt;&lt;\/p&gt;\r\n            &lt;\/div&gt;\r\n        &lt;\/div&gt;\r\n    &lt;\/div&gt;\r\n    &lt;script src=&quot;script.js&quot;&gt;&lt;\/script&gt;\r\n&lt;\/body&gt;\r\n&lt;\/html&gt;<\/code><\/pre>\n\t<p style=\"text-align:center\"><a class=\"rntwhite\" href=\"https:\/\/github.com\/RuiSantosdotme\/Random-Nerd-Tutorials\/raw\/master\/Projects\/ESP8266\/ESP8266_Multiple_Sliders_Web_Server\/data\/index.html\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<p>Let&#8217;s take a quick look at the most relevant parts of the HTML file.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Creating a Slider<\/h3>\n\n\n\n<p>The following tags create the card for the first slider (Fader 1).<\/p>\n\n\n\n<pre class=\"wp-block-code language-html\"><code>&lt;div class=\"card\"&gt;\n  &lt;p class=\"card-title\"&gt;Fader 1&lt;\/p&gt;\n  &lt;p class=\"switch\"&gt;\n    &lt;input type=\"range\" onchange=\"updateSliderPWM(this)\" id=\"slider1\" min=\"0\" max=\"100\" step=\"1\" value =\"0\" class=\"slider\"&gt;\n  &lt;\/p&gt;\n  &lt;p class=\"state\"&gt;Brightness: &lt;span id=\"sliderValue1\"&gt;&lt;\/span&gt; &amp;percnt;&lt;\/p&gt;\n&lt;\/div&gt;<\/code><\/pre>\n\n\n\n<p>The first paragraph displays a title for the card  (<span class=\"rnthl rntliteral\">Fader 1<\/span>). You can change the text to whatever you want.<\/p>\n\n\n\n<pre class=\"wp-block-code language-html\"><code>&lt;p class=\"card-title\"&gt;Fader 1&lt;\/p&gt;<\/code><\/pre>\n\n\n\n<p>To create a slider in HTML you use the <span class=\"rnthl rntliteral\"><span style=\"color: #333399;\">&lt;input&gt;<\/span><\/span> tag. The <span class=\"rnthl rntliteral\"><span style=\"color: #333399;\">&lt;input&gt;<\/span><\/span> tag specifies a field where the user can enter data.<\/p>\n\n\n\n<p>There are a wide variety of input types. To define a slider, use the <span class=\"rnthl rntliteral\">type<\/span> attribute with the <span class=\"rnthl rntliteral\">range<\/span> value. In a slider, you also need to define the minimum and the maximum range using the <span class=\"rnthl rntliteral\">min<\/span> and <span class=\"rnthl rntliteral\">max<\/span> attributes (in this case, <span class=\"rnthl rntliteral\">0<\/span> and <span class=\"rnthl rntliteral\">100<\/span>, respectively).<\/p>\n\n\n\n<p>You also need to define other attributes like:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>the <span class=\"rnthl rntliteral\">step<\/span> attribute specifies the interval between valid numbers. In our case, we set it to <span class=\"rnthl rntliteral\">1<\/span>;<\/li>\n\n\n\n<li>the <span class=\"rnthl rntliteral\">class<\/span> to style the slider (<span class=\"rnthl rntliteral\">class=&#8221;slider&#8221;<\/span>);<\/li>\n\n\n\n<li>the <span class=\"rnthl rntliteral\">id<\/span> so that we can manipulate the slider value using JavaScript (<span class=\"rnthl rntliteral\">id=&#8221;slider1&#8243;<\/span>);<\/li>\n\n\n\n<li>the <span class=\"rnthl rntliteral\">onchange<\/span> attribute to call a function (<span class=\"rnthl rntliteral\">updateSliderPWM(this)<\/span>) when you set a new position for the slider. This function (defined in the JavaScript file) sends the current slider value via the WebSocket protocol to the client. The <span class=\"rnthl rntliteral\">this<\/span> keyword refers to the HTML slider element.<\/li>\n<\/ul>\n\n\n\n<p>The slider is inside a paragraph with the <span class=\"rnthl rntliteral\">switch<\/span> class name. So, here are the tags that actually create the slider.<\/p>\n\n\n\n<pre class=\"wp-block-code language-html\"><code>&lt;p class=\"switch\"&gt;\n  &lt;input type=\"range\" onchange=\"updateSliderPWM(this)\" id=\"slider1\" min=\"0\" max=\"100\" step=\"1\" value =\"0\" class=\"slider\"&gt;\n&lt;\/p&gt;<\/code><\/pre>\n\n\n\n<p>Finally, there\u2019s a paragraph with a <span class=\"rnthl rntliteral\"><span style=\"color: #333399;\">&lt;span&gt;<\/span><\/span> tag, so that we can insert the current slider value in that paragraph by referring to its id (<span class=\"rnthl rntliteral\">id=&#8221;sliderValue1&#8243;<\/span>).<\/p>\n\n\n\n<pre class=\"wp-block-code language-html\"><code>&lt;p class=\"state\"&gt;Brightness: &lt;span id=\"sliderValue1\"&gt;&lt;\/span&gt; &amp;percnt;&lt;\/p&gt;<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Creating More Sliders<\/h3>\n\n\n\n<p>To create more sliders, you need to copy all the HTML tags that create the complete card. First, however, you need to consider that you need a unique id for each slider and slider value. In our case, we have three sliders with the following ids: <span class=\"rnthl rntliteral\">slider1<\/span>, <span class=\"rnthl rntliteral\">slider2<\/span>, <span class=\"rnthl rntliteral\">slider3<\/span>, and three placeholders for the slider value with the following ids: <span class=\"rnthl rntliteral\">sliderValue1<\/span>, <span class=\"rnthl rntliteral\">sliderValue2<\/span>, <span class=\"rnthl rntliteral\">sliderValue3<\/span>.<\/p>\n\n\n\n<p>For example, here&#8217;s the card for slider number 2.<\/p>\n\n\n\n<pre class=\"wp-block-code language-html\"><code>&lt;div class=\"card\"&gt;\n  &lt;p class=\"card-title\"&gt; Fader 2&lt;\/p&gt;\n  &lt;p class=\"switch\"&gt;\n    &lt;input type=\"range\" onchange=\"updateSliderPWM(this)\" id=\"slider2\" min=\"0\" max=\"100\" step=\"1\" value =\"0\" class=\"slider\"&gt;\n  &lt;\/p&gt;\n  &lt;p class=\"state\"&gt;Brightness: &lt;span id=\"sliderValue2\"&gt;&lt;\/span&gt; &amp;percnt;&lt;\/p&gt;\n&lt;\/div&gt;<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"css-f\">CSS File<\/h2>\n\n\n\n<p>Copy the following to the <span class=\"rnthl rntliteral\">style.css<\/span> file.<\/p>\n\n\n<pre style=\"max-height: 40em; margin-bottom: 20px;\"><code class=\"language-css\">\/*  Complete project details: https:\/\/randomnerdtutorials.com\/esp8266-nodemcu-web-server-websocket-sliders\/  *\/\r\n\r\nhtml {\r\n    font-family: Arial, Helvetica, sans-serif;\r\n    display: inline-block;\r\n    text-align: center;\r\n  }\r\n  h1 {\r\n    font-size: 1.8rem;\r\n    color: white;\r\n  }\r\n  p {\r\n    font-size: 1.4rem;\r\n  }\r\n  .topnav {\r\n    overflow: hidden;\r\n    background-color: #0A1128;\r\n  }\r\n  body {\r\n    margin: 0;\r\n  }\r\n  .content {\r\n    padding: 30px;\r\n  }\r\n  .card-grid {\r\n    max-width: 700px;\r\n    margin: 0 auto;\r\n    display: grid;\r\n    grid-gap: 2rem;\r\n    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\r\n  }\r\n  .card {\r\n    background-color: white;\r\n    box-shadow: 2px 2px 12px 1px rgba(140,140,140,.5);\r\n  }\r\n  .card-title {\r\n    font-size: 1.2rem;\r\n    font-weight: bold;\r\n    color: #034078\r\n  }\r\n  .state {\r\n    font-size: 1.2rem;\r\n    color:#1282A2;\r\n  }\r\n  .slider {\r\n    -webkit-appearance: none;\r\n    margin: 0 auto;\r\n    width: 100%;\r\n    height: 15px;\r\n    border-radius: 10px;\r\n    background: #FFD65C;\r\n    outline: none;\r\n  }\r\n  .slider::-webkit-slider-thumb {\r\n    -webkit-appearance: none;\r\n    appearance: none;\r\n    width: 30px;\r\n    height: 30px;\r\n    border-radius: 50%;\r\n    background: #034078;\r\n    cursor: pointer;\r\n  }\r\n  .slider::-moz-range-thumb {\r\n    width: 30px;\r\n    height: 30px;\r\n    border-radius: 50% ;\r\n    background: #034078;\r\n    cursor: pointer;\r\n  }\r\n  .switch {\r\n    padding-left: 5%;\r\n    padding-right: 5%;\r\n  }\r\n<\/code><\/pre>\n\t<p style=\"text-align:center\"><a class=\"rntwhite\" href=\"https:\/\/github.com\/RuiSantosdotme\/Random-Nerd-Tutorials\/raw\/master\/Projects\/ESP8266\/ESP8266_Multiple_Sliders_Web_Server\/data\/style.css\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<p>Let&#8217;s take a quick look at the relevant parts of the CSS file that style the slider. In this example, we need to use the vendor prefixes for the <span class=\"rnthl rntliteral\">appearance<\/span> attribute.<\/p>\n\n\n\n<pre class=\"wp-block-code language-css\"><code>.slider {\n  -webkit-appearance: none;\n  margin: 0 auto;\n  width: 100%;\n  height: 15px;\n  border-radius: 10px;\n  background: #FFD65C;\n  outline: none;\n}\n.slider::-webkit-slider-thumb {\n  -webkit-appearance: none;\n  appearance: none;\n  width: 30px;\n  height: 30px;\n  border-radius: 50%;\n  background: #034078;\n  cursor: pointer;\n}\n.slider::-moz-range-thumb {\n  width: 30px;\n  height: 30px;\n  border-radius: 50% ;\n  background: #034078;\n  cursor: pointer;\n}\n.switch {\n  padding-left: 5%;\n  padding-right: 5%;\n}<\/code><\/pre>\n\n\n\n<p><strong>Vendor Prefixes<\/strong><\/p>\n\n\n\n<p>Vendor prefixes allow a browser to support new CSS features before they become fully supported. The most commonly used browsers use the following prefixes:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>-webkit-&nbsp;Chrome, Safari, newer versions of Opera, almost all iOS browsers,<\/li>\n\n\n\n<li>-moz-&nbsp;Firefox,<\/li>\n\n\n\n<li>-o-&nbsp;Old versions of Opera,<\/li>\n\n\n\n<li>-ms-&nbsp;Microsoft Edge and Internet Explorer.<\/li>\n<\/ul>\n\n\n\n<p>Vendor prefixes are temporary. Once the properties are fully supported by the browser you use, you don\u2019t need them. You can use the following reference to check if the property you\u2019re using needs prefixes: <a href=\"http:\/\/shouldiprefix.com\/\">http:\/\/shouldiprefix.com\/<\/a><\/p>\n\n\n\n<p>Let\u2019s take a look at the <span class=\"rnthl rntliteral\">.slider<\/span> selector (styles the slider itself):<\/p>\n\n\n\n<pre class=\"wp-block-code language-css\"><code>.slider {\n  -webkit-appearance: none;\n  margin: 0 auto;\n  width: 100%;\n  height: 15px;\n  border-radius: 10px;\n  background: #FFD65C;outline: none;\n}<\/code><\/pre>\n\n\n\n<p>Setting <span class=\"rnthl rntliteral\">-webkit-appearance<\/span> to <span class=\"rnthl rntliteral\">none<\/span> overrides the default CSS styles applied to the slider in Google Chrome, Safari, and Android browsers.<\/p>\n\n\n\n<pre class=\"wp-block-code language-css\"><code>-webkit-appearance: none;<\/code><\/pre>\n\n\n\n<p>Setting the <span class=\"rnthl rntliteral\">margin<\/span> to <span class=\"rnthl rntliteral\">0 auto<\/span> aligns the slider inside its parent container.<\/p>\n\n\n\n<pre class=\"wp-block-code language-css\"><code>margin: 0 auto;<\/code><\/pre>\n\n\n\n<p>The slider&#8217;s width is set to 100%, its height to 15px, and its border radius to <span class=\"rnthl rntliteral\">10px<\/span>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-css\"><code>margin: 0 auto;\nwidth: 100%;\nheight: 15px;\nborder-radius: 10px;<\/code><\/pre>\n\n\n\n<p>Set the background color for the slider and set the <span class=\"rnthl rntliteral\">outline<\/span> to <span class=\"rnthl rntliteral\">none<\/span>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-css\"><code>background: #FFD65C;\noutline: none;<\/code><\/pre>\n\n\n\n<p>Then, format the slider handle. Use <span class=\"rnthl rntliteral\">-webkit-<\/span> for Chrome, Opera, Safari and Edge web browsers and <span class=\"rnthl rntliteral\">-moz-<\/span> for Firefox.<\/p>\n\n\n\n<pre class=\"wp-block-code language-css\"><code>.slider::-webkit-slider-thumb {\n  -webkit-appearance: none;\n  appearance: none;\n  width: 30px;\n  height: 30px;\n  border-radius: 50%;\n  background: #034078;\n  cursor: pointer;\n}\n.slider::-moz-range-thumb {\n  width: 30px;\n  height: 30px;\n  border-radius: 50% ;\n  background: #034078;\n  cursor: pointer;\n}<\/code><\/pre>\n\n\n\n<p>Set the <span class=\"rnthl rntliteral\">-webkit-appearance<\/span> and <span class=\"rnthl rntliteral\">appearance<\/span> properties to <span class=\"rnthl rntliteral\">none<\/span> to override default properties.<\/p>\n\n\n\n<pre class=\"wp-block-code language-css\"><code>-webkit-appearance: none;\nappearance: none;<\/code><\/pre>\n\n\n\n<p>Set a specific <span class=\"rnthl rntliteral\">width<\/span>, <span class=\"rnthl rntliteral\">height<\/span> and <span class=\"rnthl rntliteral\">border-radius<\/span> for the handler. Setting the same width and height with a <span class=\"rnthl rntliteral\">border-radius<\/span> of <span class=\"rnthl rntliteral\">50%<\/span> creates a circle.<\/p>\n\n\n\n<pre class=\"wp-block-code language-css\"><code>width: 30px;\nheight: 30px;\nborder-radius: 50%;<\/code><\/pre>\n\n\n\n<p>Then, set a color for the background and set the <span class=\"rnthl rntliteral\">cursor<\/span> to a <span class=\"rnthl rntliteral\">pointer<\/span>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-css\"><code>background: #034078;\ncursor: pointer;<\/code><\/pre>\n\n\n\n<p>Feel free to play with the slider properties to give it a different look.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"js-f\">JavaScript File<\/h2>\n\n\n\n<p>Copy the following to the <span class=\"rnthl rntliteral\">script.js<\/span> file.<\/p>\n\n\n<pre style=\"max-height: 40em; margin-bottom: 20px;\"><code class=\"language-javascript\">\/\/ Complete project details: https:\/\/randomnerdtutorials.com\/esp8266-nodemcu-web-server-websocket-sliders\/\r\n\r\nvar gateway = `ws:\/\/${window.location.hostname}\/ws`;\r\nvar websocket;\r\nwindow.addEventListener('load', onload);\r\n\r\nfunction onload(event) {\r\n    initWebSocket();\r\n}\r\n\r\nfunction getValues(){\r\n    websocket.send(&quot;getValues&quot;);\r\n}\r\n\r\nfunction initWebSocket() {\r\n    console.log('Trying to open a WebSocket connection\u2026');\r\n    websocket = new WebSocket(gateway);\r\n    websocket.onopen = onOpen;\r\n    websocket.onclose = onClose;\r\n    websocket.onmessage = onMessage;\r\n}\r\n\r\nfunction onOpen(event) {\r\n    console.log('Connection opened');\r\n    getValues();\r\n}\r\n\r\nfunction onClose(event) {\r\n    console.log('Connection closed');\r\n    setTimeout(initWebSocket, 2000);\r\n}\r\n\r\nfunction updateSliderPWM(element) {\r\n    var sliderNumber = element.id.charAt(element.id.length-1);\r\n    var sliderValue = document.getElementById(element.id).value;\r\n    document.getElementById(&quot;sliderValue&quot;+sliderNumber).innerHTML = sliderValue;\r\n    console.log(sliderValue);\r\n    websocket.send(sliderNumber+&quot;s&quot;+sliderValue.toString());\r\n}\r\n\r\nfunction onMessage(event) {\r\n    console.log(event.data);\r\n    var myObj = JSON.parse(event.data);\r\n    var keys = Object.keys(myObj);\r\n\r\n    for (var i = 0; i &lt; keys.length; i++){\r\n        var key = keys[i];\r\n        document.getElementById(key).innerHTML = myObj[key];\r\n        document.getElementById(&quot;slider&quot;+ (i+1).toString()).value = myObj[key];\r\n    }\r\n}\r\n<\/code><\/pre>\n\t<p style=\"text-align:center\"><a class=\"rntwhite\" href=\"https:\/\/github.com\/RuiSantosdotme\/Random-Nerd-Tutorials\/raw\/master\/Projects\/ESP8266\/ESP8266_Multiple_Sliders_Web_Server\/data\/script.js\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<p>Here\u2019s a list of what this code does:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>initializes a WebSocket connection with the server;<\/li>\n\n\n\n<li>sends a message to the server to get the current slider values;<\/li>\n\n\n\n<li>uses the response to update the slider values on the web page;<\/li>\n\n\n\n<li>handles data exchange through the WebSocket protocol.<\/li>\n<\/ul>\n\n\n\n<p>Let\u2019s take a look at this JavaScript code to see how it works.<\/p>\n\n\n\n<p>The gateway is the entry point to the WebSocket interface. <span class=\"rnthl rntliteral\">window.location.hostname<\/span> gets the current page address (the web server IP address).<\/p>\n\n\n\n<pre class=\"wp-block-code language-javascript\"><code>var gateway = ws:\/\/${window.location.hostname}\/ws;<\/code><\/pre>\n\n\n\n<p>Create a new global variable called <span class=\"rnthl rntliteral\">websocket<\/span>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-javascript\"><code>var websocket;<\/code><\/pre>\n\n\n\n<p>Add an event listener that will call the <span class=\"rnthl rntliteral\">onload<\/span> function when the web page loads.<\/p>\n\n\n\n<pre class=\"wp-block-code language-javascript\"><code>window.addEventListener('load', onload);<\/code><\/pre>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">onload()<\/span> function calls the <span class=\"rnthl rntliteral\">initWebSocket()<\/span> function to initialize a WebSocket connection with the server.<\/p>\n\n\n\n<pre class=\"wp-block-code language-javascript\"><code>function onload(event) {\n  initWebSocket();\n}<\/code><\/pre>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">initWebSocket()<\/span> function initializes a WebSocket connection on the gateway defined earlier. We also assign several callback functions for when the WebSocket connection is opened, closed, or when a message is received. <\/p>\n\n\n\n<pre class=\"wp-block-code language-javascript\"><code>function initWebSocket() {\n  console.log('Trying to open a WebSocket connection\u2026');\n  websocket = new WebSocket(gateway);\n  websocket.onopen = onOpen;\n  websocket.onclose = onClose;\n  websocket.onmessage = onMessage;\n}<\/code><\/pre>\n\n\n\n<p>Note that when the websocket connection in open, we&#8217;ll call the <span class=\"rnthl rntliteral\">getValues<\/span> function.<\/p>\n\n\n\n<pre class=\"wp-block-code language-javascript\"><code>function onOpen(event) {\n  console.log('Connection opened');\n  getValues();\n}<\/code><\/pre>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">getValues()<\/span> function sends a message to the server <span class=\"rnthl rntliteral\">getValues<\/span> to get the current value of all sliders. Then, we must handle what happens when we receive that message on the server side (ESP8266).<\/p>\n\n\n\n<pre class=\"wp-block-code language-javascript\"><code>function getStates(){\n  websocket.send(\"getValues\");\n}<\/code><\/pre>\n\n\n\n<p>We handle the messages received via websocket protocol on the <span class=\"rnthl rntliteral\">onMessage()<\/span> function.<\/p>\n\n\n\n<pre class=\"wp-block-code language-javascript\"><code>function onMessage(event) {\n  console.log(event.data);\n  var myObj = JSON.parse(event.data);\n  var keys = Object.keys(myObj);\n\n  for (var i = 0; i &lt; keys.length; i++){\n    var key = keys&#091;i];\n    document.getElementById(key).innerHTML = myObj&#091;key];\n    document.getElementById(\"slider\"+ (i+1).toString()).value = myObj&#091;key];\n  }\n}<\/code><\/pre>\n\n\n\n<p>The server sends the states in JSON format, for example:<\/p>\n\n\n\n<pre class=\"wp-block-code language-javascript\"><code>{\n  sliderValue1: 20;\n  sliderValue2: 50;\n  sliderValue3: 0;\n}<\/code><\/pre>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">onMessage()<\/span> function simply goes through all the values and places them on the corresponding places on the HTML page.<\/p>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">updateSliderPWM()<\/span> function runs when you move the sliders. <\/p>\n\n\n\n<pre class=\"wp-block-code language-javascript\"><code>function updateSliderPWM(element) {\n  var sliderNumber = element.id.charAt(element.id.length-1);\n  var sliderValue = document.getElementById(element.id).value;\n  document.getElementById(\"sliderValue\"+sliderNumber).innerHTML = sliderValue;\n  console.log(sliderValue);\n  websocket.send(sliderNumber+\"s\"+sliderValue.toString());\n}<\/code><\/pre>\n\n\n\n<p>This function gets the value from the slider and updates the corresponding paragraph with the right value. This function also sends a message to the server so that the ESP8266 updates the LED brightness. <\/p>\n\n\n\n<pre class=\"wp-block-code language-javascript\"><code>websocket.send(sliderNumber+\"s\"+sliderValue.toString());<\/code><\/pre>\n\n\n\n<p>The message is sent in the following format:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><span class=\"rnthl rntliteral\">slidernumber<strong>s<\/strong>slidervalue<\/span><\/li>\n<\/ul>\n\n\n\n<p>For example, if you move slider number 3 to position 40, it will send the following message:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><strong>3<\/strong>s<strong>40<\/strong><\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"arduino\">Arduino Sketch<\/h2>\n\n\n\n<p>Copy the following code to your Arduino IDE or to the <span class=\"rnthl rntliteral\">main.cpp<\/span> file if you\u2019re using PlatformIO.<\/p>\n\n\n<pre style=\"max-height: 40em; margin-bottom: 20px;\"><code class=\"language-c\">\/* \r\n  Rui Santos\r\n  Complete project details at https:\/\/RandomNerdTutorials.com\/esp8266-nodemcu-web-server-websocket-sliders\/\r\n  \r\n  Permission is hereby granted, free of charge, to any person obtaining a copy\r\n  of this software and associated documentation files.\r\n  \r\n  The above copyright notice and this permission notice shall be included in all\r\n  copies or substantial portions of the Software.\r\n*\/\r\n\r\n#include &lt;Arduino.h&gt;\r\n#include &lt;ESP8266WiFi.h&gt;\r\n#include &lt;ESPAsyncTCP.h&gt;\r\n#include &lt;ESPAsyncWebServer.h&gt;\r\n#include &quot;LittleFS.h&quot;\r\n#include &lt;Arduino_JSON.h&gt;\r\n\r\n\/\/ Replace with your network credentials\r\nconst char* ssid = &quot;REPLACE_WITH_YOUR_SSID&quot;;\r\nconst char* password = &quot;REPLACE_WITH_YOUR_PASSWORD&quot;;\r\n\r\n\/\/ Create AsyncWebServer object on port 80\r\nAsyncWebServer server(80);\r\n\/\/ Create a WebSocket object\r\n\r\nAsyncWebSocket ws(&quot;\/ws&quot;);\r\n\/\/ Set LED GPIO\r\nconst int ledPin1 = 14;\r\nconst int ledPin2 = 12;\r\nconst int ledPin3 = 13;\r\n\r\nString message = &quot;&quot;;\r\nString sliderValue1 = &quot;0&quot;;\r\nString sliderValue2 = &quot;0&quot;;\r\nString sliderValue3 = &quot;0&quot;;\r\n\r\nint dutyCycle1;\r\nint dutyCycle2;\r\nint dutyCycle3;\r\n\r\n\/\/Json Variable to Hold Slider Values\r\nJSONVar sliderValues;\r\n\r\n\/\/Get Slider Values\r\nString getSliderValues(){\r\n  sliderValues[&quot;sliderValue1&quot;] = String(sliderValue1);\r\n  sliderValues[&quot;sliderValue2&quot;] = String(sliderValue2);\r\n  sliderValues[&quot;sliderValue3&quot;] = String(sliderValue3);\r\n\r\n  String jsonString = JSON.stringify(sliderValues);\r\n  return jsonString;\r\n}\r\n\r\n\/\/ Initialize LittleFS\r\nvoid initFS() {\r\n  if (!LittleFS.begin()) {\r\n    Serial.println(&quot;An error has occurred while mounting LittleFS&quot;);\r\n  }\r\n  else{\r\n   Serial.println(&quot;LittleFS mounted successfully&quot;);\r\n  }\r\n}\r\n\r\n\/\/ Initialize WiFi\r\nvoid initWiFi() {\r\n  WiFi.mode(WIFI_STA);\r\n  WiFi.begin(ssid, password);\r\n  Serial.print(&quot;Connecting to WiFi ..&quot;);\r\n  while (WiFi.status() != WL_CONNECTED) {\r\n    Serial.print('.');\r\n    delay(1000);\r\n  }\r\n  Serial.println(WiFi.localIP());\r\n}\r\n\r\nvoid notifyClients(String sliderValues) {\r\n  ws.textAll(sliderValues);\r\n}\r\n\r\nvoid handleWebSocketMessage(void *arg, uint8_t *data, size_t len) {\r\n  AwsFrameInfo *info = (AwsFrameInfo*)arg;\r\n  if (info-&gt;final &amp;&amp; info-&gt;index == 0 &amp;&amp; info-&gt;len == len &amp;&amp; info-&gt;opcode == WS_TEXT) {\r\n    data[len] = 0;\r\n    message = (char*)data;\r\n    if (message.indexOf(&quot;1s&quot;) &gt;= 0) {\r\n      sliderValue1 = message.substring(2);\r\n      dutyCycle1 = map(sliderValue1.toInt(), 0, 100, 0, 1023);\r\n      Serial.println(dutyCycle1);\r\n      Serial.print(getSliderValues());\r\n      notifyClients(getSliderValues());\r\n    }\r\n    if (message.indexOf(&quot;2s&quot;) &gt;= 0) {\r\n      sliderValue2 = message.substring(2);\r\n      dutyCycle2 = map(sliderValue2.toInt(), 0, 100, 0, 1023);\r\n      Serial.println(dutyCycle2);\r\n      Serial.print(getSliderValues());\r\n      notifyClients(getSliderValues());\r\n    }    \r\n    if (message.indexOf(&quot;3s&quot;) &gt;= 0) {\r\n      sliderValue3 = message.substring(2);\r\n      dutyCycle3 = map(sliderValue3.toInt(), 0, 100, 0, 1023);\r\n      Serial.println(dutyCycle3);\r\n      Serial.print(getSliderValues());\r\n      notifyClients(getSliderValues());\r\n    }\r\n    if (strcmp((char*)data, &quot;getValues&quot;) == 0) {\r\n      notifyClients(getSliderValues());\r\n    }\r\n  }\r\n}\r\nvoid onEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len) {\r\n  switch (type) {\r\n    case WS_EVT_CONNECT:\r\n      Serial.printf(&quot;WebSocket client #%u connected from %s\\n&quot;, client-&gt;id(), client-&gt;remoteIP().toString().c_str());\r\n      break;\r\n    case WS_EVT_DISCONNECT:\r\n      Serial.printf(&quot;WebSocket client #%u disconnected\\n&quot;, client-&gt;id());\r\n      break;\r\n    case WS_EVT_DATA:\r\n      handleWebSocketMessage(arg, data, len);\r\n      break;\r\n    case WS_EVT_PONG:\r\n    case WS_EVT_ERROR:\r\n      break;\r\n  }\r\n}\r\n\r\nvoid initWebSocket() {\r\n  ws.onEvent(onEvent);\r\n  server.addHandler(&amp;ws);\r\n}\r\n\r\nvoid setup() {\r\n  Serial.begin(115200);\r\n  pinMode(ledPin1, OUTPUT);\r\n  pinMode(ledPin2, OUTPUT);\r\n  pinMode(ledPin3, OUTPUT);\r\n  initFS();\r\n  initWiFi();\r\n\r\n  initWebSocket();\r\n  \r\n  \/\/ Web Server Root URL\r\n  server.on(&quot;\/&quot;, HTTP_GET, [](AsyncWebServerRequest *request){\r\n    request-&gt;send(LittleFS, &quot;\/index.html&quot;, &quot;text\/html&quot;);\r\n  });\r\n  \r\n  server.serveStatic(&quot;\/&quot;, LittleFS, &quot;\/&quot;);\r\n\r\n  \/\/ Start server\r\n  server.begin();\r\n}\r\n\r\nvoid loop() {\r\n  analogWrite(ledPin1, dutyCycle1);\r\n  analogWrite(ledPin2, dutyCycle2);\r\n  analogWrite(ledPin3, dutyCycle3);\r\n\r\n  ws.cleanupClients();\r\n}\r\n<\/code><\/pre>\n\t<p style=\"text-align:center\"><a class=\"rntwhite\" href=\"https:\/\/github.com\/RuiSantosdotme\/Random-Nerd-Tutorials\/raw\/master\/Projects\/ESP8266\/ESP8266_Multiple_Sliders_Web_Server\/ESP8266_Multiple_Sliders_Web_Server.ino\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">How the Code Works<\/h3>\n\n\n\n<p>Let&#8217;s take a quick look at the relevant parts for this project. To better understand how the code works, we recommend following <a href=\"https:\/\/randomnerdtutorials.com\/esp8266-nodemcu-websocket-server-arduino\/\">this tutorial about WebSocket protocol with the ESP8266<\/a> and <a href=\"https:\/\/randomnerdtutorials.com\/esp8266-pwm-arduino-ide\/\">this tutorial about PWM with the ESP8266<\/a>.<\/p>\n\n\n\n<p>Insert your network credentials in the following variables to connect the ESP8266 to your local network:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>const char* ssid = \"REPLACE_WITH_YOUR_SSID\";\nconst char* password = \"REPLACE_WITH_YOUR_PASSWORD\";<\/code><\/pre>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">getSliderValues()<\/span> function creates a JSON string with the current slider values.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>String getSliderValues(){\n  sliderValues&#091;\"sliderValue1\"] = String(sliderValue1);\n  sliderValues&#091;\"sliderValue2\"] = String(sliderValue2);\n  sliderValues&#091;\"sliderValue3\"] = String(sliderValue3);\n\n  String jsonString = JSON.stringify(sliderValues);\n  return jsonString;\n}<\/code><\/pre>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">notifyClients()<\/span> function notifies all clients with the current slider values. Calling this function is what allows us to notify changes in all clients whenever you set a new position for a slider.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>void notifyClients(String sliderValues) {\n  ws.textAll(sliderValues);\n}<\/code><\/pre>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">handleWebSocketMessage()<\/span>, as the name suggests, handles what happens when the server receives a message from the client via WebSocket protocol. We&#8217;ve seen in the JavaScript file, that the server can receive the <span class=\"rnthl rntliteral\">getValues<\/span> message or a message with the slider number and the slider value.<\/p>\n\n\n\n<p>When it receives the <span class=\"rnthl rntliteral\">getValues<\/span> message, it sends the current slider values.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>if (strcmp((char*)data, \"getValues\") == 0) {\n  notifyClients(getSliderValues());\n}<\/code><\/pre>\n\n\n\n<p>If it receives another message, we check to which slider corresponds the message and update the corresponding duty cycle value. Finally, we notify all clients that a change occurred. Here&#8217;s an example for slider 1:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>if (message.indexOf(\"1s\") &gt;= 0) {\n  sliderValue1 = message.substring(2);\n  dutyCycle1 = map(sliderValue1.toInt(), 0, 100, 0, 1023);\n  Serial.println(dutyCycle1);\n  Serial.print(getSliderValues());\n  notifyClients(getSliderValues());\n}<\/code><\/pre>\n\n\n\n<p>In the <span class=\"rnthl rntliteral\">loop()<\/span>, we update the duty cycle of the PWM channels to adjust the brightness of the LEDs.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>void loop() {\n  analogWrite(ledPin1, dutyCycle1);\n  analogWrite(ledPin2, dutyCycle2);\n  analogWrite(ledPin3, dutyCycle3);\n\n  ws.cleanupClients();\n}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Upload Code and Files<\/h2>\n\n\n\n<p>After inserting your network credentials, save the code. Go to&nbsp;<strong>Sketch<\/strong>&nbsp;&gt;&nbsp;<strong>Show Sketch Folder<\/strong>, and create a folder called&nbsp;<strong>data<\/strong>. <\/p>\n\n\n<div class=\"wp-block-image is-style-default\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"351\" height=\"271\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/06\/arduino-ide-show-sketch-folder.png?resize=351%2C271&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Arduino IDE Open Sketch Folder to create data folder\" class=\"wp-image-158892\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/06\/arduino-ide-show-sketch-folder.png?w=351&amp;quality=100&amp;strip=all&amp;ssl=1 351w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/06\/arduino-ide-show-sketch-folder.png?resize=300%2C232&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 351px) 100vw, 351px\" \/><\/figure><\/div>\n\n\n<p>Inside that folder, you should save the HTML, CSS, and JavaScript files.<\/p>\n\n\n\n<p>Then, upload the code to your ESP8266 board. Make sure you have the right board and COM port selected. Also, make sure you\u2019ve added your network credentials.<\/p>\n\n\n<div class=\"wp-block-image is-style-default\">\n<figure class=\"aligncenter size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"32\" height=\"32\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/12\/upload-button-arduino-ide.png?resize=32%2C32&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Upload Arduino code\" class=\"wp-image-91745\"\/><\/figure><\/div>\n\n\n<p><strong>After uploading the code, you need to upload the files to the filesystem.<\/strong><\/p>\n\n\n\n<p>Press [<strong>Ctrl<\/strong>] + [<strong>Shift<\/strong>] + [<strong>P<\/strong>] on Windows or [<strong>\u2318<\/strong>] + [<strong>Shift<\/strong>] + [<strong>P<\/strong>] on MacOS to open the command palette. Search for the&nbsp;<strong>Upload LittleFS to Pico\/ESP8266\/ESP32<\/strong>&nbsp;command and click on it.<\/p>\n\n\n\n<p>If you don\u2019t have this option is because you didn\u2019t install the filesystem uploader plugin.&nbsp;<a href=\"https:\/\/randomnerdtutorials.com\/arduino-ide-2-install-esp8266-littlefs\/\" title=\"\">Check this tutorial<\/a>.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"666\" height=\"344\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/06\/ESP8266-Upload-filesystem-image-esp8266.png?resize=666%2C344&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP8266 Upload Filesystem Image\" class=\"wp-image-168043\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/06\/ESP8266-Upload-filesystem-image-esp8266.png?w=666&amp;quality=100&amp;strip=all&amp;ssl=1 666w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/06\/ESP8266-Upload-filesystem-image-esp8266.png?resize=300%2C155&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 666px) 100vw, 666px\" \/><\/figure><\/div>\n\n\n<p>When everything is successfully uploaded, open the Serial Monitor at a baud rate of 115200. Press the ESP8266 EN\/RST button, and it should print the ESP8266 IP address.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Demonstration<\/h2>\n\n\n\n<p>Open a browser on your local network and paste the ESP8266 IP address. You should get access to the web server page to control the brightness of the LEDs.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"250\" height=\"509\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/05\/Multiple-Sliders-ESP32-Web-Server-Phone-Browser-f.jpg?resize=250%2C509&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP8266 NodeMCU Web Server WebSocket with Multiple Sliders Control LEDs Brightness Demonstration\" class=\"wp-image-103846\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/05\/Multiple-Sliders-ESP32-Web-Server-Phone-Browser-f.jpg?w=250&amp;quality=100&amp;strip=all&amp;ssl=1 250w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/05\/Multiple-Sliders-ESP32-Web-Server-Phone-Browser-f.jpg?resize=147%2C300&amp;quality=100&amp;strip=all&amp;ssl=1 147w\" sizes=\"(max-width: 250px) 100vw, 250px\" \/><\/figure><\/div>\n\n\n<p>Move the sliders to control the brightness of the LEDs.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"750\" height=\"422\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/05\/ESP8266-NodeMCU-Multiple-Sliders-Web-Server-Webscocket-Arduino.jpg?resize=750%2C422&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP8266 NodeMCU Multiple Sliders Web Server Webscocket Arduino\" class=\"wp-image-104243\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/05\/ESP8266-NodeMCU-Multiple-Sliders-Web-Server-Webscocket-Arduino.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/05\/ESP8266-NodeMCU-Multiple-Sliders-Web-Server-Webscocket-Arduino.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n<p>Open several tabs or connect to the web server using another device, and notice that the slider values update almost instantaneously whenever there&#8217;s a change. <\/p>\n\n\n\n<p>You can watch the video demonstration (the following video shows a demonstration for the ESP32, but it works similarly with the ESP8266):<\/p>\n\n\n<div style=\"text-align:center\"><iframe src=\"https:\/\/player.vimeo.com\/video\/556152289?color=ff9933&title=1&byline=0&portrait=0\" width=\"720\" height=\"405\" frameborder=\"0\" webkitallowfullscreen mozallowfullscreen allowfullscreen><\/iframe><\/div><\/br>\n\n\n\n<h2 class=\"wp-block-heading\">Wrapping Up<\/h2>\n\n\n\n<p>In this tutorial, you&#8217;ve learned how to build a web server with the ESP8266 that serves a web page with multiple sliders. The sliders allow you to control the brightness of LEDs connected to the ESP8266. In addition, we&#8217;ve used the WebSocket protocol to communicate between the ESP8266 and the clients.<\/p>\n\n\n\n<p>To learn more about building web servers with the ESP8266 boards, we recommend taking a look at our eBook:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/build-web-servers-esp32-esp8266-ebook\/\"><strong>Build Web Servers with ESP32 and ESP8266 eBook<\/strong><\/a><\/li>\n<\/ul>\n\n\n\n<p>Learn more about the ESP8266 with our resources:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/home-automation-using-esp8266\/\">Home Automation using ESP8266<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/projects-esp8266\/\">More ESP8266 Projects and Tutorials\u2026<\/a><\/li>\n<\/ul>\n\n\n\n<p>Thank you for reading.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This tutorial shows how to build a web server with the ESP8266 NodeMCU board that displays a web page with multiple sliders. The sliders control the duty cycle of different &#8230; <\/p>\n<p class=\"read-more-container\"><a title=\"ESP8266 NodeMCU Web Server (WebSocket) with Multiple Sliders: Control LEDs Brightness (PWM)\" class=\"read-more button\" href=\"https:\/\/randomnerdtutorials.com\/esp8266-nodemcu-web-server-websocket-sliders\/#more-104227\" aria-label=\"Read more about ESP8266 NodeMCU Web Server (WebSocket) with Multiple Sliders: Control LEDs Brightness (PWM)\">CONTINUE READING \u00bb<\/a><\/p>\n","protected":false},"author":1,"featured_media":104242,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[265,214,246,300,240,264],"tags":[],"class_list":["post-104227","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-esp8266-project","category-esp8266","category-esp8266-arduino-ide","category-0-esp8266","category-esp8266-projects","category-project"],"aioseo_notices":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/05\/ESP8266-Multiple-Sliders-Web-Server-PWM-LEDs.jpg?fit=1280%2C720&quality=100&strip=all&ssl=1","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/104227","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/comments?post=104227"}],"version-history":[{"count":12,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/104227\/revisions"}],"predecessor-version":[{"id":168051,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/104227\/revisions\/168051"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/media\/104242"}],"wp:attachment":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/media?parent=104227"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/categories?post=104227"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/tags?post=104227"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}