In advance, this is my first post so apologies for incorrect posting.
Hoping someone can help me figure this one out. I've been playing around with deep sleep on a ESP32-c3 with mixed success. My goal is to eventually use the board as dormant most of the time, wake up, connect to wifi and an MQTT server, collect and send data, and then go back to sleep. In case it matters, I am using running Arduino IDE 1.8.19 on a Linux Mint (Cinnamon).
As a universal constant, the serial monitor displays output until the board goes to sleep for the first time. After that it will change color (between white and grey) where the changes seemingly correspond to the wake sleep cycle but no other text is output. That being the case, I rigged up a simple LED and used it to successfully test the TimerWakeUp example implementation so I know that the board and its deep sleep function works correctly in a simple application. However, when I incorporate the same code into my MQTT client code, it successfully runs through the entire code once, goes to sleep, and never wakes up again (verified by both LED and MyMQTT which I use to monitor message traffic).
I have tried just about everything that I can think of with zero luck in solving the issue. Note that the MQTT client code works just fine when the deep sleep function is not present. In fact, if I comment out the deep sleep call and uncomment the code in the loop, it works just fine. I have tried with and without Serial.flush(), disconnecting MQTT client before sleep, disconnecting from the wifi both alone and in combination. In each case, there is no difference and I cannot get the board to wake from the first deep sleep short of using the reset button. The critical part is that I need the code to start an AP (AutoconnectAP in this case) to input MQTT particulars after which the MTTP broker IP address and port information are stored so the AP will not be started (this has been verified). I have also verified that the AutoconnectAP is not starting after the unit goes to sleep. Needless to say, I'm a bit lost.
I have attached my code and the serial output until the unit undergoes deep sleep for the first time.
Thanks, in advance, for any help!!
#include <FS.h> //this needs to be first, or it all crashes and burns...
#include <WiFiManager.h> //https://github.com/tzapu/WiFiManager
#include <PubSubClient.h>
#include <Adafruit_MPU6050.h> //added
#include <Adafruit_Sensor.h> //added
#include <Wire.h> //added
Adafruit_MPU6050 mpu; //added
#ifdef ESP32
#include <SPIFFS.h>
#endif
#include <ArduinoJson.h> //https://github.com/bblanchon/ArduinoJson
//from my file
WiFiClient espClient;
PubSubClient client(espClient);
unsigned long lastMsg = 0;
#define MSG_BUFFER_SIZE (50)
char msg[MSG_BUFFER_SIZE];
char msg2[MSG_BUFFER_SIZE];
int value = 0;
int settemp = 25;
int acttemp;
int MQTTconnect;
//end from my file
const int LED_PIN = 8;
RTC_DATA_ATTR int bootCount = 0;
#define uS_TO_S_FACTOR 1000000ULL /* Conversion factor for micro seconds to seconds */
#define TIME_TO_SLEEP 60000 /* Time ESP32 will go to sleep (in seconds) */
//#define WAKE_UP_TIME 30000
//define your default values here, if there are different values in config.json, they are overwritten.
char mqtt_server[40] = "xxx.xxx.xx.xx";
char mqtt_port[6] = "1883";
//char api_token[34];
//flag for saving data
bool shouldSaveConfig = true;//false;
//callback notifying us of the need to save config
void saveConfigCallback () {
Serial.println("Should save config");
shouldSaveConfig = true;
}
void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
MQTTconnect = 0;
Serial.print("Attempting MQTT connection...");
// Create a random client ID
String clientId = "ESP8266Client-";
clientId += String(random(0xffff), HEX);
// Attempt to connect
if (client.connect(clientId.c_str())) {
Serial.println("connected");
MQTTconnect = 1;
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}
void TestMPU6050() {
Serial.println("Adafruit MPU6050 test!");
// Try to initialize!
if (!mpu.begin()) {
Serial.println("Failed to find MPU6050 chip");
while (1) {
delay(10);
}
}
Serial.println("MPU6050 Found!");
mpu.setAccelerometerRange(MPU6050_RANGE_8_G);
Serial.print("Accelerometer range set to: ");
switch (mpu.getAccelerometerRange()) {
case MPU6050_RANGE_2_G:
Serial.println("+-2G");
break;
case MPU6050_RANGE_4_G:
Serial.println("+-4G");
break;
case MPU6050_RANGE_8_G:
Serial.println("+-8G");
break;
case MPU6050_RANGE_16_G:
Serial.println("+-16G");
break;
}
mpu.setGyroRange(MPU6050_RANGE_500_DEG);
Serial.print("Gyro range set to: ");
switch (mpu.getGyroRange()) {
case MPU6050_RANGE_250_DEG:
Serial.println("+- 250 deg/s");
break;
case MPU6050_RANGE_500_DEG:
Serial.println("+- 500 deg/s");
break;
case MPU6050_RANGE_1000_DEG:
Serial.println("+- 1000 deg/s");
break;
case MPU6050_RANGE_2000_DEG:
Serial.println("+- 2000 deg/s");
break;
}
mpu.setFilterBandwidth(MPU6050_BAND_21_HZ);
Serial.print("Filter bandwidth set to: ");
switch (mpu.getFilterBandwidth()) {
case MPU6050_BAND_260_HZ:
Serial.println("260 Hz");
break;
case MPU6050_BAND_184_HZ:
Serial.println("184 Hz");
break;
case MPU6050_BAND_94_HZ:
Serial.println("94 Hz");
break;
case MPU6050_BAND_44_HZ:
Serial.println("44 Hz");
break;
case MPU6050_BAND_21_HZ:
Serial.println("21 Hz");
break;
case MPU6050_BAND_10_HZ:
Serial.println("10 Hz");
break;
case MPU6050_BAND_5_HZ:
Serial.println("5 Hz");
break;
}
}
void SetupWiFi() {
// setup_wifi();
client.setServer(mqtt_server, 1883);
//client.setCallback(callback);
//clean FS, for testing
//SPIFFS.format();
//read configuration from FS json
Serial.println("mounting FS...");
if (SPIFFS.begin()) {
Serial.println("mounted file system");
if (SPIFFS.exists("/config.json")) {
//file exists, reading and loading
Serial.println("reading config file");
File configFile = SPIFFS.open("/config.json", "r");
if (configFile) {
Serial.println("opened config file");
size_t size = configFile.size();
// Allocate a buffer to store contents of the file.
std::unique_ptr<char[]> buf(new char[size]);
configFile.readBytes(buf.get(), size);
#if defined(ARDUINOJSON_VERSION_MAJOR) && ARDUINOJSON_VERSION_MAJOR >= 6
DynamicJsonDocument json(1024);
auto deserializeError = deserializeJson(json, buf.get());
serializeJson(json, Serial);
if ( ! deserializeError ) {
#else
DynamicJsonBuffer jsonBuffer;
JsonObject& json = jsonBuffer.parseObject(buf.get());
json.printTo(Serial);
if (json.success()) {
#endif
Serial.println("\nparsed json");
strcpy(mqtt_server, json["mqtt_server"]);
strcpy(mqtt_port, json["mqtt_port"]);
// strcpy(api_token, json["api_token"]);
} else {
Serial.println("failed to load json config");
}
configFile.close();
}
}
} else {
Serial.println("failed to mount FS");
}
//end read
// The extra parameters to be configured (can be either global or just in the setup)
// After connecting, parameter.getValue() will get you the configured value
// id/name placeholder/prompt default length
WiFiManagerParameter custom_mqtt_server("server", "mqtt server", mqtt_server, 40);
WiFiManagerParameter custom_mqtt_port("port", "mqtt port", mqtt_port, 6);
// WiFiManagerParameter custom_api_token("apikey", "API token", api_token, 32);
//WiFiManager
//Local intialization. Once its business is done, there is no need to keep it around
WiFiManager wifiManager;
//set config save notify callback
wifiManager.setSaveConfigCallback(saveConfigCallback);
//set static ip
//setSTAStaticIPConfig(IPAddress(xxx,xxx, xx, xxx), IPAddress(xxx,xxx,xx, x), IPAddress(255, 255, 255, 0));
//add all your parameters here
wifiManager.addParameter(&custom_mqtt_server);
wifiManager.addParameter(&custom_mqtt_port);
// wifiManager.addParameter(&custom_api_token);
//reset settings - for testing
/* using this part to force opening AutoConnectAP the first time through the code
* afterwards, the MQTT settings should be held in memory */
if (bootCount == 1) {
wifiManager.resetSettings(); //trying to comment here 2/27/26
bootCount++;
Serial.println("Boot number: " + String(bootCount));
}
//set minimum quality of signal so it ignores AP's under that quality
//defaults to 8%
//wifiManager.setMinimumSignalQuality();
//sets timeout until configuration portal gets turned off
//useful to make it all retry or go to sleep
//in seconds
//wifiManager.setTimeout(120);
//fetches ssid and pass and tries to connect
//if it does not connect it starts an access point with the specified name
//here "AutoConnectAP" and goes into a blocking loop awaiting configuration
if (!wifiManager.autoConnect("AutoConnectAP", "password")) {
Serial.println("failed to connect and hit timeout");
delay(3000);
//reset and try again, or maybe put it to deep sleep
ESP.restart();
delay(5000);
}
//if you get here you have connected to the WiFi
Serial.println("connected...yay :)");
//read updated parameters
strcpy(mqtt_server, custom_mqtt_server.getValue());
strcpy(mqtt_port, custom_mqtt_port.getValue());
// strcpy(api_token, custom_api_token.getValue());
Serial.println("The values in the file are: ");
Serial.println("\tmqtt_server : " + String(mqtt_server));
Serial.println("\tmqtt_port : " + String(mqtt_port));
//save the custom parameters to FS
if (shouldSaveConfig) {
Serial.println("saving config");
#if defined(ARDUINOJSON_VERSION_MAJOR) && ARDUINOJSON_VERSION_MAJOR >= 6
DynamicJsonDocument json(1024);
#else
DynamicJsonBuffer jsonBuffer;
JsonObject& json = jsonBuffer.createObject();
#endif
json["mqtt_server"] = mqtt_server;
json["mqtt_port"] = mqtt_port;
//json["api_token"] = api_token;
File configFile = SPIFFS.open("/config.json", "w");
if (!configFile) {
Serial.println("failed to open config file for writing");
}
#if defined(ARDUINOJSON_VERSION_MAJOR) && ARDUINOJSON_VERSION_MAJOR >= 6
serializeJson(json, Serial);
serializeJson(json, configFile);
#else
json.printTo(Serial);
json.printTo(configFile);
#endif
configFile.close();
//end save
}
Serial.println("local ip");
Serial.println(WiFi.localIP());
}
void SetupDeepSleep() {
esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
Serial.println("ESP32 set to sleep for " + String(TIME_TO_SLEEP/1000) + " Seconds");
/*
Next we decide what all peripherals to shut down/keep on
By default, ESP32 will automatically power down the peripherals
not needed by the wakeup source, but if you want to be a poweruser
this is for you. Read in detail at the API docs
http://esp-idf.readthedocs.io/en/latest/api-reference/system/deep_sleep.html
Left the line commented as an example of how to configure peripherals.
The line below turns off all RTC peripherals in deep sleep.
*/
//esp_deep_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_OFF);
//Serial.println("Configured all RTC Peripherals to be powered down in sleep");
}
void setup() {
//put your setup code here, to run once:
/* testing LED */
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, HIGH);
delay(1000);
digitalWrite(LED_PIN, LOW);
if (bootCount > 1); { //vestigial tail left over from testing
//reconnect();
}
Serial.begin(115200);
delay(10000); //Take some time to open up the Serial Monitor
//Increment boot number and print it every reboot
++bootCount;
Serial.println("Boot number: " + String(bootCount));
TestMPU6050();
SetupWiFi();
SetupDeepSleep();
//loop instructions
// if (!client.connected()) {
// reconnect();
// }
// client.loop();
/* Get new sensor events with the readings */
sensors_event_t a, g, temp;
mpu.getEvent(&a, &g, &temp);
/* Send data via MQTT */
int tilt_deg = (atan2(a.acceleration.y,a.acceleration.z)*(180/3.14));
Serial.print("Angle = ");
Serial.println(tilt_deg);
char acttemp[20];
sprintf(acttemp,"%d",tilt_deg);
snprintf (msg, MSG_BUFFER_SIZE, "%s", acttemp);
client.publish("ESP8266_TC/tilt",msg);
//
int tilt_t = temp.temperature; //this is in C
Serial.print("Temp = ");
Serial.println(tilt_t);
char acttemp_2[20];
sprintf(acttemp_2,"%d",tilt_t);
snprintf (msg, MSG_BUFFER_SIZE, "%s", acttemp_2);
client.publish("ESP8266_TC/tilt",msg);
/* deep sleep function */
Serial.println("Going to sleep now");
client.disconnect();
delay(1000);
WiFi.disconnect();
delay(1000);
esp_deep_sleep_start();
Serial.println("This will never be printed");
}
void loop() {
// if (!client.connected()) {
// reconnect();
// }
// client.loop();
//
// /* Get new sensor events with the readings */
// sensors_event_t a, g, temp;
// mpu.getEvent(&a, &g, &temp);
//
// int tilt_deg = (atan2(a.acceleration.y,a.acceleration.z)*(180/3.14));
// Serial.print("Angle = ");
// Serial.println(tilt_deg);
// char acttemp[20];
// sprintf(acttemp,"%d",tilt_deg);
// snprintf (msg, MSG_BUFFER_SIZE, "%s", acttemp);
// client.publish("ESP8266_TC/tilt",msg);
//
// int tilt_t = temp.temperature; //this is in C
// Serial.print("Temp = ");
// Serial.println(tilt_t);
// //int atemp = ;
// char acttemp_2[20];
// sprintf(acttemp_2,"%d",tilt_t);
// snprintf (msg, MSG_BUFFER_SIZE, "%s", acttemp_2);
// client.publish("ESP8266_TC/tilt",msg);
//
// //Serial.println("");
//// digitalWrite(LED_BUILTIN, LOW);
// delay(100);
//// digitalWrite(LED_BUILTIN, HIGH);
// delay(6000);
}
Serial output:
09:20:26.970 -> Boot number: 1
09:20:26.970 -> Adafruit MPU6050 test!
09:20:27.268 -> MPU6050 Found!
09:20:27.268 -> Accelerometer range set to: +-8G
09:20:27.268 -> Gyro range set to: +- 500 deg/s
09:20:27.268 -> Filter bandwidth set to: 21 Hz
09:20:27.268 -> mounting FS...
09:20:27.268 -> E (11639) SPIFFS: mount failed, -10025
09:20:27.301 -> failed to mount FS
09:20:27.301 -> *wm:resetSettings
09:20:27.865 -> *wm:SETTINGS ERASED
09:20:27.865 -> Boot number: 2
09:20:27.865 -> *wm:AutoConnect
09:20:27.898 -> *wm:No wifi saved, skipping
09:20:27.898 -> *wm:AutoConnect: FAILED for 16 ms
09:20:27.898 -> *wm:StartAP with SSID: AutoConnectAP
09:20:28.395 -> *wm:AP IP address: 192.168.4.1
09:20:28.395 -> *wm:Starting Web Portal
09:20:51.931 -> *wm:11 networks found
09:20:57.799 -> *wm:Connecting to NEW AP: TheDocs
09:20:57.832 -> *wm:connectTimeout not set, ESP waitForConnectResult...
09:20:59.921 -> *wm:Connect to new AP [SUCCESS]
09:20:59.921 -> *wm:Got IP Address:
09:20:59.921 -> *wm:xxx.xxx.xx.xx
09:20:59.921 -> Should save config
09:21:00.949 -> *wm:config portal exiting
09:21:00.949 -> connected...yay :)
09:21:00.949 -> The values in the file are:
09:21:00.949 -> mqtt_server : xxx.xxx.xx.xx
09:21:00.949 -> mqtt_port : 1883
09:21:00.949 -> saving config
09:21:00.949 -> failed to open config file for writing
09:21:00.949 -> {"mqtt_server":"xxx.xxx.xx.xx","mqtt_port":"1883"}local ip
09:21:00.949 -> xxx.xxx.xx.xx
09:21:00.949 -> ESP32 set to sleep for 60 Seconds
09:21:00.949 -> Angle = 122
09:21:00.949 -> Temp = 22
09:21:00.949 -> Going to sleep now

