Nodemcu won't wake after "too long" deepsleep

Hello,

I just dive into arduino/nodemcu/esp8266/etc. :smiley:, so please let me know if there is anything wrong with how I made this post.

Here is my project and my issue:
Project: water tank level with ultrasonic sensor (US-100) + nodeMCU + battery powered. (My end goal is to have the nodeMCU sending a MQTT message), see code snippet at the end (please, also let me know if I can improve the code).

So far, everything is working as expected, device wakes up -> wifi connection -> mqtt connection -> get sensor value -> send mqtt message -> deep sleep.

My problem is: if SLEEP_DURATION is too long (> ~30min) the device won't wake up. If SLEEP_DURATION is less than 30 min, then everything is working fine. And I don't know what is wrong. (I have RST directly wired to D0).

Does anybody have any idea ?

#include <ESP8266WiFi.h>
#include <PubSubClient.h>

#define NB_TRYWIFI     5
#define SLEEP_DURATION 1000000 * 60 * 45

const char* wifi_ssid = "wifi_ssid";
const char* wifi_password = "wifi_pass";
IPAddress local_ip(10, 0, 5, 1);
IPAddress gateway(10, 0, 0, 1);
IPAddress subnet(255, 0, 0, 0);
IPAddress primary_dns(10, 0, 0, 1);

const char* mqtt_server = "10.0.1.2";
const int mqtt_port = 1883;
const char* mqtt_password = "mqtt_passw";
const char* mqtt_user = "mqtt_user";

const int US_100_ECHO = D2;
const int US_100_TRIG = D1;

WiFiClient espClient;
PubSubClient mqtt_client(espClient);

void sendMqttMessage(long distance, long analog){
  char json[40];
  if (mqttConnect()) {
    Serial.println("Sending mqtt message");
    sprintf(json, "{\"distance\": %d, \"analog\": %d}", distance, analog);
    mqtt_client.publish("WaterTankLevel/info", json);
  }
}

boolean mqttConnect() {
  if (!mqtt_client.connected()) {
    mqtt_client.setServer(mqtt_server, mqtt_port);
    if (mqtt_client.connect("WaterTankLevel", mqtt_user, mqtt_password)) {
      Serial.println("Connected to mqtt server");
      return mqtt_client.connected();
    }
    Serial.println("Connection to mqtt server failed!");
    return 0;
  }
  return 1;
}

boolean wifiConnect() {
  WiFi.config(local_ip, gateway, subnet, primary_dns);
  WiFi.begin(wifi_ssid, wifi_password);

  Serial.println("Connecting to WiFi");
  int _try = 0;
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
    _try++;
    if ( _try >= NB_TRYWIFI ) {
        Serial.println("Connection to wifi failed!");
        return 0;
    }
  }
  Serial.println("Connected to the WiFi");
  return 1;
}

void sleep() {
  Serial.println("Going to sleep");
  delay(1000);
  ESP.deepSleep(SLEEP_DURATION);
}

void serialSetup() {
  Serial.begin(9600);
  Serial.setTimeout(2000);

  while(!Serial) { }

  Serial.println("Waking up");

  pinMode(US_100_ECHO, INPUT);    //  The set EchoPin input mode.
  pinMode(US_100_TRIG, OUTPUT);   //  The set TrigPin output mode.
}

long readValue() {
  unsigned long len_mm = -1;
  unsigned long time_echo = 0;
  int count = 0;
  while (count < 10) {
    Serial.println("Read value from ultrasonic sensor");
    digitalWrite(US_100_TRIG, HIGH);                         // Send pulses begin by Trig / Pin
    delayMicroseconds(50);                               // Set the pulse width of 50us (> 10us)
    digitalWrite(US_100_TRIG, LOW);                          // The end of the pulse    
    time_echo = pulseIn(US_100_ECHO, HIGH);               // A pulse width calculating US-100 returned
    if((time_echo < 60000) && (time_echo > 1)) {   // Pulse effective range (1, 60000).
      len_mm = (time_echo * 34/100)/2;                   // Calculating the distance by a pulse width.   
      Serial.print("Present Distance is: ");              // Output to the serial port monitor 
      Serial.print(len_mm, DEC);                          // Output to the serial port monitor   
      Serial.println("mm");                 // Output to the serial port monitor 
      return len_mm;
    } else {
      delay(500);  
    }
    count++;
  }
  return -1;
}

void setup() {
  serialSetup();
  boolean wifi_ok = wifiConnect();
  
  if (wifi_ok) {
    long value = readValue();
    if (value > -1) {
      sendMqttMessage(value, analogRead(A0));
    } else {
      Serial.println("Cannot get sensor value");
    }
  }

  sleep();
}

void loop() {
}

Thanks for your help !

As a FYI, a simple reading of the ESP8266 API will show that

Well, this is also a second question I have, everybody is saying that max is ~71 minutes. But I can see deepsleep takes an uint64_t.

Anyway, for now, I'm only using ~30 minutes, so I should be safe.

Yes deepsleep takes a uint64_t but, if you were to look deeper into the code, the unit64_t is reduced.

You can use FAST_RTC to store a count that is retain between sleeps. In that ways the program can wake up after 30 minutes, increment the variable, check if the variable == 2. If ==2 then do the thing, otherwise go back to sleep.

I found the issue, it seems this is a programming error, now I'm defining SLEEP_DURATION like this: #define SLEEP_DURATION (120ULL* 60ULL* 1000000ULL), ULL for Unsigned Long Long in order to force SLEEP_DURATION to be an uint64_t.

@Idahowalker, actually I was able make sleeping the nodemcu for 2 hours, so it really seems it's an uint64_t under the hood.

1 Like

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.