Hello, hoping this doesn’t overlap the other topics I’ve read in here, I think it’s different enough that it warrants it’s own.
I’ve got a heap of esp32c3 boards (10 or so) with temperature sensors connected running on a 3.7v battery and sending readings every 15 minutes to an mqtt broker through wifi (using antennas on them and reporting an rssi of -45) over the network, If I power them through usb they don’t seem to skip a beat but on battery they don’t always wake up (or so it seems), i have the mqtt broker dumping the data to a sql database and i can see every step of the way that it appears to work the same as when running on USB power (other than below).
The strange thing is randomly they’ll “miss a check in” but then report as expected at the next 15 minute interval (give or take a minute or two).
Say out of 3 of them, number 1, 2 and 3 will tick away quite happy for maybe 8 15 minute intervals then number 1 will disappear on the 9th but 2 and 3 will report fine (within a minute or so as they’re not all started simultaneously).
Then on the 10th or 11th interval 1 will appear again along with 2 and 3 or maybe just 1 and 2 etc.
Sorry this is rambling but I’m hoping the detail will explain the situation.
Sometimes they come back together and behave fine, sometimes it falls apart and they’re doing random things but usually within themselves they’ll get back on track, it’s pretty off and on.
Any suggestions? I wondered if it was my network that was the problem as there’s a lot going on but the difference seems to be if it’s plugged in it’s fine if it’s on battery it’s not.
I’ve read the other topics mentioning serial and a few others but they don’t seem to be my issue.
Have i just picked the worst board to try this with or is the issue inherent with deep sleep and I won’t be able to get this how i want it?
Have included sketch below:
#include <WiFi.h>
#include <PubSubClient.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <time.h> // For time and NTP
// Wi-Fi credentials
const char* ssid = "Network";
const char* password = "Password";
// MQTT broker details
const char* mqtt_server = "192.168.14.200";
const char* mqtt_user = "User";
const char* mqtt_password = "Pass";
// Device hostname
const char* hostname = "C3-Fridge-NS-New1";
// NTP server and timezone settings
const char* ntpServer = "pool.ntp.org";
const long gmtOffset_sec = 0; // GMT offset in seconds (e.g., 3600 for GMT+1)
const int daylightOffset_sec = 0; // Daylight savings offset in seconds
// Pin definitions
#define DS18B20_PIN 6 // GPIO6 for DS18B20
#define BATTERY_PIN 4 // GPIO4 (D4) for ADC battery monitoring
// Voltage divider resistors
#define DIVIDER_RATIO 2.0 // 1:2 ratio with two 220kΩ resistors
// Battery voltage limits
#define BATTERY_MAX 4.2
#define BATTERY_MIN 3.0
// Deep sleep time in microseconds (15 minutes)
#define SLEEP_TIME 60000000
// DS18B20 setup
OneWire oneWire(DS18B20_PIN);
DallasTemperature sensors(&oneWire);
// Wi-Fi and MQTT clients
WiFiClient espClient;
PubSubClient client(espClient);
// Function to read battery voltage
float readBatteryVoltage() {
uint32_t Vbatt = 0;
// Average 16 samples for better stability
for (int i = 0; i < 16; i++) {
Vbatt += analogReadMilliVolts(BATTERY_PIN); // Read ADC value in mV
}
// Convert mV to V and scale by divider ratio
float Vbattf = (Vbatt / 16) * DIVIDER_RATIO / 1000.0;
return Vbattf;
}
// Function to calculate battery percentage
int calculateBatteryPercentage(float voltage) {
float percentage = ((voltage - BATTERY_MIN) / (BATTERY_MAX - BATTERY_MIN)) * 100.0;
if (percentage > 100) percentage = 100;
if (percentage < 0) percentage = 0;
return (int)percentage;
}
// Function to get formatted time as a string
String getFormattedTime() {
struct tm timeinfo;
if (!getLocalTime(&timeinfo)) {
return "N/A"; // If time not available
}
char timeStr[20];
strftime(timeStr, sizeof(timeStr), "%Y-%m-%d %H:%M:%S", &timeinfo);
return String(timeStr);
}
// Function to connect to Wi-Fi with timeout
void connectToWiFi() {
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
WiFi.setHostname(hostname);
int retryCount = 0;
while (WiFi.status() != WL_CONNECTED && retryCount < 30) { // Retry up to 30 times
delay(1000 * (retryCount + 1)); // Exponential backoff
retryCount++;
}
if (WiFi.status() != WL_CONNECTED) {
ESP.restart(); // Restart the device if Wi-Fi fails
}
// Configure NTP
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
}
// Function to connect to MQTT broker
void connectToMQTT() {
client.setKeepAlive(30); // Set keep-alive to 30 seconds
client.setServer(mqtt_server, 1883); // Reinitialize MQTT server
while (!client.connected()) {
if (client.connect(hostname, mqtt_user, mqtt_password)) {
// Connected
} else {
delay(5000);
}
}
}
void setup() {
sensors.begin(); // Start DS18B20
connectToWiFi();
connectToMQTT();
// Get MAC address, Wi-Fi signal strength (RSSI), and current time
String macAddress = WiFi.macAddress();
int wifiRSSI = WiFi.RSSI();
String currentTime = getFormattedTime();
// Read temperature
sensors.requestTemperatures();
float temperature = sensors.getTempCByIndex(0);
if (temperature == DEVICE_DISCONNECTED_C) {
temperature = -127; // Error value
}
// Read battery voltage
float batteryVoltage = readBatteryVoltage();
// Calculate battery percentage
int batteryPercentage = calculateBatteryPercentage(batteryVoltage);
// Publish data with MAC address, RSSI, and time
char payload[250];
snprintf(payload, sizeof(payload),
"{\"hostname\":\"%s\",\"mac\":\"%s\",\"rssi\":%d,\"time\":\"%s\",\"temp\":%.2f,\"batt\":%d}",
hostname, macAddress.c_str(), wifiRSSI, currentTime.c_str(), temperature, batteryPercentage);
bool publishSuccess = false;
for (int i = 0; i < 3; i++) { // Retry up to 3 times
if (client.publish("fridge/temperature", (uint8_t*)payload, strlen(payload), false)) {
publishSuccess = true;
break;
}
delay(5000); // Wait before retrying
}
if (!publishSuccess) {
ESP.restart(); // Restart only after multiple failures
}
// Disconnect Wi-Fi to save power
client.disconnect();
WiFi.disconnect(true);
WiFi.mode(WIFI_OFF);
// Prepare for deep sleep
esp_sleep_enable_timer_wakeup(SLEEP_TIME);
delay(1000); // Ensure clean exit
esp_deep_sleep_start();
}
void loop() {
unsigned long start = millis();
while (!client.loop() && (millis() - start) < 5000) {
delay(100); // Retry MQTT loop for up to 5 seconds
}
// Not used
}
Meant to add sorry, from the mqtt broker, whenever one of them “misses a check in” i see this in the logs:
2025-01-21T17:05:41: New connection from 192.168.14.112:64962 on port 1883.
2025-01-21T17:05:41: New client connected from 192.168.14.112:64962 as C3-Fridge-NS3 (p2, c1, k30, u'fridge1').
2025-01-21T17:05:41: No will message specified.
2025-01-21T17:05:41: Sending CONNACK to C3-Fridge-NS3 (0, 0)
2025-01-21T17:06:16: Received PINGREQ from auto-255039FA-00B6-2D14-9631-043E8A7018AE
2025-01-21T17:06:16: Sending PINGRESP to auto-255039FA-00B6-2D14-9631-043E8A7018AE
2025-01-21T17:06:31: Client C3-Fridge-NS3 has exceeded timeout, disconnecting.
it varies by name and time but everytime it’s “exceeded timeout” and gets disconnected.
Wi-Fi transmission is power-intensive, causing sudden voltage drops.
ESP32-C3 boards typically need a stable supply of at least 3.3V. If the battery voltage drops below this (even momentarily), it can cause instability or a failure to wake. Place a low ESR capacitor (e.g., 470 µF or 1000 µF) across the ESP32 power rails (VCC and GND) to smooth out power fluctuations during wake and transmission. For more info about ESP32 power saving modes, you can see here: ESP32 Low Power Modes - The Engineering Projects
Hi, thanks for this info, I’ve found some on Amazon for next day delivery : Sourcing map Aluminum Radial Electrolytic Capacitor Low ESR Green with 1000UF 25V 105 Celsius Life 3000H 10 x 20 mm High Ripple Current,Low Impedance 10pcs. Would this be correct?
as they said you are having brown-out issues… it is very difficult to get a 3.7v lipo to source 3.3v for a microcontroller because as A “3.7v lipo” battery should typically have a low voltage cutoff around 3.0 volts per cell; meaning when the voltage drops below 3.0 volts, the device should automatically stop drawing power to prevent further damage to the battery.
so when the battery is effectivly dead it is at 3.0 volts… so for example a dead battery may show 3.7v static… the device may wake and transmit… causing the voltage to drop to 3.3v as the battery has no capacity to give… the voltage may drop to 3.0v and the chip may brownout or a protective circuit may engage… then the system reboots… and the no load voltage of the battery rebounds to 3.7 and the cycle repeats… so the basic problem is your battery is dead and needs charging.
also if you need this power you should go to 2 or 3 18650 in parallel or something like a boost converter… but in no way can power be taken from a dead batttery
Well just to really throw a spanner in the works last night I had 2 on test but powered f room usb and they started the same behaviour.
They’re running over a VPN though so I’m hoping the network was the issue. Capacitors arriving today so will put a few together and see what happens. Thanks folks
Hi folks, I have my capacitors now, just hoping to check my placement is ok?
I have 2 x 220k resistors connected to gpio from a split in the battery leads going to the bat connectors on the underside of the board for reading the battery level, I’ve connected positive for the capacitor to the positive resistor and negative to the negative resistor. Is this correct or do I need to have it directly at the battery or board end?
I’m not sure about your description, but it should be the plus side of the battery to one of the resistors, the other end of the resistor goes to both the gpio and the other resistor. The other end of that resistor should go to ground and the battery. The capacitor goes between ground and the plus side of the battery, but as gnd and plus are connected to the resistors, you could as well connect the capacitor to the resistors, but not to the part that is connected to the gpio pin.
Hi, thanks for helping, does this terrible drawing explain it better? Is this ok or do i need to have the positive going into the + on cap and the negative of cap to positive resistor?
that drawing is correct, the plus of the capacitor should be to the plus of the battery. Alternatively you could disconnect it from the battery and connect it to the 3.3V line. The result is about the same, when you suddenly draw a lot of power, it takes longer for the voltage to drop.
If that helps with your situation, I don’t know. I don’t think it will, but someone else thinks the capacitor will help.
To make sure it isn’t waking up, add a counter, check that it works and counts up every 15 minutes, then disconnect the usb for a couple of hours and reconnect to read the counter. If the counter shows that it did increase every 15 minutes, it isn’t the wake up that isn’t working.
It’s definitely waking up on time (I probably shouldn’t say definitely), I checked the broker logs though and the times that it isn’t working it gets initial connection but timesout and the broker disconnects it
Will report back tomorrow on capacitor difference, have one with a capacitor attached and a other with a capacitor attached but also it has 2 batteries in parallel.
I might be ahead of myself tbh, if I don’t get my result from either I’ll need to scale it back to something basic like just the counter you suggested or remove the temp sensor and just have a test message se t every 15 mins, try and figure out where the failure is in the process.
Is it possible? I read a lot of forums with these boards, deep sleep and running from battery but last night I had the same issue while they were connected to usb power.
Soooooo. I currently have 2 running , 1 has 3 batteries in parallel and a 1000uf capacitor the other has 1 battery and 2 capacitors (was originally 1 with 2 batteries and 1 cap and the other with 1 battery and 1 cap) still the same, if anything they might be worse.
Couple of screenshots of what’s coming in (not sure how interested I can expect you to be if I’m honest) if anyone could help me think of where to start narrowing this down I’d really appreciate it.
Currently they connect to WiFi at my house over VPN to the broker. I suppose there’s still the possibility that the VPN/internet is the issue but I just find it unlikely as I don’t have much confidence in my electronics ability. I’ll move them down to the local site tomorrow and see if performance is any better
So If I may , from watching this thread. (good thread , BTW)
Can you work with just one unit? Change the code to send whenever the Delta of the Change in temp is significant enough to transmit , and sleep otherwise?
Try updating a local BLE central with a notify after many attempts at the gateway, I think it’s a network issue.
I would use a USB C power brick also to verify battery or not, sounds like you didn’t finish testing the comms part fully? No mesh or backup so that’s a problem. Get it working first then worry about SLEEP and Battery efficiencies.
Are they all trying to connect at the same time? What is the GOAL in the END for this , it seems a worthy basic project. Tell us more… You may just need better antennas, You got a picture of these Aperatices?
HTH
GL PJ
What is the topology here? Master slave , Star, Mesh ? All wifi?
What MQTT are you using (device and software) I see SubPubClient