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 OverflowESP32 Wake stub get elapsed time
How to get time that spent on deep sleep
How to get accurate timing in an ISR?
c - How can I get time taken from http request ESP32 - Stack Overflow
kiss smart unwritten sand brave roll paltry coherent cow lush
This post was mass deleted and anonymized with Redact
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
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.
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).
Its actually surprisingly hard to estimate battery life, especially over long periods. Battery voltage is not linear, meaning that it will suddenly drop off as it gets close to "empty". This also depends on the chemistry of the battery. Like others have said, you can use voltage to try and guess where the battery is at, but its not an exact science. You might need to characterize your battery and create a lookup table to check the level.
You can also try to estimate overall battery life by measuring your average current draw and checking that against the mAh rating of your battery.
Don't reinvent the wheel, there are literally chips that will do this for you. I've used the BQ27000 before, many years ago, but there's probably better and cheaper options available today. These fuel gauges track the actual amount of power going into and coming out of the battery to know exactly how much power is in a battery. They just need to be fully charged and then fully discharged to calibrate.