To my understanding it is possible and the ESP8266 internal clock is fairly precise … and I only need it to wake up at around the exact time (give or take 3 seconds) then re-calibrate it’s interval clock to compensate to the real world time … and back to sleep - just to wake up later at a given time or at exact pre-configured time.
Eventually it will trigger a simple sensor at a specific minute on every hour of the day .
I’m not sure if you can achieve this because I don’t think you can time the wake-up/sleep proces with this much accuracy. You’ll also need to be doing the measurements and so on.
I’m thinking you can set the ESP to wake up, sync time, do measurements and than wait for a specific time to put it in deepsleep.
E.g.
Wakeup at 10.00
(do stuff here, sync time and so on)
DeepSleep at 10.05 (give it some time to handle things)
Deepsleep for 55 minutes.
That way you can be fairly sure it will trigger at the right times. 5 minutes or more to do stuff will probably be overkill for reading a couple sensors, but the time trigger will be accurate I think.
lets say interval is 60 seconds and time to wake up is at 12:00
1.wakeup
2.get rtc
3.realize it is 11:58 change 60 to 180 (minus all other delays (can be pre calculated).
4.do your thing ( sensor / blinking )
go back to sleep
1.wake up at 12:00
repeat …
I just dont know the coding syntax to achieve this …
No, it’s not possible to wake an ESP from itself. You have to put in a signal to the ESP to wake up from deepsleep. You cannot set a timer to wake up from itself because it’s not active.
@Lichtsignaal but the duration of required sleep time can be calculated from trigger time less current time.
@dandan yes this can be done but the ESP’s clock is quite poor and loses up to 10 minutes per day. Probably not a problem in your case.
Until recently maximum deepSleep was defined as 2 to the power 32 which is 4,294,496,296 micro seconds or 4295 seconds or approx 71.6 minutes.
Create a long variable based on (X * hours() * 3600) + (Y * minutes() * 60) + (Z * seconds() ) for your trigger time. So if you want the trigger at 10:15:45 X is 10, Y is 15 and Z is 45.
Establish current time as a long from RTC in the same way. Compare the 2 longs and set the deepSleep duration. Keep using the maximum deepSleep duration until trigger time is less than 4295 seconds.
I saw a GitHub post recently about a change to deepSleep but struggling to find it. Will post if I find it.
uint64 time_in_us: the duration of time (ÎĽs) when the device is in Deep-sleep.
The theoretical maximum value of time_in_us can be calculated by formula:
(time_in_us / cali) << 12 = 2^31 - 1
• cali = system_rtc_clock_cali_proc(), the cali is the RTC clock period (in
us); bit11 ~ bit0 are decimal. For more details about the cali, please see the
API: system_rtc_clock_cali_proc.
So… as I understand : maximum period of a deep sleep can be up to 192 minutes… (3.2 h)…
What about light sleep ? will it be 24H or more ?
But even so - can you direct me to a code (or edit my initial code) showing a calibration of the wake up interval - based on input from Blynk RTC widget ?
I’m sure someone already have done that . .but I cant seem to find an example code…
Take a look at some of the logic in this stripped down version of your sketch
// MaxSleep.ino per https://community.blynk.cc/t/blynk-rtc-time-compensation-to-wake-up-from-deep-sleep-on-exact-second/16216
#define BLYNK_PRINT Serial
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <TimeLib.h>
#include <WidgetRTC.h>
char auth[] = "auth";
char ssid[] = "ssid";
char pass[] = "pass";
BlynkTimer timer;
WidgetRTC rtc;
// seconds in a day 86400 but rolls over to 0 after 86399
unsigned int sleepSeconds; // calculate from timeNow and wakeUpAt
unsigned int wakeUpAt = 43200; // 12 noon X 3600s
unsigned int timeNow; // time now from RTC in seconds
unsigned int maxSleep = 3600; // say 60 minutes = 3600 seconds
// digitalWrite(BUILTIN_LED, HIGH); // NOT HERE
void clockDisplay()
{
if(year() != 1970){
String currentTime = String(hour()) + ":" + minute() + " " + second()+ "'";
//String currentDate = String(day()) + "/" + month() + "/" + year();
timeNow = ((hour() * 3600) + (minute() * 60) + second()) * 100000;
if(timeNow > wakeUpAt){ // trigger time has already passed for today
Serial.println("Trigger time has already passed for today");
if(86399 - timeNow >= maxSleep){ // more than 60 minutes to midnight
Serial.println("Sleeping for maximum time");
sleepSeconds = maxSleep;
}
else{ // less than 60 minutes to midnight
sleepSeconds = (86399 - timeNow);
Serial.println("Sleeping until midnight");
}
}
else{ // trigger time has not passed for today
Serial.println("Trigger time has not passed for today");
if(wakeUpAt - timeNow >= maxSleep){ // more than 60 minutes to trigger time
Serial.println("Sleeping for maximum time");
sleepSeconds = maxSleep;
}
else{ // less than 60 minutes to trigger time
sleepSeconds = (wakeUpAt - timeNow);
Serial.println("Sleeping until trigger time");
}
}
Serial.printf("I'm going to Sleep for %d seconds\n\n", sleepSeconds);
ESP.deepSleep(sleepSeconds * 1000000);
delay(100);
}
}
BLYNK_CONNECTED() {
rtc.begin(); // Synchronize time on connection
}
void setup()
{
Serial.begin(9600);
Blynk.begin(auth, ssid, pass);
pinMode(BUILTIN_LED, OUTPUT);
pinMode(D0, WAKEUP_PULLUP);
setSyncInterval(1*60); // Sync interval in minutes
timer.setInterval(10*1000L, clockDisplay);
for (int i = 0; i < 20; i++)
{
digitalWrite(BUILTIN_LED, LOW);
delay(100);
digitalWrite(BUILTIN_LED, HIGH);
delay(100);
}
// moved deepSleep to the clockDisplay function
}
void loop()
{
Blynk.run();
timer.run();
}
With the following revised lines in setup() and maxSleep set to 40s for testing purposes it shows a cycle time, including connection to the server of 43 to 44 seconds.
setSyncInterval(1); // Sync interval in seconds
timer.setInterval(1000L, clockDisplay);
for (int i = 0; i < 10; i++)
{
digitalWrite(BUILTIN_LED, LOW);
delay(20);
digitalWrite(BUILTIN_LED, HIGH);
delay(20);
}
With an average “cali” around 24900 on my WeMos and mods to the libraries to include Espressif changes to deepSleep I am going to try for a 12000 second sleep (3h20m).
[3188] Connected to WiFi
[3188] IP: 192.168.10.172
[3188]
___ __ __
/ _ )/ /_ _____ / /__
/ _ / / // / _ \/ '_/
/____/_/\_, /_//_/_/\_\
/___/ v0.4.8 on Arduino
[3194] Connecting to blynk-cloud.com:8442
[3384] Ready (ping: 98ms).
[3786] Time sync: OK
Current time: 19:22:48
Trigger time has already passed for today
Sleeping for maximum time
I'm going to Sleep for 12000 seconds
I’ll report back later to see if it manages to sleep for 3h40m
Ran it twice and the 200m sleep was just 55m on both occasions.
The problem with the deepSleep function is that it doesn’t give any warning of invalid parameters and doesn’t even give the original 72m maximum when you request longer than whatever the new limit is.
Dropped it down to 180m to see what that comes up with.
@dandan with the version of deepSleep() that most people use it doesn’t handle the overflow of 32 bit numbers to 64 bit numbers. So in simple terms it works on a modulus 4295 seconds basis when you convert the microseconds back to seconds. So if it’s set at 4300 seconds the sleep after modulus (rollover) is just 5 seconds.
Espressif introduced 64 bit numbers for deepSleep back in May and it’s available by using their SDK 2.1.0.
After a lot of messing about I can now sleep for 12600s (3h 30m) rather than the old 1h 12m.
I also modified my version of the sketch to better handle the midnight rollover for extended sleep periods. It now sleeps the full 12600s if time to midnight plus midnight to trigger time is > 12600s. And maximum seconds from now until midnight plus time until trigger time after midnight if this is less than 12600s.
The new deepSleep() has the same inaccuracy as before so it will wake a little under 3% early. So you don’t get 12600s the actual clock time is around 12250s.
With trigger time set for 00:20:00 Serial Monitor now shows:
[3365] Ready (ping: 80ms).
[3767] Time sync: OK
Current time: 21:01:06
Trigger time has already passed for today
Sleeping until after midnight
RTC speed: 25090
I'm going to Sleep for 11933 seconds
I'm going to Sleep for 11933000 milliseconds (or X 1000 microseconds)
Note you can’t show the deepSleep microseconds directly in Serial Monitor because Serial.Print() doesn’t handle 64 bit numbers.
Thank you for the hard work .
Can you post your last edited code … ? ( with “better midnight rollover” handling ) .
( or maybe you’ve already edited your post…
Thanks again.
p.s.
Does the ESP32 handles deep sleep differently then esp8266 ?