Use millis or micros if you need more precise timing.

Here is an example sketch:

long lastDoTime = 0;

void setup(){
    Serial.begin(115200);
    delay(1000);
    Serial.println("Hello! We will do something at every ms");
}

void doThisAtEvery(int ms){
    if( millis() - lastDoTime >= ms ){
        // Must save the lastDoTime
        lastDoTime  = millis();

        // Do some stuff at every ms
    }
}

void loop(){
    // It will do the thing in every 100 ms.
    doThisAtEvery(100);
}

If you want to toggle a pin let's say every 100 microsec

long lastToggleTime = 0;
int motorPin = 14;
boolean lastPinState = LOW;

void setup(){
    Serial.begin(115200);
}

void togglePinEvery(int micros){
    if( micros() - lastToggleTime >= micros ){
        lastToggleTime = micros();
        digitalWrite(motorPin,!lastPinState);
        lastPinState = !lastPinState;
    }
}

void loop(){
    togglePinEvery(100);
}

EDIT Since you wanted timers only.

Here is a detailed explanation about timers: https://techtutorialsx.com/2017/10/07/esp32-arduino-timer-interrupts/

Code example:

volatile int interruptCounter;
int totalInterruptCounter;
 
hw_timer_t * timer = NULL;
portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
 
void IRAM_ATTR onTimer() {
  portENTER_CRITICAL_ISR(&timerMux);
  interruptCounter++;
  portEXIT_CRITICAL_ISR(&timerMux);
 
}
 
void setup() {
 
  Serial.begin(115200);
 
  timer = timerBegin(0, 80, true);
  timerAttachInterrupt(timer, &onTimer, true);
  timerAlarmWrite(timer, 1000000, true);
  timerAlarmEnable(timer);
 
}
 
void loop() {
 
  if (interruptCounter > 0) {
 
    portENTER_CRITICAL(&timerMux);
    interruptCounter--;
    portEXIT_CRITICAL(&timerMux);
 
    totalInterruptCounter++;
 
    Serial.print("An interrupt as occurred. Total number: ");
    Serial.println(totalInterruptCounter);
 
  }
}
Answer from Dr.Random on Stack Overflow
🌐
Random Nerd Tutorials
randomnerdtutorials.com › home › project › esp32 › get epoch/unix time with the esp32 (arduino)
Get Epoch/Unix Time with the ESP32 (Arduino) | Random Nerd Tutorials
February 16, 2021 - This was a quick guide showing you how to get epoch/unix time with the ESP32. The epoch time is the number of seconds elapsed since January 1 1970.
Top answer
1 of 1
1

Use millis or micros if you need more precise timing.

Here is an example sketch:

long lastDoTime = 0;

void setup(){
    Serial.begin(115200);
    delay(1000);
    Serial.println("Hello! We will do something at every ms");
}

void doThisAtEvery(int ms){
    if( millis() - lastDoTime >= ms ){
        // Must save the lastDoTime
        lastDoTime  = millis();

        // Do some stuff at every ms
    }
}

void loop(){
    // It will do the thing in every 100 ms.
    doThisAtEvery(100);
}

If you want to toggle a pin let's say every 100 microsec

long lastToggleTime = 0;
int motorPin = 14;
boolean lastPinState = LOW;

void setup(){
    Serial.begin(115200);
}

void togglePinEvery(int micros){
    if( micros() - lastToggleTime >= micros ){
        lastToggleTime = micros();
        digitalWrite(motorPin,!lastPinState);
        lastPinState = !lastPinState;
    }
}

void loop(){
    togglePinEvery(100);
}

EDIT Since you wanted timers only.

Here is a detailed explanation about timers: https://techtutorialsx.com/2017/10/07/esp32-arduino-timer-interrupts/

Code example:

volatile int interruptCounter;
int totalInterruptCounter;
 
hw_timer_t * timer = NULL;
portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
 
void IRAM_ATTR onTimer() {
  portENTER_CRITICAL_ISR(&timerMux);
  interruptCounter++;
  portEXIT_CRITICAL_ISR(&timerMux);
 
}
 
void setup() {
 
  Serial.begin(115200);
 
  timer = timerBegin(0, 80, true);
  timerAttachInterrupt(timer, &onTimer, true);
  timerAlarmWrite(timer, 1000000, true);
  timerAlarmEnable(timer);
 
}
 
void loop() {
 
  if (interruptCounter > 0) {
 
    portENTER_CRITICAL(&timerMux);
    interruptCounter--;
    portEXIT_CRITICAL(&timerMux);
 
    totalInterruptCounter++;
 
    Serial.print("An interrupt as occurred. Total number: ");
    Serial.println(totalInterruptCounter);
 
  }
}
Discussions

ESP32 Wake stub get elapsed time
Hardware: Board: ESP32 Dev Module Core Installation/update date: 16/jun/2020 IDE name: Arduino IDE Flash Frequency: 80Mhz PSRAM enabled: no Upload Speed: 115200 Computer OS: Windows 10 Description: when wake stub starts I want to know ho... More on github.com
🌐 github.com
3
August 19, 2020
How to get time that spent on deep sleep
Hi, Can i get how much time the esp32 spent while deep sleep mode active? On my project, I am using deep sleep feature. My esp sleeping 12 hour a day. If we use gpio while esp sleeping, my device&#... More on github.com
🌐 github.com
5
May 3, 2021
How to get accurate timing in an ISR?
I've done something similar for rc car signals. Use a free running timer. Set it up to run at a resolution that you need. Then, read and store the timers current count in a variable. Once the isr exits do the math in main routine. More on reddit.com
🌐 r/esp32
9
2
February 27, 2025
c - How can I get time taken from http request ESP32 - Stack Overflow
I am currently trying to get the time an HTTP request(downloading 1 file) needs to get done using ESP32 but the API has no option for it. I can set a timeout but I dont have the true time it needed... More on stackoverflow.com
🌐 stackoverflow.com
🌐
ESP32 Forum
esp32.com › viewtopic.php
get current time in millis() - ESP32 Forum
July 21, 2017 - This is how arduino gets millis https://github.com/espressif/arduino-es ... misc.c#L50 You can also call esp_log_timestamp() from esp_log.h which is the same timestamp used in the ESP_LOGx() functions. You can also use arduino in esp-idf https://github.com/espressif/arduino-es ... -component ... This might be a useful previous post: https://esp32.com/viewtopic.php?t=1468 If it were me, I'd probably use "gettimeofday".
🌐
GitHub
github.com › espressif › arduino-esp32 › issues › 4270
ESP32 Wake stub get elapsed time · Issue #4270 · espressif/arduino-esp32
August 19, 2020 - static const char RTC_RODATA_ATTR now_str[] = "now=%ld\n"; // Get current RTC time SET_PERI_REG_MASK(RTC_CNTL_TIME_UPDATE_REG, RTC_CNTL_TIME_UPDATE); while (GET_PERI_REG_MASK(RTC_CNTL_TIME_UPDATE_REG, RTC_CNTL_TIME_VALID) == 0) { ets_delay_us(1); } SET_PERI_REG_MASK(RTC_CNTL_INT_CLR_REG, RTC_CNTL_TIME_VALID_INT_CLR); uint64_t now = READ_PERI_REG(RTC_CNTL_TIME0_REG); now |= ((uint64_t)READ_PERI_REG(RTC_CNTL_TIME1_REG)) << 32; ets_printf(now_str,now); // print always 0 here
Author   espressif
🌐
ESP32 Forum
esp32.com › viewtopic.php
ESP32 Wake stub get elapsed time - ESP32 Forum
August 19, 2020 - Use below lines of code in start of your main code: struct timeval now; gettimeofday(&now, NULL); int sleep_time_ms = ((now.tv_sec - sleep_enter_time.tv_sec) * 1000) + ((now.tv_usec - sleep_enter_time.tv_usec) / 1000); printf("sleep_time_ms %d\r\n", sleep_time_ms); this will give you time spend ...
🌐
GitHub
github.com › espressif › arduino-esp32 › issues › 5147
How to get time that spent on deep sleep · Issue #5147 · espressif/arduino-esp32
May 3, 2021 - Hi, Can i get how much time the esp32 spent while deep sleep mode active? On my project, I am using deep sleep feature. My esp sleeping 12 hour a day. If we use gpio while esp sleeping, my device's next sleep time will be shifted. So I have to calculate how much time that i spent in deep sleep time until gpio wake up occurs.
Author   espressif
🌐
Programming Electronics Academy
programmingelectronics.com › home › using time features with your esp32 [guide + code]
Using time features with your ESP32 [Guide + Code] - Programming Electronics Academy
June 12, 2024 - The ESP32 device acts as the client and the time server acts as the server. . Once you are connected to the internet via your WiFi connection, you will need to connect to a time server to get the current date and time.
🌐
Espressif
docs.espressif.com › projects › esp-idf › en › latest › esp32 › api-reference › system › esp_timer.html
ESP Timer (High Resolution Timer) - ESP32 - — ESP-IDF Programming Guide latest documentation
The time passed since the initialization of ESP Timer can be obtained using the convenience function esp_timer_get_time(). The initialization happens shortly before the app_main function is called. This function is fast and has no locking mechanisms that could potentially introduce delays or ...
Find elsewhere
🌐
Espressif
docs.espressif.com › projects › esp-idf › en › stable › esp32 › api-reference › system › system_time.html
System Time - ESP32 - — ESP-IDF Programming Guide v6.0.2 documentation
To modify the RTC clock source, set CONFIG_RTC_CLK_SRC in project configuration. More details about the wiring requirements for the external crystal or external oscillator, please refer to the Hardware Design Guidelines. To get the current time, use the POSIX function gettimeofday().
🌐
Hackster.io
hackster.io › ronbentley1 › esp-32-elapsed-timer-alerting-framework-56473e
ESP 32 Elapsed Timer Alerting Framework - Hackster.io
October 5, 2022 - However, there is nothing special ... the ETA elapsed time interval would have a different time value/meaning which would need to be taken into account when defining ETAs. The ETA framework was developed using an ESP 32S 30 pin WROOM microcontroller and the Arduino IDE. The IDE board selection was "DOIT ESP32 DEVKIT ...
🌐
PlatformIO
registry.platformio.org › libraries › dejwk › roo_time
dejwk/roo_time: Arduino-compliant ESP32-tested library for ...
July 4, 2025 - The world's first package and project dependency management solution for embedded development
Top answer
1 of 2
1

Hi Mate I suggest to use the Network Time Protocol. It’s a standard Internet Protocol (IP) for synchronizing the computer clocks to some reference over a network. The protocol can be used to synchronize all networked devices to Coordinated Universal Time (UTC). NTP sets the clocks of computers to UTC, any local time zone offset or day light saving time offset is applied by the client. In this manner clients can synchronize to servers regardless of location and time zone differences. The server is using the User Datagram Protocol (UDP) on port 123. A client then transmits a request packet to a NTP server. In response to this request the NTP server sends a time stamp packet.

Please try this code:

#include "NTPClient.h"
#include "ESP8266WiFi.h"
#include "WiFiUdp.h"

const char *ssid = "***********";
const char *password = "***********";

const long utcOffsetInSeconds = 0;

char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};

// Define NTP Client to get time
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org", utcOffsetInSeconds);

void setup(){
Serial.begin(115200);

WiFi.begin(ssid, password);

while ( WiFi.status() != WL_CONNECTED ) {
delay ( 500 );
Serial.print ( "." );
}

timeClient.begin();
}

void loop() {
timeClient.update();

Serial.print(daysOfTheWeek[timeClient.getDay()]);
Serial.print(", ");
Serial.print(timeClient.getHours());
Serial.print(":");
Serial.print(timeClient.getMinutes());
Serial.print(":");
Serial.println(timeClient.getSeconds());
//Serial.println(timeClient.getFormattedTime());

delay(1000);
}

Note: the line:

const long utcOffsetInSeconds = 0;

sets the UTC time (basically the Greenwich time with no light saving time offset), if you wish, set your own offset in seconds from the Greenwich time. Great article here: https://www.instructables.com/Getting-Time-From-Internet-Using-ESP8266-NTP-Clock/

If you get two readings and you make the difference between the two, you have the duration of the operation and, (very important since we are talking about network operations), the time reference for a following analysis.

I hope this helps All the best

2 of 2
0

Firstly, calling gettimeofday() and calculating the difference is IMHO too much effort for such a simple task. It's easier to call esp_timer_get_time() to get microseconds since boot and calculate durations based on that.

Secondly, the custom event handler which you've given your HTTP client (_http_event_handler) gets called for each relevant event in the HTTP download, so use that to see how long each step takes. I've converted to milliseconds because it seems the correct unit scale to measure download events.

uint64_t start_time;
esp_http_client_config_t config = {
    .url = DOWNLOAD_FILE_URL,
    .event_handler = _http_event_handler,
    .user_data = &start_time,
};
esp_http_client_handle_t client = esp_http_client_init(&config);
start_time = esp_timer_get_time();
esp_err_t err = esp_http_client_perform(client);
ESP_LOGI(TAG, "Total time %u ms", (uint32_t)((esp_timer_get_time() - start_time) / 1000));
...

esp_err_t _http_event_handle(esp_http_client_event_t *evt) {
    uint32_t duration_ms = (uint32_t) ((esp_timer_get_time() - *(uint64_t*)(evt->user_data)) / 1000);
    switch(evt->event_id) {
        case HTTP_EVENT_ERROR:
            ESP_LOGI(TAG, "HTTP_EVENT_ERROR %u ms", duration_ms);
            break;
        case HTTP_EVENT_ON_CONNECTED:
            ESP_LOGI(TAG, "HTTP_EVENT_ON_CONNECTED %u ms", duration_ms);
            break;
        case HTTP_EVENT_HEADER_SENT:
            ESP_LOGI(TAG, "HTTP_EVENT_HEADER_SENT %u ms", duration_ms);
            break;
        case HTTP_EVENT_ON_HEADER:
            ESP_LOGI(TAG, "HTTP_EVENT_ON_HEADER %u ms", duration_ms);
            printf("%.*s", evt->data_len, (char*)evt->data);
            break;
        case HTTP_EVENT_ON_DATA:
            ESP_LOGI(TAG, "HTTP_EVENT_ON_DATA, len=%d %u ms", evt->data_len, duration_ms);
            break;
        case HTTP_EVENT_ON_FINISH:
            ESP_LOGI(TAG, "HTTP_EVENT_ON_FINISH %u ms", duration_ms);
            break;
        case HTTP_EVENT_DISCONNECTED:
            ESP_LOGI(TAG, "HTTP_EVENT_DISCONNECTED %u ms", duration_ms);
            break;
    }
    return ESP_OK;
}

Finally, note that if you're doing an HTTPS download then the poor little ESP32 will take a significant time performing the TLS handshake crypto calculations.

🌐
Arduino Forum
forum.arduino.cc › projects › programming
Question about ESP32 millis() counter? - Programming - Arduino Forum
March 8, 2021 - Hello, I have this kind of question. Is there any limitation about max millis() counter? I mean does it matter if currenttime in millis counts up certain value and the whole loop stops? I'm using millis() in order to set one counter to 0. At the moment ESP32 plugged to serial monitor about 23hours ticking, the millis() was working fine.
🌐
ESP32 Forum
esp32.com › viewtopic.php
RTC timer in deep sleep - ESP32 Forum
July 10, 2020 - Hi I would know the time elapsed from start and end of the deep sleep. After some search I found a function (below my implementation): ... RTC_IRAM_ATTR uint64_t pw_getTime(void) { SET_PERI_REG_MASK(RTC_CNTL_TIME_UPDATE_REG, RTC_CNTL_TIME_UPDATE_M); while (GET_PERI_REG_MASK(RTC_CNTL_TIME_UPDATE_REG, RTC_CNTL_TIME_VALID_M) == 0) { } uint64_t now = READ_PERI_REG(RTC_CNTL_TIME0_REG); now |= ((uint64_t) READ_PERI_REG(RTC_CNTL_TIME1_REG)) << 32; return now * 100 / (RTC_CTNL_SLOWCLK_FREQ / 10000); // scale RTC_CTNL_SLOWCLK_FREQ to avoid overflow; } This function is called in stub when the sleep ends; obviously for obtain the time elapsed I must call this function before enter the sleep, but in this case it crashs, I solved it by cloning the function without the RTC_IRAM_ATTR attribute.
🌐
GitHub
github.com › sstaub › Timer
GitHub - sstaub/Timer: Small library for measuring elapsed time between start and stop command · GitHub
Timer timer; // for micro second resolution: Timer timer(MICROS); timer.start(); // start the timer timer.pause(); // pause the timer timer.resume(); // resume the timer timer.stop(); // stops the timer timer.read(); // gives back the elapsed time in milli or micro seconds · Complete example: Here we created one timer, you can run it and get the result in the Serial monitor.
Starred by 31 users
Forked by 3 users
Languages   C++
🌐
Reddit
reddit.com › r/esp32 › how to measure amount of time before battery fails
r/esp32 on Reddit: How to Measure Amount of Time Before Battery Fails
November 24, 2022 -

I've been playing with some different ways of powering an ESP32 with a battery. I want to measure the amount of time before it fails, which could be days.

It seems like a good way to do this would be to write the elapsed time since bootup to EEPROM, but I haven't played with that yet.

It's probably not hard, but I was wondering if anyone knows of existing code, or a better method, before I start reinventing the wheel. My Googling skills aren't working too well today and all the examples I've found so far just show how to store and read one byte of data (the state of a push button).

🌐
Espressif
docs.espressif.com › projects › esp-idf › en › latest › esp32 › api-reference › system › system_time.html
System Time - ESP32 - — ESP-IDF Programming Guide latest documentation
October 13, 2022 - The RTC clock source may not meet ... configurations and power consumption, refer to Low Power Mode in Bluetooth LE. To get the current time, use the POSIX function gettimeofday()....
🌐
ESP32 Forum
esp32.com › board index › english forum › discussion forum › esp-idf
How to show Date and Time in log? - ESP32 Forum
Milliseconds Since Boot ... something like "YYYY-MM-DD hh:mm:ss" ... The ESP32 only knows elapsed time either milliseconds since boot (if you use LOG_TIMESTAMP_SOURCE_RTOS) or HH:MM:SS.SSS since the last power up (if you use LOG_TIMESTAMP_SOURCE_SYSTEM)....