The Arduino package manager has a library called NTPClient, which provides, as you might guess, an NTP client. Using this with the system clock lets you keep reasonable time without a battery-backed RTC.

Once you know what time it is, scheduling events becomes trivial. This isn't a fully working example, but should give you the idea. The docs have more information. The NTPClient also works quite well with the AceTime library for time zone and other management.

#include <NTPClient.h>
#include <WiFiUdp.h>
#include <ESP8266WiFi.h>
#include <AceTime.h>
#include <ctime>

using namespace ace_time;
using namespace ace_time::clock;
using namespace std;

WiFiUDP ntpUDP;
const long utcOffsetInSeconds = 0;  
// Get UTC from NTP - let AceTime figure out the local time
NTPClient timeClient(ntpUDP, "pool.ntp.org", utcOffsetInSeconds, 3600);  
//3600s/h - sync time once per hour, this is sufficient.
// don't hammer pool.ntp.org!


static BasicZoneProcessor estProcessor;
static SystemClockLoop systemClock(nullptr /*reference*/, nullptr /*backup*/);

const char* ssid = // your SSID;
const char* password = // your wifi password;
 
void setup() {
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  Serial.println("Connecting to wifi...");
  while (WiFi.status() != WL_CONNECTED) {
    Serial.println('.');
    delay(500);
  }
  systemClock.setup();
  timeClient.begin();
}

int clockUpdateCounter = 50000;  
void loop(){
  // Update the system clock from the NTP client periodically
  if (++clockUpdateCounter > 50000){  // can be more elegant than this... depends on your loop speed, can actually use the real time for this too, I'm just making this simple because I don't have a lot of time...
    clockUpdateCounter = 0;
    timeClient.update();
    // doesn't matter how often you call timeClient.update().
    // you can put this in the main loop() if you want.  
    // We supplied 3600s as the refresh interval in the constructor
    // and internally .update() checks whether enough time has passed 
    // before making a request to the NTP server itself
    auto estTz = TimeZone::forZoneInfo(&zonedb::kZoneAmerica_Toronto, &estProcessor);
    auto estTime = ZonedDateTime::forUnixSeconds(timeClient.getEpochTime(), estTz);
    // using the system clock is optional, but has a few 
    // conveniences.  Here we just make sure that the systemClock remains 
    // sync'd with the NTP server.  Doesn't matter how often you do this
    // but usually around once an hour is plenty
    systemClock.setNow(estTime.toEpochSeconds());
  }
  systemClock.loop();
  delay(30);
}

The above keeps the system clock in sync with the NTP server. You can then use the system clock to fetch the time and use it for all types of timing purposes. eg :

 // get Time
  acetime_t nowT = systemClock.getNow();
  auto estTz = TimeZone::forZoneInfo(&zonedb::kZoneAmerica_Toronto, &estProcessor);
  auto nowTime = ZonedDateTime::forEpochSeconds(nowT, estTz);

Checking the time is fast, so you can do it inside loop() and only trigger the action when whatever time has elapsed.

This is a particularly nice solution for database integration since you can record a real timestamp of the actual date and time when logging your data to the database.

Answer from J... on Stack Overflow
🌐
Blogger
8266iot.blogspot.com › p › dont-delay.html
Home Automation and IOT with the ESP8266 and Arduino IDE: Don't delay!
This alone is one good reason is why programming the ESP8266 is different from programming e.g. an AVR with the Arduino IDE. If you replace the while statement with: ... Then it works as you would have expected. The system sits doing nothing until pin 5 goes LOW. So it looks like "delay" is the solution.
Discussions

c++ - Esp8266 Timer instead of delay - Stack Overflow
I'm working on a smart Irrigation system built on an ESP8266 microcontroller coded on Arduino ide; basically I want to send data of temperature to my database every 4 minutes, check the sensors eve... More on stackoverflow.com
🌐 stackoverflow.com
Fractional Microsecond Delay;
Your best bet is to use the chip's hardware timers. I'd start by reading this: https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/timer.html Depending on what you're doing, it might also be worth looking into the RMT peripheral. It's designed for generating infrared remote control signals but it can be used to precisely generate custom pulses for other purposes too. It's overkill but it'd get the job done. https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/rmt.html If you're willing to put in the time to learn the lower level ESP32 APIs, they'll seriously pay off in performance and flexibility. You should be able to accomplish microsecond timing without delayXXX() or interrupts using the RMT peripheral. More on reddit.com
🌐 r/esp8266
10
11
October 5, 2021
ESP8266 delay/milliseconds makes LED strip buggy
My setup ESP8266 powered by USB, common ground with LED strip 120 WS2812B LED's powered by a 5V 10A power supply D5 (GPIO14) as data pin The issue Currently I'm working on a project that us... More on github.com
🌐 github.com
8
December 29, 2019
Help with yield and delay

I guess your problem is a stack overflow, because of too many recursions.

You should try doing it with loops. Something like

while (Serial.available() == 0) {

delay(100);

}

And

do {

....

} while (inputChar != 13);

More on reddit.com
🌐 r/esp8266
3
3
July 3, 2022
🌐
Everything ESP8266
esp8266.com › viewtopic.php
ESP8266 how to scatter out the delays() properly - Everything ESP8266
Code: Select all64 bytes from ... transmitted, 231 packets received, 57% packet loss round-trip min/avg/max = 3.223/37.771/445.012 ms I have to have a delay() with at least the value of 500 in the middle of the main loop otherwise the results worsen to the point that if I don't ...
Top answer
1 of 1
2

The Arduino package manager has a library called NTPClient, which provides, as you might guess, an NTP client. Using this with the system clock lets you keep reasonable time without a battery-backed RTC.

Once you know what time it is, scheduling events becomes trivial. This isn't a fully working example, but should give you the idea. The docs have more information. The NTPClient also works quite well with the AceTime library for time zone and other management.

#include <NTPClient.h>
#include <WiFiUdp.h>
#include <ESP8266WiFi.h>
#include <AceTime.h>
#include <ctime>

using namespace ace_time;
using namespace ace_time::clock;
using namespace std;

WiFiUDP ntpUDP;
const long utcOffsetInSeconds = 0;  
// Get UTC from NTP - let AceTime figure out the local time
NTPClient timeClient(ntpUDP, "pool.ntp.org", utcOffsetInSeconds, 3600);  
//3600s/h - sync time once per hour, this is sufficient.
// don't hammer pool.ntp.org!


static BasicZoneProcessor estProcessor;
static SystemClockLoop systemClock(nullptr /*reference*/, nullptr /*backup*/);

const char* ssid = // your SSID;
const char* password = // your wifi password;
 
void setup() {
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  Serial.println("Connecting to wifi...");
  while (WiFi.status() != WL_CONNECTED) {
    Serial.println('.');
    delay(500);
  }
  systemClock.setup();
  timeClient.begin();
}

int clockUpdateCounter = 50000;  
void loop(){
  // Update the system clock from the NTP client periodically
  if (++clockUpdateCounter > 50000){  // can be more elegant than this... depends on your loop speed, can actually use the real time for this too, I'm just making this simple because I don't have a lot of time...
    clockUpdateCounter = 0;
    timeClient.update();
    // doesn't matter how often you call timeClient.update().
    // you can put this in the main loop() if you want.  
    // We supplied 3600s as the refresh interval in the constructor
    // and internally .update() checks whether enough time has passed 
    // before making a request to the NTP server itself
    auto estTz = TimeZone::forZoneInfo(&zonedb::kZoneAmerica_Toronto, &estProcessor);
    auto estTime = ZonedDateTime::forUnixSeconds(timeClient.getEpochTime(), estTz);
    // using the system clock is optional, but has a few 
    // conveniences.  Here we just make sure that the systemClock remains 
    // sync'd with the NTP server.  Doesn't matter how often you do this
    // but usually around once an hour is plenty
    systemClock.setNow(estTime.toEpochSeconds());
  }
  systemClock.loop();
  delay(30);
}

The above keeps the system clock in sync with the NTP server. You can then use the system clock to fetch the time and use it for all types of timing purposes. eg :

 // get Time
  acetime_t nowT = systemClock.getNow();
  auto estTz = TimeZone::forZoneInfo(&zonedb::kZoneAmerica_Toronto, &estProcessor);
  auto nowTime = ZonedDateTime::forEpochSeconds(nowT, estTz);

Checking the time is fast, so you can do it inside loop() and only trigger the action when whatever time has elapsed.

This is a particularly nice solution for database integration since you can record a real timestamp of the actual date and time when logging your data to the database.

🌐
Hackaday
hackaday.com › 2022 › 10 › 28 › esp8266-web-server-saves-60-power-with-a-1-ms-delay
ESP8266 Web Server Saves 60% Power With A 1 Ms Delay | Hackaday
October 28, 2022 - In [Tomaž]’s tests, that one millisecond delay reduced idle power consumption at 3.3 V from roughly 230 mW to around 70 mW — about 60% — while only delaying the web server’s response times by 6-8 milliseconds.
🌐
Random Nerd Tutorials
randomnerdtutorials.com › home › esp8266 › esp8266 projects › esp8266 interrupts and timers using arduino ide (nodemcu)
ESP8266 Interrupts and Timers using Arduino IDE (NodeMCU) | Random Nerd Tutorials
August 6, 2019 - When you call delay(1000) your program stops on that line for 1 second. delay() is a blocking function. Blocking functions prevent a program from doing anything else until that particular task is completed.
🌐
Reddit
reddit.com › r/esp8266 › fractional microsecond delay;
r/esp8266 on Reddit: Fractional Microsecond Delay;
October 5, 2021 -

Hey all, possess any of you managed to get fractional microsecond delay on the ESP8266/ESP32? I need to delay about 5.33 microseconds between setting a pin high and then back to low. I understand that delayMicroseconds might‏‏‎‏‏‎‏‏‎‏‏‎­be close, but wanted to see if there might be something with a bit more resolution. Thanks!

Find elsewhere
🌐
GitHub
github.com › FastLED › FastLED › issues › 945
ESP8266 delay/milliseconds makes LED strip buggy · Issue #945 · FastLED/FastLED
December 29, 2019 - I started playing around with the code more and I figured out that it was the FastLED itself (or maybe a combination with the WebSocket?). Whenever I don't have any waiting function and always call my FastLED function in the void loop() it'll work just fine. But whenever there's a delay (doesn't matter whether it's blocking or non-blocking) the LED strip starts to bug out.
Author   FastLED
🌐
Reddit
reddit.com › r/esp8266 › help with yield and delay
r/esp8266 on Reddit: Help with yield and delay
July 3, 2022 -

I'm trying to build a serial command line interface for an ESP8266. Here's some of my code:

String ReadUntilEnter(String currentInput) {

if (Serial.available() > 0) {

char inputChar = Serial.read();

// On newline, stop reading chars and return the string

if ((int) inputChar == 13) {

Serial.print("\r\n");

return currentInput;

}

// If the character is not a newline, add it to the string and keep listening

else {

Serial.print(inputChar);

currentInput += inputChar;

return ReadUntilEnter(currentInput);

}

}

// Wait for serial to become available

else {

delay(100);

return ReadUntilEnter(currentInput);

}

}

void loop() {

Serial.print("Console# ");

while (Serial.available() == 0) {}

String command = ReadUntilEnter("");

// handle command

}

Essentially, I want the users to be greeted with a prompt that says:

Console#

The user can then type in a command:

Console# hack cia

The issue I am encountering happens when the user has typed one or more characters inside the prompt, but has not yet hit enter. The function is holding up the thread while waiting for the next character. The watchdog does not like this and will reset the ESP if someone takes too long to type a command. It works decently well with the 100 ms delay but if you take a long time, it will be halted by the watchdog. I have tried using the yield() function in place of the 100 ms delay, but the ESP would crash once it hit the yield statement - not a watchdog stop but a full crash with a stack trace and everything. Can someone please give me some advice? I've looked at tons of forum threads on the topic of the watchdog but I can't get it to work

Thanks so much

🌐
Arduino Forum
forum.arduino.cc › projects › programming
esp8266 problem no delay time possible in my programm - Programming - Arduino Forum
August 23, 2017 - Dear everybody, I want to control a pump via alexa and an esp8266 (plus relais). The problem I have is that I just wanna switch on the pump for a small time 5s therefore I need to insert a delay for my GPIO somehow The Code i use looksas followed: #include #include #include "fauxmoESP.h" #define WIFI_SSID ""//change your Wifi name #define WIFI_PASS "**"//Change your Wifi Password #define SERIAL_BAUDRATE 115200 fauxmoESP fauxmo; //declare switching pins //Cha...
🌐
Reddit
reddit.com › r/esp8266 › do i need a timer/delay circuit to make this work?
r/esp8266 on Reddit: Do I need a timer/delay circuit to make this work?
July 28, 2022 -

I bought a cheap ESP-01/relay module I picked up to ultimately wire up my garage door. Everything works as advertised, but I'm getting a low/ground pulse on GPIO0 on startup that's triggering the relay momentarily. I have spent way too much time googling this issue to no avail. I've found others with same issue, but haven't found any fixes. I don't think there's anything in the software that will prevent it, and I've tried a 10k pullup on GPIO0 without success. Should I try a lower resistance resistor?

Ultimately I'll probably just buy a better ESP8266 for this project, but just for the sake of learning how to use a timer/delay circuit, I thought I'd post here for any advice/recommendations. Keep in mind I'm a bit of a novice with all this stuff.

Edit: Recommendations in here I tried:

2200uf/35v across power and ground. Still pulses

Tried using GPIO2 instead of 0. Still pulses

Tried a delay of 5 seconds right off the bat in the setup function. Still pulses

Swapped order of digitalWrite and pinMode. Still pulses

Appreciate all the suggestions!

Bonus video: https://www.youtube.com/watch?v=jnZMach5tH8

🌐
Stack Overflow
stackoverflow.com › questions › 64553495 › delay-in-connect-function-while-using-esp8266-with-arduino
mqtt - delay in .connect() function while using ESP8266 with arduino - Stack Overflow
I'm using ESP8266-7 as the only micocontroller in my project and I have a tiny problem with it. there are sometimes that the internet line is broken and my ESP tries to reconnect to the broker. while this happens, the program freezes until the internet gets back online and ESP reconnects to the broker.
🌐
Arduino Forum
forum.arduino.cc › projects › programming
5 Seconds delay on ESP8266 in Server Request - Programming - Arduino Forum
November 18, 2021 - I have a concern on my Internet of Things project. I have 5 seconds delay on the components of ESP8266. Short explanation of my project, is RFID based door security system using magnetic door lock.
🌐
Nanona
sub.nanona.fi › esp8266 › timing-and-ticks.html
Timing and clocking with ESP8266
Invoking os_delay_us() allows us to halt processing with microsecond granularity. Since there is always call overhead to calling os_delay_us -function, these tests express how long is really slept, when we expect one microsecond sleep. We know that because esp8266's clock rate being 80Mhz, ...
🌐
GitHub
github.com › esp8266 › Arduino › issues › 5999
Can Delay(..) be interrupted?! · Issue #5999 · esp8266/Arduino
April 19, 2019 - This is the sketch which shows delay(..) doesn't work as expected (i.e. delay is blocking until esp_schedule() is called).
Author   esp8266
🌐
GitHub
github.com › esp8266 › Arduino › issues › 3220
Delay() at start of Setup() prevents esp8266 from connecting to a network · Issue #3220 · esp8266/Arduino
May 9, 2017 - We use a small delay() of a few seconds to allow telemetry to start on an external device such as a pc before the esp starts.
Author   esp8266