From 13d58eecc15670ad6d970ec75419a9c714e8cdb8 Mon Sep 17 00:00:00 2001 From: Joerg Lehmann Date: Tue, 11 Feb 2020 16:57:31 +0100 Subject: [PATCH] add sleep mode code --- mini-beieli-node.ino | 192 ++++++++++++++++++++++++++++++++++++++++++- mini_beieli_node.h | 2 +- 2 files changed, 190 insertions(+), 4 deletions(-) diff --git a/mini-beieli-node.ino b/mini-beieli-node.ino index fbffcec..487398b 100644 --- a/mini-beieli-node.ino +++ b/mini-beieli-node.ino @@ -144,6 +144,11 @@ bool g_fPrintedSleeping = false; static osjob_t iterationJob; static osjob_t sendJob; +// the cycle time to use +unsigned gTxCycle; +// remaining before we reset to default +unsigned gTxCycleCount; + void setup(void) { gCatena.begin(); @@ -304,7 +309,7 @@ bool setup_scales(void) // we wait 400ms (settling time according HX711 datasheet @ 10 SPS delay(400); - + if (config_data.debug_level > 0) { gCatena.SafePrintf("%010d - setup_scale done\n", millis()); } @@ -341,7 +346,7 @@ void setup_uplink(void) gCatena.SafePrintf("%010d - setup_uplink\n", millis()); } - LMIC_setClockError(1*65536/100); + LMIC_setClockError(1 * 65536 / 100); /* figure out when to reboot */ gRebootMs = (CATCFG_T_REBOOT + os_getRndU2() - 32768) * 1000; @@ -894,6 +899,8 @@ static void txNotProvisionedCb( static void settleDoneCb( osjob_t* pSendJob) { + const bool fDeepSleep = checkDeepSleep(); + if (config_data.debug_level > 0) { gCatena.SafePrintf("%010d - settleDoneCb\n", millis()); } @@ -914,7 +921,186 @@ static void settleDoneCb( NVIC_SystemReset(); } - sleepDoneCb(pSendJob); + if (! g_fPrintedSleeping) + doSleepAlert(fDeepSleep); + + /* count what we're up to */ + updateSleepCounters(); + + if (fDeepSleep) + doDeepSleep(pSendJob); + else + doLightSleep(pSendJob); +} + +bool checkDeepSleep(void) +{ + bool const fDeepSleepTest = gCatena.GetOperatingFlags() & + static_cast(gCatena.OPERATING_FLAGS::fDeepSleepTest); + bool fDeepSleep; + + if (fDeepSleepTest) + { + fDeepSleep = true; + } +#ifdef USBCON + else if (Serial.dtr()) + { + fDeepSleep = false; + } +#endif + else if (gCatena.GetOperatingFlags() & + static_cast(gCatena.OPERATING_FLAGS::fDisableDeepSleep)) + { + fDeepSleep = false; + } + else if ((gCatena.GetOperatingFlags() & + static_cast(gCatena.OPERATING_FLAGS::fUnattended)) != 0) + { + fDeepSleep = true; + } + else + { + fDeepSleep = false; + } + + return fDeepSleep; +} + +void doSleepAlert(const bool fDeepSleep) +{ + g_fPrintedSleeping = true; + + if (fDeepSleep) + { + bool const fDeepSleepTest = gCatena.GetOperatingFlags() & + static_cast(gCatena.OPERATING_FLAGS::fDeepSleepTest); + const uint32_t deepSleepDelay = fDeepSleepTest ? 10 : 30; + if (config_data.debug_level > 2) { + gCatena.SafePrintf("using deep sleep in %u secs" +#ifdef USBCON + " (USB will disconnect while asleep)" +#endif + ": ", + deepSleepDelay + ); + + } + // sleep and print + if (config_data.debug_level > 2) { + gLed.Set(LedPattern::TwoShort); + } + + for (auto n = deepSleepDelay; n > 0; --n) + { + uint32_t tNow = millis(); + + while (uint32_t(millis() - tNow) < 1000) + { + gCatena.poll(); + yield(); + } + if (config_data.debug_level > 2) { + gCatena.SafePrintf("."); + } + } + if (config_data.debug_level > 2) { + gCatena.SafePrintf("\nStarting deep sleep.\n"); + } + uint32_t tNow = millis(); + while (uint32_t(millis() - tNow) < 100) + { + gCatena.poll(); + yield(); + } + } + else if (config_data.debug_level > 2) { + gCatena.SafePrintf("using light sleep\n"); + } +} + +void updateSleepCounters(void) +{ + // update the sleep parameters + if (gTxCycleCount > 1) + { + // values greater than one are decremented and ultimately reset to default. + --gTxCycleCount; + } + else if (gTxCycleCount == 1) + { + // it's now one (otherwise we couldn't be here.) + if (config_data.debug_level > 2) { + gCatena.SafePrintf("resetting tx cycle to default: %u\n", CATCFG_T_CYCLE); + } + + gTxCycleCount = 0; + gTxCycle = CATCFG_T_CYCLE; + } + else + { + // it's zero. Leave it alone. + } +} + +void doDeepSleep(osjob_t *pJob) +{ + bool const fDeepSleepTest = gCatena.GetOperatingFlags() & + static_cast(gCatena.OPERATING_FLAGS::fDeepSleepTest); + uint32_t const sleepInterval = CATCFG_GetInterval( + fDeepSleepTest ? CATCFG_T_CYCLE_TEST : gTxCycle + ); + + /* ok... now it's time for a deep sleep */ + gLed.Set(LedPattern::Off); + deepSleepPrepare(); + + /* sleep */ + gCatena.Sleep(sleepInterval); + + /* recover from sleep */ + deepSleepRecovery(); + + /* and now... we're awake again. trigger another measurement */ + sleepDoneCb(pJob); +} + +void deepSleepPrepare(void) +{ + Serial.end(); + Wire.end(); + SPI.end(); + if (fFlash) + gSPI2.end(); +} + +void deepSleepRecovery(void) +{ + Serial.begin(); + Wire.begin(); + SPI.begin(); + if (fFlash) + gSPI2.begin(); +} + +void doLightSleep(osjob_t *pJob) +{ + uint32_t interval = sec2osticks(CATCFG_GetInterval(gTxCycle)); + + gLed.Set(LedPattern::Sleeping); + + if (gCatena.GetOperatingFlags() & + static_cast(gCatena.OPERATING_FLAGS::fQuickLightSleep)) + { + interval = 1; + } + + gLed.Set(LedPattern::Sleeping); + os_setTimedCallback( + &iterationJob, + os_getTime() + interval, + sleepDoneCb + ); } static void sleepDoneCb(osjob_t* pJob) diff --git a/mini_beieli_node.h b/mini_beieli_node.h index fbf60ce..2393d90 100644 --- a/mini_beieli_node.h +++ b/mini_beieli_node.h @@ -56,7 +56,7 @@ enum { | \****************************************************************************/ -static const int32_t fwVersion = 20200210; +static const int32_t fwVersion = 20200211; static const byte INIT_PACKAGE_INTERVAL = 100; // send an init package every 100 packages; static const byte MAX_VALUES_TO_SEND = 8;