Battery Power - BLEShark Nano endurance

ESP32 Power Consumption: How BLEShark Nano Lasts on Battery

The BLEShark Nano runs on a 500mAh battery. Depending on what you're doing, that battery can last anywhere from roughly an hour to several hours. The difference comes down to how much current the ESP32-C3 and its peripherals are drawing at any moment. WiFi transmission, BLE advertising, IR blasting, and deep sleep all have very different current profiles. This article breaks down the numbers and explains how the firmware manages power to extend useful battery life.

Table of Contents

ESP32-C3 Power Modes

The ESP32-C3 has several well-defined power modes. Understanding them is the foundation for understanding battery life:

Active mode: CPU running at full clock (160MHz on C3), WiFi or BLE radio active. This is the default when the device is doing something. Total chip current (not including peripherals) ranges from 20mA at idle to over 300mA during WiFi TX burst.

Modem sleep: CPU running, but the WiFi/BLE modem powers down between scheduled receive windows. The CPU can still execute code. Modem sleep is used during DTIM-based WiFi power saving (the station checks for beacons every N intervals and sleeps the modem between them). Not directly useful for the BLEShark's scanning use case, but relevant for maintaining a WiFi connection efficiently.

Light sleep: CPU pauses, but SRAM is retained. The device wakes on GPIO, timer, or wireless events. Wake-up latency is around 130 microseconds. Current drops to around 800uA for the chip alone. Peripheral current (OLED, voltage regulators) adds to this.

Deep sleep: CPU off, SRAM mostly powered down (only RTC memory retained). Only the RTC controller, RTC memory, and ULP (Ultra-Low-Power) co-processor remain active. Current drops to 5-10 microamps. Wake-up requires a full chip restart (GPIO interrupt or timer), taking around 30ms.

The BLEShark's practical operating range is between active mode (doing useful work) and light sleep (display off, waiting for button press). Deep sleep is used when the battery is critically low and the device wants to preserve remaining charge.

stateDiagram-v2
    [*] --> Active: Power on

    state Active {
        [*] --> WiFiScan: WiFi scanning
        WiFiScan --> WiFiTX: Transmit
(deauth, beacon) WiFiTX --> WiFiScan: TX complete WiFiScan --> BLEScan: Switch to BLE BLEScan --> BLETX: BLE spam/advertise BLETX --> BLEScan: TX complete BLEScan --> WiFiScan: Switch to WiFi } state "Current Draw" as DRAW { [*] --> D1: WiFi RX: ~50-70mA D1 --> D2: WiFi TX: ~130-160mA D2 --> D3: BLE RX: ~20-30mA D3 --> D4: BLE TX: ~50-70mA D4 --> D5: IR blast: ~200mA peak D5 --> D6: OLED on: ~15-20mA } Active --> LightSleep: Idle timeout LightSleep --> Active: Timer/GPIO wake Active --> DeepSleep: User request DeepSleep --> Active: Reset/GPIO state LightSleep { [*] --> LS: ~0.8mA
RAM retained
WiFi state saved } state DeepSleep { [*] --> DS: ~5-10uA
Only RTC memory
Full reboot needed }

ESP32-C3 power state machine on BLEShark Nano - active mode current varies by radio activity, with light sleep preserving state and deep sleep minimizing drain to microamps.

WiFi Current Draw

WiFi has the highest current demand of any feature on the device. The numbers vary significantly by operation:

WiFi scan (passive): The radio listens on each channel for beacon frames and probe responses. The chip draws around 100-120mA during passive scanning. This is listen-only - no transmission, just receiving.

WiFi scan (active): Includes sending probe request frames to elicit probe responses from APs. The TX burst when sending a probe request spikes to 200-240mA for a few milliseconds, then returns to ~110mA for the dwell period. Average current during an active scan cycle is around 130mA.

WiFi transmit (raw frame injection): Deauth attacks, AP spam (beacon injection), and handshake capture all require raw frame injection. Sending management frames at high rate (hundreds per second) puts the radio in near-continuous TX. This is the highest sustained current draw: 200-240mA continuously.

WiFi AP mode (captive portal, file portal): Hosting an access point means the radio is continuously active, sending beacons every 100ms and handling client associations. Current in AP mode is around 100-130mA baseline, with TX spikes when clients are actively communicating.

WiFi connected (idle): If connected to a network but not actively transmitting, the modem can sleep between DTIM intervals. Current drops to 15-30mA depending on DTIM interval. The BLEShark uses this mode during OTA update download when connected to an update server - it's not sending anything, just receiving.

At 200mA average during intensive WiFi operations, the 500mAh battery gives you about 2.5 hours of continuous deauth or AP spam. In practice, you're not running these continuously for 2.5 hours, so battery life during normal mixed-use sessions is longer.

BLE Current Draw

BLE is significantly more power-efficient than WiFi. The numbers:

BLE advertising (BLESpam): Sending advertisement packets on the three BLE advertising channels (37, 38, 39) at a typical advertising interval. Each advertisement is a brief TX burst of about 0.5ms, followed by a listen window (for scan responses), then the radio is off. At a 100ms advertising interval, the radio is active for roughly 3-5% of the time. Average current: 10-25mA depending on advertising interval and payload size.

BLE scanning (passive): The radio listens on advertising channels, rotating through channels 37, 38, 39 with configurable scan windows and intervals. Passive scanning (listen only, no scan request) draws 10-20mA. Active scanning (sends SCAN_REQ to get scan responses) adds TX bursts and averages 15-25mA.

BLE connected (HID - Bad-BT): Maintaining a BLE connection for HID (keyboard) uses the connection interval timing. At a 50ms connection interval, the radio is active for ~1ms every 50ms (2% duty cycle for the connection event). Average current for a connected BLE HID device: 8-15mA. This is notably lower than WiFi even in active use, which is why BLE keyboards last for months on a coin cell.

BLE + Shiver mesh (coexistence): BLESpam running alongside ESP-NOW mesh adds the mesh protocol's radio time on top of BLE advertising. During the 500ms mesh window every 2 seconds (25% duty cycle), the radio handles ESP-NOW traffic. The combined current averages around 40-60mA, depending on mesh traffic volume.

IR Blasting Current Spike

IR transmission is interesting from a power perspective because it creates brief but significant current spikes. The IR LED in a typical IR blaster module draws 50-100mA during a pulse. IR remote control protocols modulate a 38kHz carrier with data encoding - the LED turns on and off thousands of times per second during a transmission.

An NEC protocol frame takes about 67ms to transmit (9ms lead burst + 4.5ms gap + 32 data bits + stop bit). During those 67ms, the IR LED is drawing high current in bursts. Average current during an IR transmission is around 30-50mA, but peak current during the lead burst can hit 80-100mA.

TV-B-Gone mode cycles through a database of power codes for hundreds of TV brands. Each code takes 50-100ms, and the TV-B-Gone sequence runs for 1-2 minutes total. During active TV-B-Gone operation, the current draw is moderate (30-50mA average) but sustained longer than a single IR command.

The current spikes from IR transmission are handled by the 500mAh battery and decoupling capacitors on the PCB. A brief 100mA spike over 9ms consumes about 0.25mAh - negligible on a 500mAh battery. The concern is that sudden current demands can cause voltage droop on the supply rail, which is why the hardware design includes adequate bulk capacitance near the IR LED driver.

Display Power

The SSD1306 OLED draws about 10-15mA when displaying content, and near zero when turned off. The current varies with screen content - more lit pixels means more current. A full-white screen draws more than the typical BLEShark menu (dark background, white text).

With the display on and showing a typical menu: ~12mA for the display. With the display off (after timeout): ~1mA for the display controller in standby.

The display timeout (default ~60 seconds of inactivity) saves approximately 11mA continuously when you're not actively using the device. Over an hour of pocket carry time, that's 11mAh saved - about 2% of total battery capacity. Small, but it adds up during a full day of on-and-off use.

Battery Life Math

Battery life = capacity (mAh) / average current draw (mA). For the BLEShark's 500mAh battery:

graph TD
    subgraph "BLEShark Nano Battery Budget (500mAh)"
        subgraph "WiFi Scanning Mode"
            WS_DRAW["Average: ~80mA
(RX + periodic TX)"] WS_OLED["OLED: +15mA"] WS_TOTAL["Total: ~95mA"] WS_LIFE["Battery life: ~5.2 hours"] end subgraph "AP Spam Mode" AP_DRAW["Average: ~140mA
(continuous TX)"] AP_OLED["OLED: +15mA"] AP_TOTAL["Total: ~155mA"] AP_LIFE["Battery life: ~3.2 hours"] end subgraph "BLE Scanning Mode" BLE_DRAW["Average: ~35mA
(BLE RX)"] BLE_OLED["OLED: +15mA"] BLE_TOTAL["Total: ~50mA"] BLE_LIFE["Battery life: ~10 hours"] end subgraph "Idle (Menu/Display)" IDLE_DRAW["CPU: ~15mA
(active, no radio)"] IDLE_OLED["OLED: +15mA"] IDLE_TOTAL["Total: ~30mA"] IDLE_LIFE["Battery life: ~16.6 hours"] end end WS_DRAW --> WS_OLED --> WS_TOTAL --> WS_LIFE AP_DRAW --> AP_OLED --> AP_TOTAL --> AP_LIFE BLE_DRAW --> BLE_OLED --> BLE_TOTAL --> BLE_LIFE IDLE_DRAW --> IDLE_OLED --> IDLE_TOTAL --> IDLE_LIFE

Estimated battery life across BLEShark Nano operating modes - from 3+ hours of continuous AP spam to 10+ hours of passive BLE scanning on the 500mAh LiPo cell.

  • Active WiFi scanning continuously: ~120mA average -> ~4 hours
  • Active deauth / frame injection: ~220mA average -> ~2.3 hours
  • BLE scanning only: ~20mA average -> ~25 hours
  • BLE connected (Bad-BT active): ~15mA average -> ~33 hours
  • Hosting captive portal: ~120mA average -> ~4 hours
  • Idle (display off, no radio activity): ~5mA -> ~100 hours
  • Deep sleep: ~0.01mA -> ~5,000 hours (theoretical)

Mixed use - scanning for a few minutes, then idle, then running deauth for a few minutes - lands somewhere in the middle. A typical active security testing session with the BLEShark should last 3-5 hours before needing a charge. USB-C means you can charge off a power bank while using the device.

How the Firmware Manages Power

The BLEShark firmware makes deliberate power management decisions that aren't always visible to the user:

sequenceDiagram
    participant USER as User Input
    participant FW as Firmware
Power Manager participant RADIO as WiFi/BLE Radio participant OLED as OLED Display participant BAT as Battery Monitor Note over FW,BAT: Active Operation USER->>FW: Start WiFi scan FW->>RADIO: Enable WiFi RX FW->>OLED: Show scan results Note over FW,BAT: Idle Detection FW->>FW: No input for 30s FW->>OLED: Dim display FW->>FW: No input for 60s FW->>OLED: Display off FW->>RADIO: Reduce scan interval Note over FW,BAT: Battery Monitoring BAT->>FW: Voltage: 3.3V (low) FW->>OLED: Show battery warning FW->>RADIO: Reduce TX power BAT->>FW: Voltage: 3.0V (critical) FW->>RADIO: Disable radio FW->>OLED: Show shutdown warning FW->>FW: Enter deep sleep Note over FW,BAT: USB-C Charging BAT->>FW: USB power detected FW->>FW: Resume from sleep FW->>OLED: Show charging status

Firmware power management strategy - the BLEShark progressively reduces power consumption during idle periods and monitors battery voltage to prevent brownout damage.

Radio-off intervals: During BLE scanning, the coexistence controller uses scan window/interval settings that leave gaps between scan windows. A scan interval of 200ms with a scan window of 100ms means the radio is off 50% of the time. You trade scan frequency for battery life.

Display dimming: After a shorter timeout (configurable), the display dims before turning off. Dimming reduces current without losing the display entirely.

CPU frequency scaling: Not all tasks need 160MHz. For UI rendering and BLE scanning, the ESP32-C3 can run at 80MHz and draw proportionally less current. The firmware scales clock speed based on what's running.

Mesh duty cycle: The Shiver mesh uses a 500ms active window every 2 seconds - a 25% duty cycle. Nodes that have no pending commands sleep the radio for the 1500ms idle period, then wake for the next window. This structured scheduling means mesh participation costs around 25% of the radio-always-on current.

Charging awareness: When plugged into USB-C, some power constraints relax. OTA updates, for example, run at full WiFi speed without throttling for power, because USB is supplying more than enough current to compensate.

Charging: USB-C and Charge Rate

The BLEShark Nano charges via USB-C. The charge circuit uses a standard LiPo charge controller (typically TP4054 or similar) that charges the 500mAh cell at 300-500mA (0.6-1C rate), providing a full charge in about 1-2 hours from empty.

USB-C at 5V provides up to 500mA from a standard port (2.5W), or higher with Power Delivery. The charge controller limits charge current to safe levels regardless of what the USB port can supply. You can charge from a laptop USB port, a USB wall adapter, or a USB power bank - all work fine.

You can use the BLEShark while charging. The charge circuit handles this gracefully: if current consumption exceeds what USB is supplying, the battery supplements the supply. If USB is supplying more than you're consuming, the excess goes to charging the battery. The charge IC manages this automatically.

A fully depleted 500mAh battery charged at 400mA reaches approximately 80% capacity in about 45 minutes, then the charge rate tapers during the constant-voltage phase for the final 20%. Total time from dead to full is typically around 90-120 minutes.

Get BLEShark Nano

Back to blog

Leave a comment