{"id":96485,"date":"2020-04-30T14:09:55","date_gmt":"2020-04-30T14:09:55","guid":{"rendered":"https:\/\/randomnerdtutorials.com\/?p=96485"},"modified":"2025-03-17T12:05:46","modified_gmt":"2025-03-17T12:05:46","slug":"esp32-esp8266-web-server-timer-pulse","status":"publish","type":"post","link":"https:\/\/randomnerdtutorials.com\/esp32-esp8266-web-server-timer-pulse\/","title":{"rendered":"ESP32\/ESP8266 Web Server: Control Outputs with Timer"},"content":{"rendered":"\n<p>In this tutorial you&#8217;ll build a web server to control the ESP32 or ESP8266 NodeMCU outputs with a pulse using Arduino IDE. The pulse width (&#8220;timer&#8221;) can be adjusted using a slider on the web page. When you click the ON button, the ESP sets the output state to HIGH for the number of seconds defined in the slider. This can be specially useful to control appliances that need a HIGH signal for a predetermined number of seconds to actuate.<\/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\/2020\/04\/ESP32-ESP8266-NodeMCU-Web-Server-Control-Outputs-with-Timer-Pulse.jpg?resize=1200%2C675&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 ESP8266 NodeMCU Web Server: Control Outputs with Timer using Arduino IDE\" class=\"wp-image-96521\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/04\/ESP32-ESP8266-NodeMCU-Web-Server-Control-Outputs-with-Timer-Pulse.jpg?w=1280&amp;quality=100&amp;strip=all&amp;ssl=1 1280w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/04\/ESP32-ESP8266-NodeMCU-Web-Server-Control-Outputs-with-Timer-Pulse.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/04\/ESP32-ESP8266-NodeMCU-Web-Server-Control-Outputs-with-Timer-Pulse.jpg?resize=1024%2C576&amp;quality=100&amp;strip=all&amp;ssl=1 1024w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/04\/ESP32-ESP8266-NodeMCU-Web-Server-Control-Outputs-with-Timer-Pulse.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>The ESP32\/ESP8266 boards will be programmed using Arduino IDE. So make sure you have these boards installed:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/installing-esp32-arduino-ide-2-0\/\" title=\"\">Installing ESP32 Board in Arduino IDE (Windows, Mac OS X, and Linux)<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/installing-esp8266-nodemcu-arduino-ide-2-0\/\" title=\"\">Installing ESP8266 Board in Arduino IDE (Windows, Mac OS X, Linux)<\/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 an overview of how this project works.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" decoding=\"async\" width=\"885\" height=\"696\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/04\/ESP32-ESP8266-Control-Outputs-with-Timer-Web-Server-Project-Overview-How-it-Works.png?resize=885%2C696&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 ESP8266 NodeMCU Control Outputs with Timer Web Server How it Works Project Overview\" class=\"wp-image-96518\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/04\/ESP32-ESP8266-Control-Outputs-with-Timer-Web-Server-Project-Overview-How-it-Works.png?w=885&amp;quality=100&amp;strip=all&amp;ssl=1 885w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/04\/ESP32-ESP8266-Control-Outputs-with-Timer-Web-Server-Project-Overview-How-it-Works.png?resize=300%2C236&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/04\/ESP32-ESP8266-Control-Outputs-with-Timer-Web-Server-Project-Overview-How-it-Works.png?resize=768%2C604&amp;quality=100&amp;strip=all&amp;ssl=1 768w\" sizes=\"(max-width: 885px) 100vw, 885px\" \/><\/figure><\/div>\n\n\n<ul class=\"wp-block-list\">\n<li>The ESP32\/ESP8266 hosts a web server that allows you to control an output with a pulse;<\/li>\n\n\n\n<li>The web server contains a slider that allows you to define the pulse width (how many seconds the output should be HIGH);<\/li>\n\n\n\n<li>There&#8217;s an ON\/OFF button. Set it to ON to send the pulse. After that, you&#8217;ll see a timer decreasing for the duration of the pulse width;<\/li>\n\n\n\n<li>When the timer is over, the output is set to LOW, and the web server button goes back to OFF state;<\/li>\n\n\n\n<li>This web server can be useful to control devices that need a pulse to activate like garage door openers, for example.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Installing Libraries \u2013 Async Web Server<\/h2>\n\n\n\n<p>To build the web server you need to install the following libraries:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>ESP32:<\/strong>\u00a0install the\u00a0<a href=\"https:\/\/github.com\/ESP32Async\/ESPAsyncWebServer\" target=\"_blank\" rel=\"noopener\" title=\"\">ESPAsyncWebServer<\/a> and the\u00a0<a href=\"https:\/\/github.com\/ESP32Async\/AsyncTCP\" target=\"_blank\" rel=\"noopener\" title=\"\">AsyncTCP\u00a0<\/a>libraries\u00a0(by ESP32Async).<\/li>\n\n\n\n<li><strong>ESP8266:<\/strong>\u00a0install the\u00a0<a href=\"https:\/\/github.com\/ESP32Async\/ESPAsyncWebServer\" target=\"_blank\" rel=\"noopener\" title=\"\">ESPAsyncWebServer<\/a>\u00a0and the\u00a0<a href=\"https:\/\/github.com\/ESP32Async\/ESPAsyncTCP\" target=\"_blank\" rel=\"noopener\" title=\"\">ESPAsyncTCP<\/a>\u00a0libraries (by ESP32Async).<\/li>\n<\/ul>\n\n\n\n<p>You can install those libraries in the Arduino IDE Library Manager. Go to <strong>Sketch <\/strong>&gt; <strong>Include Library<\/strong> &gt; <strong>Manage Libraries<\/strong> and search for the libraries&#8217; names.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Code<\/h2>\n\n\n\n<p>Copy the following code to your Arduino IDE.<\/p>\n\n\n<pre style=\"max-height: 40em; margin-bottom: 20px;\"><code class=\"language-c\">\/*********\n  Rui Santos &amp; Sara Santos - Random Nerd Tutorials\n  Complete project details at https:\/\/RandomNerdTutorials.com\/esp32-esp8266-web-server-timer-pulse\/\n  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n*********\/\n\n\/\/ Import required libraries\n#ifdef ESP32\n  #include &lt;WiFi.h&gt;\n  #include &lt;AsyncTCP.h&gt;\n#else\n  #include &lt;ESP8266WiFi.h&gt;\n  #include &lt;ESPAsyncTCP.h&gt;\n#endif\n#include &lt;ESPAsyncWebServer.h&gt;\n\n\/\/ Replace with your network credentials\nconst char* ssid = &quot;REPLACE_WITH_YOUR_SSID&quot;;\nconst char* password = &quot;REPLACE_WITH_YOUR_PASSWORD&quot;;\n\nconst char* PARAM_INPUT_1 = &quot;state&quot;;\nconst char* PARAM_INPUT_2 = &quot;value&quot;;\n\nconst int output = 2;\n\nString timerSliderValue = &quot;10&quot;;\n\n\/\/ Create AsyncWebServer object on port 80\nAsyncWebServer server(80);\n\nconst char index_html[] PROGMEM = R&quot;rawliteral(\n&lt;!DOCTYPE HTML&gt;&lt;html&gt;\n&lt;head&gt;\n  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot;&gt;\n  &lt;title&gt;ESP Web Server&lt;\/title&gt;\n  &lt;style&gt;\n    html {font-family: Arial; display: inline-block; text-align: center;}\n    h2 {font-size: 2.4rem;}\n    p {font-size: 2.2rem;}\n    body {max-width: 600px; margin:0px auto; padding-bottom: 25px;}\n    .switch {position: relative; display: inline-block; width: 120px; height: 68px} \n    .switch input {display: none}\n    .slider {position: absolute; top: 0; left: 0; right: 0; bottom: 0; background-color: #ccc; border-radius: 34px}\n    .slider:before {position: absolute; content: &quot;&quot;; height: 52px; width: 52px; left: 8px; bottom: 8px; background-color: #fff; -webkit-transition: .4s; transition: .4s; border-radius: 68px}\n    input:checked+.slider {background-color: #2196F3}\n    input:checked+.slider:before {-webkit-transform: translateX(52px); -ms-transform: translateX(52px); transform: translateX(52px)}\n    .slider2 { -webkit-appearance: none; margin: 14px; width: 300px; height: 20px; background: #ccc;\n      outline: none; -webkit-transition: .2s; transition: opacity .2s;}\n    .slider2::-webkit-slider-thumb {-webkit-appearance: none; appearance: none; width: 30px; height: 30px; background: #2f4468; cursor: pointer;}\n    .slider2::-moz-range-thumb { width: 30px; height: 30px; background: #2f4468; cursor: pointer; } \n  &lt;\/style&gt;\n&lt;\/head&gt;\n&lt;body&gt;\n  &lt;h2&gt;ESP Web Server&lt;\/h2&gt;\n  &lt;p&gt;&lt;span id=&quot;timerValue&quot;&gt;%TIMERVALUE%&lt;\/span&gt; s&lt;\/p&gt;\n  &lt;p&gt;&lt;input type=&quot;range&quot; onchange=&quot;updateSliderTimer(this)&quot; id=&quot;timerSlider&quot; min=&quot;1&quot; max=&quot;20&quot; value=&quot;%TIMERVALUE%&quot; step=&quot;1&quot; class=&quot;slider2&quot;&gt;&lt;\/p&gt;\n  %BUTTONPLACEHOLDER%\n&lt;script&gt;\nfunction toggleCheckbox(element) {\n  var sliderValue = document.getElementById(&quot;timerSlider&quot;).value;\n  var xhr = new XMLHttpRequest();\n  if(element.checked){ xhr.open(&quot;GET&quot;, &quot;\/update?state=1&quot;, true); xhr.send();\n    var count = sliderValue, timer = setInterval(function() {\n      count--; document.getElementById(&quot;timerValue&quot;).innerHTML = count;\n      if(count == 0){ clearInterval(timer); document.getElementById(&quot;timerValue&quot;).innerHTML = document.getElementById(&quot;timerSlider&quot;).value; }\n    }, 1000);\n    sliderValue = sliderValue*1000;\n    setTimeout(function(){ xhr.open(&quot;GET&quot;, &quot;\/update?state=0&quot;, true); \n    document.getElementById(element.id).checked = false; xhr.send(); }, sliderValue);\n  }\n}\nfunction updateSliderTimer(element) {\n  var sliderValue = document.getElementById(&quot;timerSlider&quot;).value;\n  document.getElementById(&quot;timerValue&quot;).innerHTML = sliderValue;\n  var xhr = new XMLHttpRequest();\n  xhr.open(&quot;GET&quot;, &quot;\/slider?value=&quot;+sliderValue, true);\n  xhr.send();\n}\n&lt;\/script&gt;\n&lt;\/body&gt;\n&lt;\/html&gt;\n)rawliteral&quot;;\n\n\/\/ Replaces placeholder with button section in your web page\nString processor(const String&amp; var){\n  \/\/Serial.println(var);\n  if(var == &quot;BUTTONPLACEHOLDER&quot;){\n    String buttons = &quot;&quot;;\n    String outputStateValue = outputState();\n    buttons+= &quot;&lt;p&gt;&lt;label class=\\&quot;switch\\&quot;&gt;&lt;input type=\\&quot;checkbox\\&quot; onchange=\\&quot;toggleCheckbox(this)\\&quot; id=\\&quot;output\\&quot; &quot; + outputStateValue + &quot;&gt;&lt;span class=\\&quot;slider\\&quot;&gt;&lt;\/span&gt;&lt;\/label&gt;&lt;\/p&gt;&quot;;\n    return buttons;\n  }\n  else if(var == &quot;TIMERVALUE&quot;){\n    return timerSliderValue;\n  }\n  return String();\n}\n\nString outputState(){\n  if(digitalRead(output)){\n    return &quot;checked&quot;;\n  }\n  else {\n    return &quot;&quot;;\n  }\n  return &quot;&quot;;\n}\n\nvoid setup(){\n  \/\/ Serial port for debugging purposes\n  Serial.begin(115200);\n\n  pinMode(output, OUTPUT);\n  digitalWrite(output, LOW);\n\n  \/\/ Connect to Wi-Fi\n  WiFi.begin(ssid, password);\n  while (WiFi.status() != WL_CONNECTED) {\n    delay(1000);\n    Serial.println(&quot;Connecting to WiFi..&quot;);\n  }\n\n  \/\/ Print ESP Local IP Address\n  Serial.println(WiFi.localIP());\n\n  \/\/ Route for root \/ web page\n  server.on(&quot;\/&quot;, HTTP_GET, [](AsyncWebServerRequest *request){\n    request-&gt;send(200, &quot;text\/html&quot;, index_html, processor);\n  });\n\n  \/\/ Send a GET request to &lt;ESP_IP&gt;\/update?state=&lt;inputMessage&gt;\n  server.on(&quot;\/update&quot;, HTTP_GET, [] (AsyncWebServerRequest *request) {\n    String inputMessage;\n    \/\/ GET input1 value on &lt;ESP_IP&gt;\/update?state=&lt;inputMessage&gt;\n    if (request-&gt;hasParam(PARAM_INPUT_1)) {\n      inputMessage = request-&gt;getParam(PARAM_INPUT_1)-&gt;value();\n      digitalWrite(output, inputMessage.toInt());\n    }\n    else {\n      inputMessage = &quot;No message sent&quot;;\n    }\n    Serial.println(inputMessage);\n    request-&gt;send(200, &quot;text\/plain&quot;, &quot;OK&quot;);\n  });\n  \n  \/\/ Send a GET request to &lt;ESP_IP&gt;\/slider?value=&lt;inputMessage&gt;\n  server.on(&quot;\/slider&quot;, HTTP_GET, [] (AsyncWebServerRequest *request) {\n    String inputMessage;\n    \/\/ GET input1 value on &lt;ESP_IP&gt;\/slider?value=&lt;inputMessage&gt;\n    if (request-&gt;hasParam(PARAM_INPUT_2)) {\n      inputMessage = request-&gt;getParam(PARAM_INPUT_2)-&gt;value();\n      timerSliderValue = inputMessage;\n    }\n    else {\n      inputMessage = &quot;No message sent&quot;;\n    }\n    Serial.println(inputMessage);\n    request-&gt;send(200, &quot;text\/plain&quot;, &quot;OK&quot;);\n  });\n  \n  \/\/ Start server\n  server.begin();\n}\n  \nvoid loop() {\n  \n}\n<\/code><\/pre>\n\t<p style=\"text-align:center\"><a class=\"rntwhite\" href=\"https:\/\/github.com\/RuiSantosdotme\/Random-Nerd-Tutorials\/raw\/master\/Projects\/ESP\/ESP_Web_Server_Timer_Pulse.ino\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<p>You just need to enter your network credentials (SSID and password) and the web server will work straight away. The code is compatible with both the&nbsp;<a rel=\"noreferrer noopener\" href=\"https:\/\/makeradvisor.com\/tools\/esp32-dev-board-wi-fi-bluetooth\/\" target=\"_blank\">ESP32<\/a>&nbsp;and&nbsp;<a rel=\"noreferrer noopener\" href=\"https:\/\/makeradvisor.com\/tools\/esp8266-esp-12e-nodemcu-wi-fi-development-board\/\" target=\"_blank\">ESP8266<\/a>&nbsp;boards and controls the on-board LED&nbsp;<span class=\"rnthl rntclblue\">GPIO 2<\/span>&nbsp;\u2013 you can change the code to control any other GPIO.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">How the Code Works<\/h2>\n\n\n\n<p>We\u2019ve already explained in great details how web servers like this work in previous tutorials (<a href=\"https:\/\/randomnerdtutorials.com\/esp32-dht11-dht22-temperature-humidity-web-server-arduino-ide\/\">DHT Temperature Web Server<\/a>&nbsp;or&nbsp;<a href=\"https:\/\/randomnerdtutorials.com\/esp32-esp8266-relay-web-server\/\">Relay Web Server<\/a>), so we\u2019ll just take a look at the relevant parts for this project.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Network Credentials<\/h3>\n\n\n\n<p>As said previously, insert your network credentials in the following lines:<\/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<h3 class=\"wp-block-heading\">Slider Label<\/h3>\n\n\n\n<p>Above the slider, there&#8217;s a number showing the current slider value.<\/p>\n\n\n\n<pre class=\"wp-block-code language-html\"><code>&lt;p&gt;&lt;span id=\"timerValue\"&gt;%TIMERVALUE%&lt;\/span&gt; s&lt;\/p&gt;<\/code><\/pre>\n\n\n\n<p>By default, the slider value is set to the <span class=\"rnthl rntliteral\">%TIMERVALUE%<\/span> placeholder.<\/p>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">%TIMERVALUE%<\/span> is a placeholder that will be replaced with the value stored in the <span class=\"rnthl rntliteral\">timerSliderValue<\/span> variable which is set to 10 by default. But you can change that in the following line:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>String timerSliderValue = \"10\";<\/code><\/pre>\n\n\n\n<p>This will also be changed when you move the slider. When the slider is moved, it calls a JavaScript function that updates the slider value.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Slider<\/h3>\n\n\n\n<p>The following line creates the slider. <\/p>\n\n\n\n<pre class=\"wp-block-code language-html\"><code>&lt;input type=\"range\" onchange=\"updateSliderTimer(this)\" id=\"timerSlider\" min=\"1\" max=\"20\" value=\"%TIMERVALUE%\" step=\"1\" class=\"slider2\"&gt;<\/code><\/pre>\n\n\n\n<p>Let\u2019s break this down into smaller sections.<\/p>\n\n\n\n<p>In HTML, a slider is an input type. The <span style=\"color: #333399;\">&lt;input&gt;<\/span> tag specifies an input field where the user can enter data. The slider is an input field of type <span class=\"rnthl rntliteral\">range<\/span>. There are many other input field types.<\/p>\n\n\n\n<pre class=\"wp-block-code language-html\"><code>&lt;input type=\"range\"&gt;<\/code><\/pre>\n\n\n\n<p>The default range of the slider is 0 to 100. You can use the following attributes to customize the slider settings:<\/p>\n\n\n\n<ul><li><span class=\"rnthl rntliteral\">max<\/span>: specifies the maximum value allowed. In our example, we&#8217;re setting it to 20, but you can change that value.<\/li><li><span class=\"rnthl rntliteral\">min<\/span>: specifies the minimum value. In this case, we&#8217;re setting it to 1.<\/li><li><span class=\"rnthl rntliteral\">step<\/span>: specifies the number interval. It&#8217;s set to 1.<\/li><li><span class=\"rnthl rntliteral\">value<\/span>: specifies the default value of the slider. In this case, it is equal to <span class=\"rnthl rntliteral\">%TIMERVALUE%<\/span>. <\/li><\/ul>\n\n\n\n<pre class=\"wp-block-code language-html\"><code>&lt;input type=\"range\" onchange=\"updateSliderTimer(this)\" id=\"timerSlider\" min=\"1\" max=\"20\" value=\"%TIMERVALUE%\" step=\"1\" class=\"slider2\"&gt;<\/code><\/pre>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">%TIMERVALUE%<\/span> is a placeholder that will be replaced with an actual value. In the code, it will be replaced with the value of the <span class=\"rnthl rntliteral\">timerSliderValue<\/span> variable that is set to 10 by default. But you can change that in the following line:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>String timerSliderValue = \"10\";<\/code><\/pre>\n\n\n\n<p>The slider has two more attributes: <span class=\"rnthl rntliteral\">id<\/span> and <span class=\"rnthl rntliteral\">onchange<\/span>.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><span class=\"rnthl rntliteral\">id<\/span>: specifies a unique id for an HTML element (slider). The id allows us to manipulate the element using CSS or JavaScript.<\/li>\n\n\n\n<li><span class=\"rnthl rntliteral\">onchange<\/span>: is an event attribute that occurs when we change the value of the element (the slider). When you move the slider, it calls the <span class=\"rnthl rntliteral\">updateSliderTimer()<\/span> function. <\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Update Slider Value (JavaScript)<\/h3>\n\n\n\n<p>When you move the slider, the <span class=\"rnthl rntliteral\">updateSliderTimer()<\/span> function is executed. <\/p>\n\n\n\n<p>It gets the current slider value by referring to its id <span class=\"rnthl rntliteral\">timerSlider<\/span>:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>var sliderValue = document.getElementById(\"timerSlider\").value;<\/code><\/pre>\n\n\n\n<p>Updates the slider label to the current slider value by referring to its id <span class=\"rnthl rntliteral\">timerValue<\/span>:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>document.getElementById(\"timerValue\").innerHTML = sliderValue;<\/code><\/pre>\n\n\n\n<p>Then, it makes a request on the <em>\/slider?value=sliderValue<\/em> URL. Where the <span class=\"rnthl rntliteral\">sliderValue<\/span> is equal to the current slider value.<\/p>\n\n\n\n<p>Then, the ESP32\/ESP8266 handles what happens when it receives a request on that URL.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Control the Output with Timer (JavaScript)<\/h3>\n\n\n\n<p>When you click the ON\/OFF button to control the output, it calls the <span class=\"rnthl rntliteral\">toogleCheckbox()<\/span> JavaScript function.<\/p>\n\n\n\n<p>This function gets the current value of the slider label:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>var sliderValue = document.getElementById(\"timerSlider\").value;<\/code><\/pre>\n\n\n\n<p>Makes a request on the <em>\/update?state=<strong>1<\/strong><\/em> URL so that the ESP knows it needs to set the output to <span class=\"rnthl rntliteral\">HIGH<\/span>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>if(element.checked){ xhr.open(\"GET\", \"\/update?state=1\", true); xhr.send();<\/code><\/pre>\n\n\n\n<p>The following lines decrease the slider label value every second creating the countdown timer. <\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>var count = sliderValue, timer = setInterval(function() {\n  count--; document.getElementById(\"timerValue\").innerHTML = count;\n  if(count == 0){ clearInterval(timer); document.getElementById(\"timerValue\").innerHTML = document.getElementById(\"timerSlider\").value; }\n}, 1000);<\/code><\/pre>\n\n\n\n<p>When the timer hits zero, the label value gets back to its original value and a request is made on the <em>\/update?state=<strong>0<\/strong><\/em> URL, so that the ESP knows it is time to set the output to <span class=\"rnthl rntliteral\">LOW<\/span>. The button on the web server gets back to the off state.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>setTimeout(function(){ xhr.open(\"GET\", \"\/update?state=0\", true); \ndocument.getElementById(element.id).checked = false; xhr.send(); }, sliderValue);<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Handle Requests<\/h3>\n\n\n\n<p>The ESP32\/ESP8266 needs to handle what happens when it receives a request on a certain URL.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Root URL<\/h4>\n\n\n\n<p>When you access the root URL <span class=\"rnthl rntliteral\"><strong>\/<\/strong><\/span>, send the HTML text saved on the <span class=\"rnthl rntliteral\">index_html<\/span> variable. All placeholders are replaced with the actual values by the <span class=\"rnthl rntliteral\">processor()<\/span> function.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>server.on(\"\/\", HTTP_GET, &#091;](AsyncWebServerRequest *request){\n  request-&gt;send_P(200, \"text\/html\", index_html, processor);\n});<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Control Output State<\/h4>\n\n\n\n<p>The following lines handle what happens when you receive a request on the <em>\/update?state=<strong>1<\/strong><\/em> and <em>\/update?state=<strong>0<\/strong><\/em> URLs. It sets the output state to <span class=\"rnthl rntliteral\">HIGH<\/span> or <span class=\"rnthl rntliteral\">LOW<\/span> accordingly.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>server.on(\"\/update\", HTTP_GET, &#091;] (AsyncWebServerRequest *request) {\n  String inputMessage;\n  \/\/ GET input1 value on &lt;ESP_IP&gt;\/update?state=&lt;inputMessage&gt;\n  if (request-&gt;hasParam(PARAM_INPUT_1)) {\n    inputMessage = request-&gt;getParam(PARAM_INPUT_1)-&gt;value();\n    digitalWrite(output, inputMessage.toInt());\n  }\n  else {\n    inputMessage = \"No message sent\";\n  }\n  Serial.println(inputMessage);\n  request-&gt;send(200, \"text\/plain\", \"OK\");\n});<\/code><\/pre>\n\n\n\n<p>The output state is updated in the following line:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>digitalWrite(output, inputMessage.toInt());<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Update Slider Value<\/h3>\n\n\n\n<p>Every time you drag the slider, the ESP receives a request with the new value. We store the new slider value and print it in the Serial Monitor.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Send a GET request to &lt;ESP_IP&gt;\/slider?value=&lt;inputMessage&gt;\nserver.on(\"\/slider\", HTTP_GET, &#091;] (AsyncWebServerRequest *request) {\n  String inputMessage;\n  \/\/ GET input1 value on &lt;ESP_IP&gt;\/slider?value=&lt;inputMessage&gt;\n  if (request-&gt;hasParam(PARAM_INPUT_2)) {\n    inputMessage = request-&gt;getParam(PARAM_INPUT_2)-&gt;value();\n    timerSliderValue = inputMessage;\n  }\n  else {\n    inputMessage = \"No message sent\";\n  }\n  Serial.println(inputMessage);\n  request-&gt;send(200, \"text\/plain\", \"OK\");\n});<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Demonstration<\/h2>\n\n\n\n<p>Upload the code to your ESP32 or ESP8266 NodeMCU board. Then, open the Serial Monitor and press the on-board RST\/EN button to get is IP address.<\/p>\n\n\n\n<p>Open a browser in your local network and type the ESP IP address. The following page should load.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" decoding=\"async\" width=\"786\" height=\"532\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/04\/ESP32-ESP8266-Control-Outputs-with-Timer-Web-Server.png?resize=786%2C532&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 ESP8266 NodeMCU Web Server Control Outputs with Timer using Arduino IDE demonstration\" class=\"wp-image-96516\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/04\/ESP32-ESP8266-Control-Outputs-with-Timer-Web-Server.png?w=786&amp;quality=100&amp;strip=all&amp;ssl=1 786w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/04\/ESP32-ESP8266-Control-Outputs-with-Timer-Web-Server.png?resize=300%2C203&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/04\/ESP32-ESP8266-Control-Outputs-with-Timer-Web-Server.png?resize=768%2C520&amp;quality=100&amp;strip=all&amp;ssl=1 768w\" sizes=\"(max-width: 786px) 100vw, 786px\" \/><\/figure><\/div>\n\n\n<p>Drag the slider to adjust the pulse width, and then, click the ON\/OFF button. The output (in this case <span class=\"rnthl rntclblue\">GPIO 2<\/span> &#8211; built-in LED) will stay on for the period of time you&#8217;ve set on the slider.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"750\" height=\"422\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/04\/ESP32-board-Built_in-LED-turned-on-HIGH.jpg?resize=750%2C422&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 board Built in LED turned on HIGH\" class=\"wp-image-96167\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/04\/ESP32-board-Built_in-LED-turned-on-HIGH.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/04\/ESP32-board-Built_in-LED-turned-on-HIGH.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>Watch the next quick video for a live demonstration:<\/p>\n\n\n<div style=\"text-align:center\"><iframe src=\"https:\/\/player.vimeo.com\/video\/413528253?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 to control an output with a pulse. The pulse width can be adjusted with a slider on the web server page. This can be specially useful to control certain appliances that need a HIGH signal for a determined number of seconds to actuate, like garage door openers.<\/p>\n\n\n\n<p>We hope you liked this tutorial. We have more web server projects you may like:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-esp8266-input-data-html-form\/\">Input Data on HTML Form ESP32\/ESP8266 Web Server using Arduino IDE<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-esp8266-web-server-http-authentication\/\">ESP32\/ESP8266 Web Server HTTP Authentication (Username and Password Protected)<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-esp8266-web-server-physical-button\/\">ESP32\/ESP8266: Control Outputs with Web Server and a Physical Button Simultaneously<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-esp8266-web-server-outputs-momentary-switch\/\">ESP32\/ESP8266 Web Server: Control Outputs with Momentary Switch<\/a><\/li>\n<\/ul>\n\n\n\n<p>Learn more about the ESP32 and ESP8266 board with our resources.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/learn-esp32-with-arduino-ide\/\">Learn ESP32 using Arduino IDE<\/a><\/li>\n\n\n\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-esp32\/\">More ESP32 tutorials&#8230;<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/projects-esp8266\/\">More ESP8266 tutorials&#8230;<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>In this tutorial you&#8217;ll build a web server to control the ESP32 or ESP8266 NodeMCU outputs with a pulse using Arduino IDE. The pulse width (&#8220;timer&#8221;) can be adjusted using &#8230; <\/p>\n<p class=\"read-more-container\"><a title=\"ESP32\/ESP8266 Web Server: Control Outputs with Timer\" class=\"read-more button\" href=\"https:\/\/randomnerdtutorials.com\/esp32-esp8266-web-server-timer-pulse\/#more-96485\" aria-label=\"Read more about ESP32\/ESP8266 Web Server: Control Outputs with Timer\">CONTINUE READING \u00bb<\/a><\/p>\n","protected":false},"author":1,"featured_media":96521,"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":[276,281,277,299,264],"tags":[],"class_list":["post-96485","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-esp32","category-esp32-project","category-esp32-arduino-ide","category-0-esp32","category-project"],"aioseo_notices":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/04\/ESP32-ESP8266-NodeMCU-Web-Server-Control-Outputs-with-Timer-Pulse.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\/96485","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=96485"}],"version-history":[{"count":2,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/96485\/revisions"}],"predecessor-version":[{"id":168075,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/96485\/revisions\/168075"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/media\/96521"}],"wp:attachment":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/media?parent=96485"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/categories?post=96485"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/tags?post=96485"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}