ESP32 Bench
Boards: ESP32, S2, S3, C3, C6
Flash and monitor: Web Serial
← All projects

Battery deep-sleep sensor

Wake every five minutes, read a DS18B20 and the battery voltage, then go back to deep sleep. A boot counter survives in RTC memory.

Intermediate30 min115200 baud
Board
Fig. 1. Pins this project uses on the ESP32-DevKitC V4, 38 pin. USB connector at the bottom.

Wiring

FromTo boardNote
DS18B20 VDD (red)3V3
DS18B20 GND (black)GND
DS18B20 DATA (yellow)GPIO 44.7 kΩ pull-up from DATA to 3V3
Battery + through 100 kΩGPIO 35Divider top. Never connect the battery straight to a GPIO
100 kΩ from GPIO 35GNDDivider bottom: the pin sees half the battery voltage

Tested on this board

Not run on this board yet. Treat the wiring and code as a first draft.

Firmware, Arduino sketch for ESP32 Dev Module

#include <OneWire.h>
#include <DallasTemperature.h>

const int PROBE_PIN = 4;
const int BAT_PIN = 35;       // ADC1 pin at the middle of a 100k/100k divider
const uint64_t SLEEP_MINUTES = 5;

// RTC memory keeps these through deep sleep. Losing power or flashing clears them.
RTC_DATA_ATTR uint32_t boots = 0;
RTC_DATA_ATTR float lastC = NAN;

OneWire oneWire(PROBE_PIN);
DallasTemperature probes(&oneWire);

void setup() {
  Serial.begin(115200);
  boots++;
  bool timer = esp_sleep_get_wakeup_cause() == ESP_SLEEP_WAKEUP_TIMER;
  Serial.printf("boot %lu, woke by %s\n", (unsigned long)boots, timer ? "timer" : "power-on or reset");

  probes.begin();
  probes.requestTemperatures();  // about 750 ms at full resolution
  float c = probes.getTempCByIndex(0);
  if (c == DEVICE_DISCONNECTED_C) {
    Serial.println("no probe: check the data wire and the 4.7 kOhm pull-up");
  } else {
    Serial.printf("temp %.2f C, last time %.2f C\n", c, lastC);
    lastC = c;
  }

  uint32_t mv = 0;
  for (int i = 0; i < 8; i++) mv += analogReadMilliVolts(BAT_PIN);
  float battery = mv / 8.0f * 2.0f / 1000.0f;  // the divider halves the voltage
  Serial.printf("battery %.2f V\n", battery);

  Serial.printf("awake %lu ms, sleeping %llu min\n", millis(), (unsigned long long)SLEEP_MINUTES);
  Serial.flush();
  esp_sleep_enable_timer_wakeup(SLEEP_MINUTES * 60ULL * 1000000ULL);
  esp_deep_sleep_start();
}

void loop() {}  // never reached: every wake starts again at setup()

Parts

QuantityPartWhere to buy
1×ESP32 dev boardBuy at Amazon
1×DS18B20 waterproof probeBuy at Adafruit
1×4.7 kΩ resistor, pull-up for the probe data lineBuy at Amazon
2×100 kΩ resistors, battery dividerBuy at Adafruit
1×Single-cell Li-ion or LiPo battery with protection, and a way to get 3.3 V from it

Amazon buy links may include an Associates tag, and this site may earn a commission from qualifying Amazon purchases at no extra cost to you. Adafruit links are direct.

Libraries

OneWire, DallasTemperature

Load it

  1. In the Arduino IDE, install the esp32 board package and pick the board named above the sketch.
  2. Install the libraries listed above from the Library Manager.
  3. Paste the sketch, choose the board's port and upload. Hold BOOT if the upload stalls at Connecting.
  4. Close the IDE's serial monitor, then open the bench here to watch the output.

Field notes

  • A dev board is the wrong thing to run from a battery. Its voltage regulator, USB serial chip and power LED keep drawing current in deep sleep, typically milliamps rather than the microamps the chip itself needs. Measure your own board with a meter in series with the battery before trusting a battery-life estimate.
  • Espressif's datasheets put the chip alone at around 5 to 10 µA in deep sleep with the RTC timer running, depending on the chip. Getting near that needs a board built for low power, or a bare module with a low-quiescent regulator.
  • A full Li-ion cell is 4.2 V, too high for the 3V3 pin. Use a board with a battery connector, or a low-dropout 3.3 V regulator with a small quiescent current. The 5V pin's regulator on most dev boards drops too much voltage to run from one cell for long.
  • The 100k/100k divider draws about 20 µA from the battery all the time. For long battery life, switch it with a MOSFET or use larger resistors with a 100 nF capacitor from the pin to GND.
  • The battery pin must be an ADC1 pin: ADC2 cannot be read while Wi-Fi is on, which matters as soon as you add a Wi-Fi upload.
  • On the S3 and C3 with the native USB port, the serial port disappears during deep sleep and the bench loses the connection on every sleep. Use the UART USB port, or reconnect after each wake.

Not tested yet

  • Not tested on hardware yet, and no current draw has been measured. Compiles for every board listed with Arduino-ESP32 core 3.3.12.

Built it? Send a build report with your board and what the serial port printed. Working reports become the "Tested on this board" entries above.