        <style>
            #donation_buttons td{
                border:medium none;
                background: inherit !important;
            }
            #donation_buttons table{               
                border:medium none;
                margin: auto;
                width: auto;
            }
        </style>
        {"id":7848,"date":"2024-12-26T23:47:28","date_gmt":"2024-12-26T23:47:28","guid":{"rendered":"https:\/\/rogerbit.com\/wprb\/?p=7848"},"modified":"2024-12-26T23:47:28","modified_gmt":"2024-12-26T23:47:28","slug":"temporizador-webserver","status":"publish","type":"post","link":"https:\/\/rogerbit.com\/wprb\/2024\/12\/temporizador-webserver\/","title":{"rendered":"Temporizador programable desde webserver con esp32"},"content":{"rendered":"<p><iframe loading=\"lazy\" title=\"Temporizador programable desde webserver con esp32  - PCBWay.es\" width=\"1160\" height=\"653\" src=\"https:\/\/www.youtube.com\/embed\/uhaq6UpFKgA?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen><\/iframe><\/p>\n<hr \/>\n<p data-pm-slice=\"1 1 []\">En este tutorial, aprender\u00e1s a construir un sistema de temporizador programable utilizando un ESP32, un display OLED SH1106 y un servidor web. Este proyecto es ideal para automatizar el encendido y apagado de una luz o cualquier dispositivo conectado, estableciendo horarios espec\u00edficos desde una interfaz web f\u00e1cil de usar.<\/p>\n<hr \/>\n<p style=\"text-align: left;\">Tal vez pueda interesarte proyectos en arduino, pic, rob\u00f3tica, telecomunicaciones, suscribete en\u00a0<a href=\"http:\/\/www.youtube.com\/user\/carlosvolt?sub_confirmation=1\">http:\/\/www.youtube.com\/user\/carlosvolt?sub_confirmation=1<\/a>\u00a0mucho videos con c\u00f3digo fuentes completos y diagramas<\/p>\n<p style=\"text-align: left;\"><div id=\"ubm-banners-rotation-n1\" data-interval=\"4000\" class=\"ubm_banners_rotation\" style=\"overflow: hidden; width: 200px; height: 150px;\"><div id=\"3_ubm_banner\" class=\"ubm_rotating_banner\"><a href=\"https:\/\/bit.ly\/3aXRDAu\" target=\"_blank\" rel=\"dofollow\"><img src=\"https:\/\/rogerbit.com\/wprb\/wp-content\/uploads\/useful_banner_manager_banners\/3-2-logo youtube.png\" width=\"100%\" height=\"100%\" alt=\"SUSCRIBETE A NUESTRO CANAL DE YOUTUBE, TUTORIALES GRATIS\" \/><\/a><\/div><\/div><\/p>\n<hr \/>\n<h4>Caracter\u00edsticas Principales:<\/h4>\n<ul data-spread=\"false\">\n<li><strong>Programaci\u00f3n de horarios<\/strong>: Configura horas y fechas para encender y apagar el dispositivo conectado.<\/li>\n<li><strong>Conectividad WiFi<\/strong>: Controla y visualiza el estado del sistema desde cualquier dispositivo en la misma red.<\/li>\n<li><strong>Persistencia de datos<\/strong>: Los horarios y el estado del dispositivo se guardan en la memoria, incluso despu\u00e9s de un reinicio.<\/li>\n<li><strong>Interfaz gr\u00e1fica<\/strong>: Muestra informaci\u00f3n en tiempo real, como la hora actual, la IP del dispositivo, y los horarios programados en un display OLED.<\/li>\n<\/ul>\n<h4>Requisitos Previos:<\/h4>\n<p>Antes de comenzar, aseg\u00farate de tener conocimientos b\u00e1sicos sobre:<\/p>\n<ul data-spread=\"false\">\n<li>Programaci\u00f3n en Arduino IDE<\/li>\n<li>Configuraci\u00f3n de redes WiFi<\/li>\n<li>Uso de componentes electr\u00f3nicos b\u00e1sicos<\/li>\n<\/ul>\n<p>Con este proyecto, podr\u00e1s automatizar tareas cotidianas, optimizando tiempo y recursos. \u00a1Manos a la obra!<\/p>\n<hr \/>\n<h2>Componentes electr\u00f3nicos<\/h2>\n<h4>Un Esp32<\/h4>\n<p><a href=\"https:\/\/rogerbit.com\/wprb\/wp-content\/uploads\/2021\/03\/esp32.jpg\"><img loading=\"lazy\" class=\"alignnone wp-image-6331\" src=\"https:\/\/rogerbit.com\/wprb\/wp-content\/uploads\/2021\/03\/esp32.jpg\" sizes=\"(max-width: 407px) 100vw, 407px\" srcset=\"https:\/\/rogerbit.com\/wprb\/wp-content\/uploads\/2021\/03\/esp32.jpg 500w, https:\/\/rogerbit.com\/wprb\/wp-content\/uploads\/2021\/03\/esp32-300x300.jpg 300w, https:\/\/rogerbit.com\/wprb\/wp-content\/uploads\/2021\/03\/esp32-150x150.jpg 150w\" alt=\"\" width=\"407\" height=\"407\" \/><\/a><\/p>\n<h4>Caracter\u00edsticas del m\u00f3dulo ESP32-T<\/h4>\n<p><img src=\"http:\/\/rogerbit.com\/wprb\/wp-content\/uploads\/2017\/08\/esp32pinout-227x300.jpg\" \/><\/p>\n<h3>Conectividad<\/h3>\n<hr \/>\n<p>El m\u00f3dulo ESP32 dispone de todas las variantes del\u00a0<strong>WiFi<\/strong>:<\/p>\n<ul>\n<li>802.11 b\/g\/n\/e\/i\/n<\/li>\n<li>Wi-Fi Direct (P2P), P2P Discovery, P2P Group Owner mode and P2P Power Management<\/li>\n<\/ul>\n<p>Esta versi\u00f3n nueva incluye la conectividad mediante<strong>\u00a0Bluethoot<\/strong>\u00a0de bajo consumo<\/p>\n<ul>\n<li>Bluetooth v4.2 BR\/EDR and BLE<\/li>\n<li>BLE Beacon<\/li>\n<\/ul>\n<p>Adem\u00e1s, puede comunicarse mediante los protocoles<strong>\u00a0SPI, I2C, UART, MAC Ethernet, Host SD<\/strong><\/p>\n<h3>Prestaciones\u00a0del microcontrolador<\/h3>\n<hr \/>\n<p>La\u00a0<strong>CPU<\/strong>\u00a0est\u00e1 formado por un\u00a0<strong>SoC modelo Tensilica LX6<\/strong>\u00a0con las siguientes caracter\u00edsticas\u00a0y memoria<\/p>\n<ul>\n<li>Doble n\u00facleo de 32 bits con velocidad de 160MHz<\/li>\n<li>Memoria ROM de 448 kBytes<\/li>\n<li>Memoria SRAM de 520kBytes<\/li>\n<\/ul>\n<p>Dispne de<strong>\u00a048 Pines<\/strong><\/p>\n<ul>\n<li>18 ADC de 12 bits<\/li>\n<li>2 DAC de 8 bits<\/li>\n<li>10 pines sensores de contacto<\/li>\n<li>16 PWM<\/li>\n<li>20 Entradas\/salidas digitales<\/li>\n<\/ul>\n<h3>Alimentaci\u00f3n y modos de consumo<\/h3>\n<p>Para un correcto funcionamiento del ESP32 es necesario subministrar un voltaje de entre 2,8V y 3,6V. La energ\u00eda que consume depende del modo de funcionamiento. Contiene un modo, el\u00a0<strong>Ultra Low Power Solution (ULP)<\/strong>, en que se contin\u00faan realizando tareas b\u00e1sicas (ADC, RTC\u2026) en el modo Sleep.<\/p>\n<p><strong>Pines hembra<\/strong><\/p>\n<p><a href=\"https:\/\/rogerbit.com\/wprb\/wp-content\/uploads\/2021\/03\/pines-hembra.jpg\"><img loading=\"lazy\" class=\"alignnone wp-image-6332\" src=\"https:\/\/rogerbit.com\/wprb\/wp-content\/uploads\/2021\/03\/pines-hembra.jpg\" sizes=\"(max-width: 500px) 100vw, 500px\" srcset=\"https:\/\/rogerbit.com\/wprb\/wp-content\/uploads\/2021\/03\/pines-hembra.jpg 500w, https:\/\/rogerbit.com\/wprb\/wp-content\/uploads\/2021\/03\/pines-hembra-300x223.jpg 300w\" alt=\"\" width=\"378\" height=\"281\" \/><\/a><\/p>\n<p><strong>Cables dupont hembra macho<\/strong><\/p>\n<div class=\"google-auto-placed ap_container\">\n<p><img loading=\"lazy\" class=\"alignnone wp-image-7023 \" src=\"https:\/\/rogerbit.com\/wprb\/wp-content\/uploads\/2022\/08\/dupunt-macho-hembra-150x150.jpg\" sizes=\"(max-width: 225px) 100vw, 225px\" srcset=\"https:\/\/rogerbit.com\/wprb\/wp-content\/uploads\/2022\/08\/dupunt-macho-hembra-150x150.jpg 150w, https:\/\/rogerbit.com\/wprb\/wp-content\/uploads\/2022\/08\/dupunt-macho-hembra-300x300.jpg 300w, https:\/\/rogerbit.com\/wprb\/wp-content\/uploads\/2022\/08\/dupunt-macho-hembra-768x768.jpg 768w, https:\/\/rogerbit.com\/wprb\/wp-content\/uploads\/2022\/08\/dupunt-macho-hembra.jpg 800w\" alt=\"\" width=\"225\" height=\"225\" \/><\/p>\n<hr \/>\n<p><strong>Display oled sh1106<\/strong><\/p>\n<p><a href=\"http:\/\/rogerbit.com\/wprb\/wp-content\/uploads\/2020\/12\/display-oled.jpg\"><img loading=\"lazy\" class=\"alignnone wp-image-6148\" src=\"http:\/\/rogerbit.com\/wprb\/wp-content\/uploads\/2020\/12\/display-oled.jpg\" sizes=\"(max-width: 280px) 100vw, 280px\" srcset=\"https:\/\/rogerbit.com\/wprb\/wp-content\/uploads\/2020\/12\/display-oled.jpg 809w, https:\/\/rogerbit.com\/wprb\/wp-content\/uploads\/2020\/12\/display-oled-300x285.jpg 300w, https:\/\/rogerbit.com\/wprb\/wp-content\/uploads\/2020\/12\/display-oled-768x729.jpg 768w, https:\/\/rogerbit.com\/wprb\/wp-content\/uploads\/2020\/12\/display-oled-600x570.jpg 600w\" alt=\"\" width=\"280\" height=\"266\" \/><\/a><\/p>\n<p>Se trata de un m\u00f3dulo de pantalla OLED monocrom\u00e1tica DE 128\u00d764 puntos con interface I2C .Que presenta varias ventajas en comparaci\u00f3n con pantallas LCD, y podemos destacar su alto brillo, un muy buen contraste, un \u00e1ngulo de visi\u00f3n m\u00e1s amplio, y bajo consumo de energ\u00eda. ES compatible con Arduino Rasberry Pi y microcontroladores PIC entre otros. Trabaja con niveles l\u00f3gicos de 3.3V a 5V tiene un angulo de visi\u00f3n mayor a los 160 grados. el Tama\u00f1o de la pantalla es de 1,3 pulgadas. Se alimenta con un voltaje de 3.3V a 5V Se lo puede usar en aplicaciones como relojes inteligentes, MP3, term\u00f3metros, instrumentos, y proyectos varios, etc.<\/p>\n<p><strong>Caracter\u00edsticas<\/strong><\/p>\n<ul>\n<li>Interface: I2C(3.3V \/ 5V logic level)<\/li>\n<li>Resolution: 128 x 64<\/li>\n<li>Angle of view: &gt;160 degree<\/li>\n<li>Display color: Blue<\/li>\n<li>Display size: 1.3 inch<\/li>\n<li>Driver IC: SH1106<\/li>\n<li>Power supply: DC\u00a03.3V~5V<\/li>\n<li>Operating temperature: -20~70\u2019C<\/li>\n<li>Application: smart watch, MP3, thermometer, instruments, DIY projects, etc.<\/li>\n<\/ul>\n<hr \/>\n<p><strong>PCB<\/strong><\/p>\n<p><img loading=\"lazy\" class=\"alignnone size-large wp-image-6800\" src=\"https:\/\/rogerbit.com\/wprb\/wp-content\/uploads\/2022\/03\/pcb.png\" sizes=\"(max-width: 494px) 100vw, 494px\" srcset=\"https:\/\/rogerbit.com\/wprb\/wp-content\/uploads\/2022\/03\/pcb.png 494w, https:\/\/rogerbit.com\/wprb\/wp-content\/uploads\/2022\/03\/pcb-300x258.png 300w\" alt=\"\" width=\"494\" height=\"425\" \/><\/p>\n<hr \/>\n<p><img loading=\"lazy\" class=\"alignnone size-large wp-image-6801\" src=\"https:\/\/rogerbit.com\/wprb\/wp-content\/uploads\/2022\/03\/pcb_ser.png\" sizes=\"(max-width: 496px) 100vw, 496px\" srcset=\"https:\/\/rogerbit.com\/wprb\/wp-content\/uploads\/2022\/03\/pcb_ser.png 496w, https:\/\/rogerbit.com\/wprb\/wp-content\/uploads\/2022\/03\/pcb_ser-300x258.png 300w\" alt=\"\" width=\"496\" height=\"427\" \/><\/p>\n<p>Descargar archivo gerber \u2013&gt;\u00a0<a href=\"https:\/\/rogerbit.com\/wprb\/wp-content\/uploads\/2021\/11\/Gerber_esp32.zip\">Gerber_esp32<\/a><\/p>\n<hr \/>\n<p><strong>Circuito<\/strong><\/p>\n<p><img loading=\"lazy\" class=\"alignnone size-large wp-image-7849\" src=\"https:\/\/rogerbit.com\/wprb\/wp-content\/uploads\/2024\/12\/circuito-1024x591.jpg\" alt=\"\" width=\"1024\" height=\"591\" srcset=\"https:\/\/rogerbit.com\/wprb\/wp-content\/uploads\/2024\/12\/circuito-1024x591.jpg 1024w, https:\/\/rogerbit.com\/wprb\/wp-content\/uploads\/2024\/12\/circuito-300x173.jpg 300w, https:\/\/rogerbit.com\/wprb\/wp-content\/uploads\/2024\/12\/circuito-768x443.jpg 768w, https:\/\/rogerbit.com\/wprb\/wp-content\/uploads\/2024\/12\/circuito-1536x886.jpg 1536w, https:\/\/rogerbit.com\/wprb\/wp-content\/uploads\/2024\/12\/circuito-2048x1181.jpg 2048w, https:\/\/rogerbit.com\/wprb\/wp-content\/uploads\/2024\/12\/circuito-820x473.jpg 820w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/p>\n<hr \/>\n<p><strong>C\u00f3digo Fuente<\/strong><\/p>\n<pre class=\"lang:default decode:true \" title=\"C\u00f3digo Fuente\">#include &lt;WiFi.h&gt; \r\n#include &lt;NTPClient.h&gt;\r\n#include &lt;WiFiUdp.h&gt;\r\n#include &lt;EEPROM.h&gt;\r\n#include &lt;ESPAsyncWebServer.h&gt;\r\n#include &lt;TimeLib.h&gt;\r\n#include &lt;U8g2lib.h&gt;\r\n#include &lt;Wire.h&gt;\r\n\r\n\/\/ Configuraci\u00f3n WiFi\r\nconst char* ssid = \"Tu_Red_wifi\";\r\nconst char* password = \"Tu_Clave_Wifi\";\r\n\r\n\r\n\/\/ Configuraci\u00f3n OLED\r\nU8G2_SH1106_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, \/* reset=*\/ U8X8_PIN_NONE);\r\n\r\n\/\/ Configuraci\u00f3n NTP\r\nWiFiUDP ntpUDP;\r\nNTPClient timeClient(ntpUDP, \"pool.ntp.org\", -3 * 3600, 60000);\r\n\r\n\/\/ Configuraci\u00f3n del servidor web\r\nAsyncWebServer server(80);\r\n\r\n\/\/ Configuraci\u00f3n de pines\r\n#define LIGHT_PIN 12\r\n\r\n\/\/ Variables globales\r\nint onHour, onMinute, offHour, offMinute;\r\nint onDay, onMonth, onYear;\r\nint offDay, offMonth, offYear;\r\nbool lightStatus = false;\r\n\r\n\/\/ Funciones de configuraci\u00f3n y estado\r\nvoid saveSettings() {\r\n  EEPROM.write(0, onHour);\r\n  EEPROM.write(1, onMinute);\r\n  EEPROM.write(2, offHour);\r\n  EEPROM.write(3, offMinute);\r\n  EEPROM.write(4, lightStatus);\r\n  EEPROM.write(5, onDay);\r\n  EEPROM.write(6, onMonth);\r\n  EEPROM.write(7, onYear - 2000);\r\n  EEPROM.write(8, offDay);\r\n  EEPROM.write(9, offMonth);\r\n  EEPROM.write(10, offYear - 2000);\r\n  EEPROM.commit();\r\n}\r\n\r\nvoid loadSettings() {\r\n  onHour = EEPROM.read(0);\r\n  onMinute = EEPROM.read(1);\r\n  offHour = EEPROM.read(2);\r\n  offMinute = EEPROM.read(3);\r\n  lightStatus = EEPROM.read(4);\r\n  onDay = EEPROM.read(5);\r\n  onMonth = EEPROM.read(6);\r\n  onYear = EEPROM.read(7) + 2000;\r\n  offDay = EEPROM.read(8);\r\n  offMonth = EEPROM.read(9);\r\n  offYear = EEPROM.read(10) + 2000;\r\n}\r\n\r\nvoid updateLightState() {\r\n  digitalWrite(LIGHT_PIN, lightStatus ? HIGH : LOW);\r\n  Serial.println(lightStatus ? \"Luz encendida\" : \"Luz apagada\");\r\n  updateOLEDDisplay(); \/\/ Actualizar display cuando cambia el estado\r\n}\r\n\r\n\/\/ Funci\u00f3n para actualizar el display OLED\r\nvoid updateOLEDDisplay() {\r\n  u8g2.clearBuffer();\r\n  u8g2.setFont(u8g2_font_ncenB08_tr); \/\/ Elegir una fuente\r\n\r\n  \/\/ Mostrar hora y fecha actual\r\n  char currentTimeStr[30];\r\n  snprintf(currentTimeStr, sizeof(currentTimeStr), \"%02d:%02d:%02d %02d\/%02d\/%04d\", \r\n           hour(), minute(), second(), day(), month(), year());\r\n  u8g2.drawStr(0, 10, \"Hora Actual:\");\r\n  u8g2.drawStr(0, 20, currentTimeStr);\r\n\r\n  \/\/ Mostrar hora de encendido programada\r\n  char onTimeStr[30];\r\n  snprintf(onTimeStr, sizeof(onTimeStr), \"%02d:%02d %02d\/%02d\/%04d\", \r\n           onHour, onMinute, onDay, onMonth, onYear);\r\n  u8g2.drawStr(0, 30, \"Enc:\");\r\n  u8g2.drawStr(30, 30, onTimeStr);\r\n\r\n  \/\/ Mostrar hora de apagado programada\r\n  char offTimeStr[30];\r\n  snprintf(offTimeStr, sizeof(offTimeStr), \"%02d:%02d %02d\/%02d\/%04d\", \r\n           offHour, offMinute, offDay, offMonth, offYear);\r\n  u8g2.drawStr(0, 50, \"Apa:\");\r\n  u8g2.drawStr(30, 50, offTimeStr);\r\n\r\n  \/\/ Mostrar direcci\u00f3n IP\r\n  u8g2.drawStr(0, 64, WiFi.localIP().toString().c_str());\r\n\r\n  u8g2.sendBuffer();\r\n}\r\n\r\n\/\/ Configuraci\u00f3n inicial\r\nvoid setup() {\r\n  pinMode(LIGHT_PIN, OUTPUT);\r\n  Serial.begin(115200);\r\n\r\n  \/\/ Inicializar OLED\r\n  Wire.begin();\r\n  u8g2.begin();\r\n  u8g2.clearBuffer();\r\n  u8g2.setFont(u8g2_font_ncenB08_tr);\r\n  u8g2.drawStr(0, 10, \"Iniciando...\");\r\n  u8g2.sendBuffer();\r\n\r\n  EEPROM.begin(512);\r\n  loadSettings();\r\n  updateLightState();\r\n\r\n  WiFi.begin(ssid, password);\r\n  while (WiFi.status() != WL_CONNECTED) {\r\n    delay(1000);\r\n    Serial.println(\"Conectando a WiFi...\");\r\n  }\r\n  Serial.println(\"WiFi conectado\");\r\n  Serial.print(\"Direcci\u00f3n IP: \");\r\n  Serial.println(WiFi.localIP());\r\n\r\n  timeClient.begin();\r\n  timeClient.update(); \/\/ Actualizaci\u00f3n inmediata al inicio\r\n  time_t now = timeClient.getEpochTime();\r\n  setTime(now);\r\n\r\n  updateOLEDDisplay(); \/\/ Actualizar display con la hora exacta al inicio\r\n\r\n  server.on(\"\/\", HTTP_GET, [](AsyncWebServerRequest *request) {\r\n    String html = \"&lt;h1&gt;Programar Temporizador&lt;\/h1&gt;\";\r\n    timeClient.update();\r\n\r\n    time_t now = timeClient.getEpochTime();\r\n    setTime(now);\r\n    html += \"&lt;p&gt;Hora actual: \" + String(hour()) + \":\" + String(minute()) + \":\" + String(second()) + \"&lt;\/p&gt;\";\r\n    html += \"&lt;p&gt;Fecha actual: \" + String(day()) + \"\/\" + String(month()) + \"\/\" + String(year()) + \"&lt;\/p&gt;\";\r\n\r\n    html += \"&lt;p&gt;&lt;b&gt;Estado de la Luz:&lt;\/b&gt; \" + String(lightStatus ? \"Encendida\" : \"Apagada\") + \"&lt;\/p&gt;\";\r\n\r\n    html += \"&lt;p&gt;&lt;b&gt;Encendido Programado:&lt;\/b&gt; \" + String(onDay) + \"\/\" + String(onMonth) + \"\/\" + String(onYear) + \" \" + String(onHour) + \":\" + String(onMinute) + \"&lt;\/p&gt;\";\r\n    html += \"&lt;p&gt;&lt;b&gt;Apagado Programado:&lt;\/b&gt; \" + String(offDay) + \"\/\" + String(offMonth) + \"\/\" + String(offYear) + \" \" + String(offHour) + \":\" + String(offMinute) + \"&lt;\/p&gt;\";\r\n\r\n    html += \"&lt;form action='\/set' method='GET'&gt;\"\r\n            \"Encender: Hora &lt;input type='time' name='onTime'&gt; Fecha &lt;input type='date' name='onDate'&gt;&lt;br&gt;\"\r\n            \"Apagar: Hora &lt;input type='time' name='offTime'&gt; Fecha &lt;input type='date' name='offDate'&gt;&lt;br&gt;\"\r\n            \"&lt;input type='submit' value='Guardar'&gt;\"\r\n            \"&lt;\/form&gt;\";\r\n\r\n    request-&gt;send(200, \"text\/html\", html);\r\n  });\r\n\r\n  server.on(\"\/set\", HTTP_GET, [](AsyncWebServerRequest *request) {\r\n    if (request-&gt;hasParam(\"onTime\") &amp;&amp; request-&gt;hasParam(\"onDate\") &amp;&amp; \r\n        request-&gt;hasParam(\"offTime\") &amp;&amp; request-&gt;hasParam(\"offDate\")) {\r\n      String onTime = request-&gt;getParam(\"onTime\")-&gt;value();\r\n      String onDate = request-&gt;getParam(\"onDate\")-&gt;value();\r\n      String offTime = request-&gt;getParam(\"offTime\")-&gt;value();\r\n      String offDate = request-&gt;getParam(\"offDate\")-&gt;value();\r\n\r\n      onHour = onTime.substring(0, 2).toInt();\r\n      onMinute = onTime.substring(3, 5).toInt();\r\n      onYear = onDate.substring(0, 4).toInt();\r\n      onMonth = onDate.substring(5, 7).toInt();\r\n      onDay = onDate.substring(8, 10).toInt();\r\n\r\n      offHour = offTime.substring(0, 2).toInt();\r\n      offMinute = offTime.substring(3, 5).toInt();\r\n      offYear = offDate.substring(0, 4).toInt();\r\n      offMonth = offDate.substring(5, 7).toInt();\r\n      offDay = offDate.substring(8, 10).toInt();\r\n\r\n      saveSettings();\r\n      updateOLEDDisplay(); \/\/ Actualizar display despu\u00e9s de guardar\r\n      request-&gt;send(200, \"text\/html\", \"&lt;h1&gt;Guardado!&lt;\/h1&gt;&lt;a href='\/'&gt;Volver&lt;\/a&gt;\");\r\n    } else {\r\n      request-&gt;send(400, \"text\/html\", \"Faltan par\u00e1metros\");\r\n    }\r\n  });\r\n\r\n  server.begin();\r\n}\r\n\r\nvoid loop() {\r\n  timeClient.update();\r\n  time_t now = timeClient.getEpochTime();\r\n  setTime(now);\r\n\r\n  \/\/ Actualizar display cada segundo\r\n  static unsigned long lastDisplayUpdate = 0;\r\n  if (millis() - lastDisplayUpdate &gt; 1000) {\r\n    updateOLEDDisplay();\r\n    lastDisplayUpdate = millis();\r\n  }\r\n\r\n  if (year() == onYear &amp;&amp; month() == onMonth &amp;&amp; day() == onDay &amp;&amp; \r\n      hour() == onHour &amp;&amp; minute() == onMinute &amp;&amp; !lightStatus) {\r\n    lightStatus = true;\r\n    saveSettings();\r\n    updateLightState();\r\n  } else if (year() == offYear &amp;&amp; month() == offMonth &amp;&amp; day() == offDay &amp;&amp; \r\n             hour() == offHour &amp;&amp; minute() == offMinute &amp;&amp; lightStatus) {\r\n    lightStatus = false;\r\n    saveSettings();\r\n    updateLightState();\r\n  }\r\n}<\/pre>\n<hr \/>\n<p>No te pierdas ning\u00fan video m\u00e1s suscr\u00edbete a nuestro canal de telegram\u00a0<a href=\"https:\/\/t.me\/carlosvolt_electronica_robotica\">https:\/\/t.me\/carlosvolt_electronica_robotica<\/a><\/p>\n<hr \/>\n<div class=\"page-sidebar widget\" id=\"donation_buttons\"><form action=\"https:\/\/www.paypal.com\/cgi-bin\/webscr\" method=\"post\" target=\"_blank\" ><input type=\"hidden\" name=\"business\" value=\"donacion@rogerbit.com\"><input type=\"hidden\" name=\"bn\" value=\"mbjtechnolabs_SP\"><input type=\"hidden\" name=\"cmd\" value=\"_donations\"><input type=\"hidden\" name=\"item_name\" value=\"Ayuda a RogerBit.com\"><input type=\"hidden\" name=\"item_number\" value=\"www.rogerbit.com\"><input type=\"hidden\" class=\"set_donation_button_amount\" name=\"amount\" value=\"1\"><table ><tbody><tr><td><label for=\"rogerBit necesita de tu ayuda para seguir existiendo :-)\">rogerBit necesita de tu ayuda para seguir existiendo :-)<\/label><\/td><\/tr><\/tbody><\/table><table ><tbody><tr><td><input style=\"margin-top:10px;\" type=\"image\" name=\"submit\" border=\"0\" src=\"https:\/\/www.paypal.com\/en_US\/i\/btn\/btn_donateCC_LG.gif\" alt=\"PayPal - The safer, easier way to pay online\"><\/td><\/tr><\/tbody><\/table><input type=\"hidden\" name=\"currency_code\" value=\"USD\"><input type=\"hidden\" name=\"notify_url\" value=\"https:\/\/rogerbit.com\/wprb\/?Donation_Button&#038;action=ipn_handler\"><\/form><\/div>\n<hr \/>\n<p><strong>PROYECTO RECOMENDADO<\/strong><\/p>\n<p><iframe loading=\"lazy\" title=\"Encender luz desde thindspeak con esp32 - PCBWay.es\" width=\"1160\" height=\"653\" src=\"https:\/\/www.youtube.com\/embed\/Q8-XT-qfwhQ?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen><\/iframe><\/p>\n<\/div>\n<!-- AddThis Advanced Settings generic via filter on the_content --><!-- AddThis Share Buttons generic via filter on the_content -->","protected":false},"excerpt":{"rendered":"<p>En este tutorial, aprender\u00e1s a construir un sistema de temporizador programable utilizando un ESP32, un display OLED SH1106 y un servidor web. Este proyecto es ideal para automatizar el encendido y apagado de una luz o cualquier dispositivo conectado, estableciendo horarios espec\u00edficos desde una interfaz web f\u00e1cil de usar. Tal vez pueda interesarte proyectos en [&hellip;]<!-- AddThis Advanced Settings generic via filter on get_the_excerpt --><!-- AddThis Share Buttons generic via filter on get_the_excerpt --><\/p>\n","protected":false},"author":1,"featured_media":7851,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[11],"tags":[467,330,465,2061,2060,2042,1691,2059,921,214],"_links":{"self":[{"href":"https:\/\/rogerbit.com\/wprb\/wp-json\/wp\/v2\/posts\/7848"}],"collection":[{"href":"https:\/\/rogerbit.com\/wprb\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/rogerbit.com\/wprb\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/rogerbit.com\/wprb\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/rogerbit.com\/wprb\/wp-json\/wp\/v2\/comments?post=7848"}],"version-history":[{"count":2,"href":"https:\/\/rogerbit.com\/wprb\/wp-json\/wp\/v2\/posts\/7848\/revisions"}],"predecessor-version":[{"id":7852,"href":"https:\/\/rogerbit.com\/wprb\/wp-json\/wp\/v2\/posts\/7848\/revisions\/7852"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/rogerbit.com\/wprb\/wp-json\/wp\/v2\/media\/7851"}],"wp:attachment":[{"href":"https:\/\/rogerbit.com\/wprb\/wp-json\/wp\/v2\/media?parent=7848"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/rogerbit.com\/wprb\/wp-json\/wp\/v2\/categories?post=7848"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/rogerbit.com\/wprb\/wp-json\/wp\/v2\/tags?post=7848"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}