I'm trying to create a battery & solar-powered ESP32 for future use with sensors. It connects to Wifi, MQTT, publishes some readings and status messages and goes back to sleep. From time to time (it can happen after a few sleep cycles and sometimes after a few hundred cycles), I get 2 unexplained behaviours: 1) fails to connect to MQTT at boot, 2) fails to sleep.
Sometimes those behaviours happen simultaneously.
Is there a known issue with deepsleep
and MQTT (using PubSubClient
)? Most deepsleep examples I see online, all code is outside the loop()
section - is it mandatory to be like that?
I don't share code, since it is more a general question.
Guy
EDIT1
most of
callback
was commented out, leaving only printing the incoming message.LED was attached to a GPIO, generating a blink on
loop()
- when sleep succeeds - it goes off, when it fails, it stays on. This test shows that when this "error" happens, code actually stop running, but does not enter deep sleep (power-wise).
2 Answers 2
Is there a known issue with deepsleep and MQTT ?
No. There may be a specific problem with the specific library you are using, but the concept of there being an issue with MQTT in general is nonsense.
Most deepsleep example I see online, all code is outside loop()section - is it mandatory to be like that ?
No, that's just being structured and tidy with your code. Whether code is in loop or in functions that are called by loop makes no difference. It can be a lot easier to manage your code if you structure it in functions rather than dumping it all in loop.
-
I don't know about the nonsense, but s similar question was asked in github.com/knolleary/pubsubclient/issues/634 ( same behviour, but case is still open... )guyd– guyd2020年07月11日 16:02:40 +00:00Commented Jul 11, 2020 at 16:02
-
MQTT is just a protocol. The concept of it having a problem makes no logical sense. If there is a problem that is related to using MQTT then it's a problem with pubsubclient not MQTT.Majenko– Majenko2020年07月11日 16:04:46 +00:00Commented Jul 11, 2020 at 16:04
-
OK, I agree, I ment to
pubsubClient
guyd– guyd2020年07月11日 16:15:55 +00:00Commented Jul 11, 2020 at 16:15
The problem with calling ESP.deepSleep(xx)
inside loop()
is that watchdog is already activated there, and then a reset occurs during the sleep state.
To fix this, I used the software's own ESP.restart()
reset technique after having written a signature to a "not init" variable, as follows:
Variable area:
uint16_t SleepSign __attribute__((section(".noinit"))); // Hot reset / deep sleep signature.
Then, at the beginning of setup()
we write the code that tests the content of that uninitialized variable, and if it contains the signature, ESP.deepSleep(xx)
is called. In my case I use ESP.deepSleep(0)
because I intend for the device to reboot only on a new boot:
void setup()
{
if (SleepSign == 0xdd11) ESP.deepSleep(0);
Rest of the initialization:
...
Inside loop():
...
if ((millis() - timeconnect) > 300*1000) {
SleepSign = 0xdd11; // deep sleep at restart
ESP.restart();
}
...
This system is tested and works correctly, reducing consumption to the minimum specified by espressif. I previously tried to block watch before exiting setup()
, but it didn't work, of course:
*((volatile uint32_t*) 0x60000900) &= ~(1); // Hardware WDT OFF
Obviously, if we are interested in using a timed deepSleep, and have the device do anything before going back to sleep, we can assign several values to the SleepSign variable to control the restart, also resetting its value before calling ESP.deepSleep(0):
void setup()
{
if (SleepSign == 0xdd11) {
SleepSign = 0xffff;
ESP.deepSleep(xx);
}
Rest of the initialization:
...
The only drawback I find is that the esp will perform a reset before going to sleep, but I don't think that matters much.
if (a+1 == 2) {
, not by commenting the line, because commenting the line would cause the compiler to generate different code ........ do the same with the sleep codea+1
should create a logic state that wont enter theif
loop to voidpublish
? and the other part to theesp_deep_sleep_start();
? I dont understand why so... by the way- see edit 1///
to prevent the MQTT publish command from running, then the compiler will produce different code that may not have the sleep problem .... using an if statement makes sure that the compiler does not skip un-executed code ..... do the same kind of a test for the sleep code to see if it is affecting the MQTT code ...... do the tests separatelypublish
workaround did not work, even not when I increased MQTT_MAX_PACKET_SIZE to 512 to be sureESP.restart()
every 30 sec was added toloop()