Kode Dot
Power and battery
What charges a Kode Dot and what feeds it: the charger, the fuel gauge, the 5 V it can give out, what each part of the board costs, and the code to read the battery.
What it is
Three parts keep a Kode Dot running: a lithium cell, a charger and a fuel gauge. The BQ25896 is the charger and the power path: USB-C comes in, the battery charges, and the board runs from whichever is there. It also reports which source is feeding the device and how a charge is going. The CW2217 is the fuel gauge, on a shunt in series with the cell, so it sees everything the board draws and can tell you the level.
The charger also works backwards. With no USB attached it can boost the cell to 5 V on the expansion header, so a module plugged in there runs from the battery.
How it is connected
flowchart LR usb["USB-C, 5 V"] --> pmic["BQ25896"] bat["LiPo cell"] <--> pmic pmic --> sys["System rail"] pmic -. "boost, on request" .-> hdr["Header 5 V"] bat --> gauge["CW2217 on the shunt"] p4["ESP32-P4"] -- "I2C, 0x6B / 0x64" --> pmic p4 -- "I2C" --> gauge
Both chips answer on the shared I2C bus: the charger at 0x6B, the gauge at
0x64. The gauge is powered from the cell, so with no battery fitted it does
not answer at all. The bottom button is wired to the charger's power-on line,
which is how a fully-off Kode Dot starts with a long press.
Specifications
| Thing | Value |
|---|---|
| Charger | BQ25896, U13, at 0x6B. Power path from USB-C, charge control, ADC for VBUS, VSYS, battery and charge current |
| Fuel gauge | CW2217, U14, at 0x64, on a 10 mΩ shunt. Powered from the cell |
| Charge limit | 850 mA, set by the charger's ILIM pin, not by a register |
| 5 V out | The charger's boost onto the header's 5 V pins, about 5.00 V, on request. Fused at 2 A |
| Power on | Bottom button held 2 to 3 s, or USB-C plugged in |
| Power off | A firmware action. kodeOS's Turn off card puts the board in deep sleep, and BOT held about a second wakes it. Ship mode, only from the console verb ship_mode, opens the battery switch, and nothing is preserved (internals/power-and-sleep) |
| Kode driver | kode_battery_init, then kode_battery_read for volts, percent, charging and USB present |
| Cell | TBD: the capacity Kode ships |
| Validated | Kode-Dot-Val/12-POWER: charge, gauge, boost and a consumption profile on a board |
What the parts cost, measured one at a time on a validation board with no C5 fitted and no speaker. Use it to rank the parts against each other; do not add it up into a battery life.
| Part | Current |
|---|---|
| NFC field | About 109 mA, and a floor while it is up |
| Display, white, full brightness | About 76 mA |
| Status LED, all three at maximum | About 71 mA |
| Both cores at 100 % | About 46 mA |
| RFID carrier | About 17 mA |
| Infrared, averaged over a frame | About 12 mA |
| Display at 25 % brightness | About 3 mA |
| Wi-Fi and Bluetooth | TBD: not in the profile, no C5 on that board |
Gotchas
Apps that use it
On the marketplace, apps that put this part to work. Install one from
start/first-app and see it before you write a line.
Example code
Read the battery once a second and log it. On USB you see the charging flag set; unplug and the voltage starts to fall.
/*
* battery_log.c - 2026-09-18 - from Kode with love
*
* Logs the Kode Dot's battery once a second: volts, an estimated percent,
* whether it is charging and whether USB is present. Brings the board up,
* wakes the charger and the gauge through the Kode driver, then reads.
* With no battery fitted the init fails: the gauge runs from the cell.
*/
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "kode.h"
/* Board, then both chips, then one reading per second. */
void app_main(void)
{
ESP_ERROR_CHECK(kode_bsp_init());
ESP_ERROR_CHECK(kode_battery_init()); /* blocks about a third of a second */
while (1) {
kode_battery_t b;
if (kode_battery_read(&b) == ESP_OK) {
ESP_LOGI("battery", "%.2f V %3u %% %s %s", b.volts, b.percent,
b.charging ? "charging" : "not charging", b.usb_present ? "usb" : "battery");
}
vTaskDelay(pdMS_TO_TICKS(1000));
}
}Compiled on the date in the header against the kode component with
ESP-IDF v6.1. TBD: a run on a V1 board.
In the SDK
kdrv_power: the charger and the gauge inkode-sdk.