Electrical – Extend ESP8266 12 F Deep Sleep Time

esp8266rtc

I would like to extend the maximum DeepSleep time of my ESP8266 12 F Module (running the Arduino ESP8266 Firmware) to 4 hours. I just found out that the maximum Deepsleep time is 71 minutes:

I found this short description on this Site:

One common way to extend the deep sleep time is to maintain a counter in NVM (i.e., Flash or RTC Memory), and increment the counter each time that the device wakes up. If it reaches a certain threshold, then do the work, otherwise go back to sleep.

So I'm trying to understand how this should work?
After Deep Sleep, the ESP8266 12 F module starts again at the Setup.
I know that:

bool rtcUserMemoryRead(uint32_t offset, uint32_t *data, size_t size);
bool rtcUserMemoryWrite(uint32_t offset, uint32_t *data, size_t size);

reads and writes stuff to the RTC Memory but I am not sure how to get a counter ready so that the Module goes into deep sleep 4*3600 seconds (so 4 Hours):

const int sleepTimeS = 3600;//1 Hour (3600 seconds)    
void loop() { 
do somehting;
ESP.deepSleep(sleepTimeS * 1000000,WAKE_RF_DEFAULT); 
}

How would I position everything so that the code runs on boot up and than goes into deep sleep for 4 hours?

DigitalNinjas post did it, I had to make 2 adjustments. Here's the version that worked for me:

// NVM Data
#define RTCMemOffset 10 // arbitrary location
#define MAGIC_NUMBER 55 // used to know if the memory is good and been written to 

    struct
    {
int wakeCount;
bool bFirstTime;
int magicNumber;
    } nvmData;

    nvmData sleepMemory;

    bool bDoneSleeping;

    void setup()
    {
/* Woke up and entered setup */
bDoneSleeping = false;

if(ESP.rtcUserMemoryRead((uint32_t)RTCMemOffset, (uint32_t*) &sleepMemory, sizeof(sleepMemory)))// EDIT: ESP. was missing
{
    if(sleepMemory.magicNumber != MAGIC_NUMBER) // memory got corrupt or this is the first time
    {
        sleepMemory.bFirstTime = true;
        sleepMemory.magicNumber = MAGIC_NUMBER;
        sleepMemory.wakeCount = 0;
        bDoneSleeping = true;// EDIT: Set bDoneSleeping to true so that the code runs on boot up
    }
    else
    {
        sleepMemory.wakeCount += 1; // incrememnt the sleep counter
        sleepMemory.bFirstTime = false;
    }

    if(sleepMemory.wakeCount >= 4) // reset the counter and do whatever else   you need to do since 4 hours have passed
    {
        sleepMemory.wakeCount = 0;
        bDoneSleeping = true;
    }   

   ESP.rtcUserMemoryWrite((uint32_t)RTCMemOffset, (uint32_t*) &sleepMemory, sizeof(sleepMemory)); // write the new values to memory // EDIT: ESP. was missing
}

if(bDoneSleeping)
{
     // Perform tasks
}
else
    // Go back to sleep
    }   

Best Answer

All they are suggesting is that you keep a counter in non-volatile memory so that you can keep track of how many times the ESP has woken up.

Sometimes you want to know if it's the very first time the application has run, so that you can do things you'd only want to do on the first boot. You can use a Boolean flag for this purpose. If you find out that you don't need that you can remove it from my example. Please note that I did not compile nor test this code, it could have errors and is meant purely as an example to get you started on a solution. Hope it helps :)

// NVM Data
#define RTCMemOffset 10 // arbitrary location
#define MAGIC_NUMBER 55 // used to know if the memory is good and been written to 

struct
{
    int wakeCount;
    bool bFirstTime;
    int magicNumber;
} nvmData;

nvmData sleepMemory;

bool bDoneSleeping;

void setup()
{
    /* Woke up and entered setup */
    bDoneSleeping = false;

    if(rtcUserMemoryRead((uint32_t)RTCMemOffset, (uint32_t*) &sleepMemory, sizeof(sleepMemory)))
    {
        if(sleepMemory.magicNumber != MAGIC_NUMBER) // memory got corrupt or this is the first time
        {
            sleepMemory.bFirstTime = true;
            sleepMemory.magicNumber = MAGIC_NUMBER;
            sleepMemory.wakeCount = 0;
        }
        else
        {
            sleepMemory.wakeCount += 1; // incrememnt the sleep counter
            sleepMemory.bFirstTime = false;
        }

        if(sleepMemory.wakeCount >= 4) // reset the counter and do whatever else you need to do since 4 hours have passed
        {
            sleepMemory.wakeCount = 0;
            bDoneSleeping = true;
        }   

        rtcUserMemoryWrite((uint32_t)RTCMemOffset, (uint32_t*) &sleepMemory, sizeof(sleepMemory)); // write the new values to memory
    }

    if(bDoneSleeping)
    {
         // Perform tasks
    }
    else
        // Go back to sleep
}