# 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

```mermaid
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
```

*Charger and gauge on the I2C bus; the charger feeds the board and, on request, the header*

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

> **WARNING**
>
> **The gauge does not answer.** There is no battery. It runs from the cell,
> not from USB, so a Kode Dot on a cable alone has a charger and no gauge.

> **WARNING**
>
> **The charge current you set went back to the default.** The charger's
> watchdog resets its registers every 40 s unless you feed it. Set the current,
> and keep the watchdog fed or turn it off.

> **NOTE**
>
> **Brightness is the cheapest battery you have.** A white screen at full
> brightness costs about 76 mA; at a quarter it costs about 3 mA, and black is
> free on an AMOLED. A dark interface saves more than any other change.

## 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.

- https://apps.kode.diy/app/fe5d0c44-1e50-419a-803e-653d826264e2

## 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.

```c
/*
 * 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`](https://github.com/kodediy/kode-sdk/tree/main/components/kdrv/kdrv_power): the charger and the gauge in `kode-sdk`.
