Preview build — page text is a draft awaiting human review. Code badges come from real compiles. The flasher is real but not yet hardware-tested; the Playground is still a preview.

TP4056 with Wemos D1 mini — Li-ion power and battery monitor

Run a Wemos D1 mini from a Li-ion cell with a TP4056 module: OUT+ to the 5V pin, a 100 kΩ resistor to A0 for battery voltage, and deep sleep in between.

Arduino C++Verified — core esp8266 3.1.2, 3 Nov 2026Compile-only

Community draft — report a mistake

A TP4056 module and an 18650 cell turn a D1 mini into a wireless sensor you can leave in the garden or on the terrace. The cell connects to the charger’s B+/B−, and the charger’s OUT+/OUT− power the D1 mini through its 5V pin and regulator. Charging happens through the TP4056’s own USB socket.

The D1 mini has a neat trick for checking the cell: its A0 divider is already on the board, so one extra 100 kΩ resistor from OUT+ to A0 is all it takes to read up to 4.2 V. The sketch reads the voltage, then deep-sleeps for five minutes (D0 jumpered to RST) to make the cell last.

Wiring

Wemos D1 miniOnly the pins used are shown · 3.3 V logic18650 Li-ion cell (protected)TP4056 Li-ion charger module (with DW01A protection)100 kΩ+−A0GND5VIN+ (not connected)IN- (not connected)B+B-OUT+OUT-
Also needed: 100 kΩ resistor, jumper wire from D0 to RST on the D1 mini (deep-sleep wake).
Every connection
Wemos D1 miniTP4056 Li-ion charger module (with DW01A protection)WireNotes
18650 Li-ion cell (protected) · +B+red
18650 Li-ion cell (protected) · −B-black
5VOUT+redThe cell (3.0–4.2 V) feeds the D1 mini’s 3.3 V regulator through the 5V pin. Never connect OUT+ to 3V3.
GNDOUT-black
A0OUT+orangeVia 100 kΩ — Adds to the board’s 220 kΩ / 100 kΩ divider: A0 then reads 0–4.2 V.

5 V input (4.5–5.5 V, USB) part, 3.3 V board. No logic pins. OUT+ is the raw cell voltage, 3.0–4.2 V: feed it to an ESP32 or Pico through a low-dropout 3.3 V regulator (HT7333, MCP1700) or the board’s VSYS/VIN pin, and to a 5 V board through a boost converter (MT3608). Never connect it straight to a 3.3 V pin.

Board quirks

  • The D1 mini’s A0 already has a 220 kΩ / 100 kΩ divider (about 3.2 V full scale). One extra 100 kΩ in series makes it (100 + 220 + 100) / 100 × 1.0 V = 4.2 V full scale — exactly a full Li-ion cell — with no other parts. It draws about 10 µA from the cell all the time.
  • OUT+ goes to the 5V pin so the cell passes through the board’s 3.3 V regulator. On 3V3 directly, a fully charged cell at 4.2 V would exceed the ESP8266’s 3.6 V limit.
  • The regulator needs some headroom: below about 3.4–3.5 V the 3.3 V rail starts to sag and Wi-Fi can brown out. The sketch stops waking up below 3.3 V; the TP4056’s protection chip cuts off much lower (about 2.5 V) to protect the cell itself.
  • Don’t plug the D1 mini’s USB in while the cell is connected unless you know your board has a diode between USB 5 V and the 5V pin. Without one, USB 5 V is pushed into OUT+ and the cell. Charge through the TP4056’s own USB socket.
  • Use a module with the protection chip (DW01 + 8205, labelled OUT+/OUT−) and a protected or branded cell. Keep the charger off flammable surfaces; Li-ion cells left charging in a hot room in May deserve respect.
  • Resistor tolerance (±5 %) shifts the reading. Measure the cell with a multimeter once and set CAL to correct it.

Code

tp4056-battery-d1mini.inoArduino C++Open in PlaygroundOpen in PlaygroundFlash
// Battery-powered Wemos D1 mini (ESP8266) from a TP4056 charger module + one Li-ion cell,
// measuring the cell voltage on A0 and deep-sleeping between readings.
// OUT+ → 5V (through the board's 3.3 V regulator), OUT- → GND,
// OUT+ → 100 kΩ → A0 (with the board's 220k/100k divider this makes A0 read 0-4.2 V),
// D0 → RST for deep-sleep wake. Never connect OUT+ to the 3V3 pin.
#include <ESP8266WiFi.h>

const float FULL_SCALE_V = 4.2;     // (100k + 220k + 100k) / 100k x 1.0 V
const float CAL = 1.00;             // multimeter reading / printed reading, to trim resistor tolerance
const float LOW_CUTOFF_V = 3.30;    // below this, stop waking up
const uint32_t SLEEP_SECONDS = 300;

float batteryVolts() {
  long sum = 0;
  for (int i = 0; i < 16; i++) {
    sum += analogRead(A0);
    delay(2);
  }
  return (sum / 16.0f) * FULL_SCALE_V / 1023.0f * CAL;
}

void setup() {
  WiFi.mode(WIFI_OFF);
  Serial.begin(115200);
  Serial.println();
  float v = batteryVolts();
  // Rough guide only: a Li-ion cell's voltage is not linear with charge.
  int pct = constrain((int)((v - 3.3f) / (4.2f - 3.3f) * 100), 0, 100);
  Serial.printf("Battery %.2f V (about %d %%)\n", v, pct);

  if (v < LOW_CUTOFF_V) {
    Serial.println("Battery low - sleeping until reset. Charge it via the TP4056's USB.");
    ESP.deepSleep(0);  // 0 = sleep until RST; draws only the sleep current
  }
  Serial.printf("Sleeping %lu s\n", (unsigned long)SLEEP_SECONDS);
  ESP.deepSleep(SLEEP_SECONDS * 1000000ULL);
}

void loop() {}

Expected serial output

Serial Monitor · 115200Output
Battery 3.97 V (about 74 %)
Sleeping 300 s

Common errors

Reading is about 30 % too high

The 100 kΩ series resistor is missing (or shorted), so the sketch’s 4.2 V scale is applied to a 3.2 V divider. Check the resistor between OUT+ and A0.

Board never wakes after the first reading

D0 must be wired to RST for deep sleep. Full fix.

Board resets as soon as Wi-Fi starts on battery

The cell is low and the regulator can’t supply the Wi-Fi current peaks. Charge the cell, and add a 470 µF capacitor between 3V3 and GND.

↑↓ to move · Enter to open