How the BLEShark Nano's ESP32 Handles WiFi and BLE Simultaneously
The ESP32-C3 inside the BLEShark Nano has a single 2.4GHz radio. One antenna. One RF front end. Yet it can scan WiFi networks while also advertising over BLE, run the Shiver mesh while sniffing 802.11 traffic, and keep a BLE connection alive while you browse the file portal. This seems like it shouldn't work - and it almost doesn't. The whole thing is held together by a coexistence controller and very careful scheduling.
This article explains how that works at a hardware and firmware level.
stateDiagram-v2
[*] --> IDLE
IDLE --> WIFI_ACTIVE: WiFi request
(scan, TX, RX)
IDLE --> BLE_ACTIVE: BLE request
(advertise, scan)
WIFI_ACTIVE --> IDLE: WiFi done or
BLE priority interrupt
BLE_ACTIVE --> IDLE: BLE window closes
IDLE --> ESPNOW: ESP-NOW request
(mesh packet)
ESPNOW --> IDLE: Packet sent/received
WIFI_ACTIVE --> WIFI_ACTIVE: Extend for
active transfer
note right of WIFI_ACTIVE: WiFi gets priority
for data integrity
note right of BLE_ACTIVE: BLE windows are
short and predictable
note right of ESPNOW: Uses WiFi radio
but custom protocol
ESP32-C3 coexistence controller state machine - the radio arbitrator prioritizes WiFi data integrity while scheduling BLE and ESP-NOW operations in available time slots
Table of Contents
- One Radio, Two Protocols
- The Coexistence Controller
- Time-Division Multiplexing in Practice
- BLE Advertising During WiFi Scanning
- Where It Breaks Down
- How BLEShark Nano Handles the Tradeoffs
- The Shiver Mesh Complication
One Radio, Two Protocols
WiFi (802.11) and Bluetooth Low Energy both operate in the 2.4GHz ISM band. Classic Bluetooth uses frequency hopping across 79 channels. BLE uses three fixed advertising channels (37, 38, 39) at 2402, 2426, and 2480 MHz, plus 37 data channels. WiFi channels 1 through 13 overlap significantly with this spectrum.
On a desktop or laptop, the WiFi chip and the Bluetooth chip are separate silicon. They share the antenna through a coexistence arbitration scheme, but they're fundamentally independent radios. On the ESP32-C3, there is no such luxury. One RF transceiver handles everything.
The ESP32-C3 uses Espressif's own RF front end, integrated directly on-chip. The baseband handles both 802.11b/g/n (2.4GHz only) and BLE 5.0. At any given clock cycle, it can only do one thing - but it switches between them fast enough that both protocols appear to run concurrently.
gantt
title ESP32-C3 Radio Time-Division Multiplexing
dateFormat X
axisFormat %L ms
section WiFi
Channel scan :w1, 0, 15
Idle :w2, 15, 20
Beacon RX :w3, 20, 25
Idle :w4, 25, 30
Data TX :w5, 30, 45
section BLE
Idle :b1, 0, 15
ADV on ch37 :b2, 15, 17
ADV on ch38 :b3, 17, 19
ADV on ch39 :b4, 19, 20
Idle :b5, 20, 30
Scan window :b6, 30, 32
Time-division multiplexing on the ESP32-C3 - the single 2.4 GHz radio alternates between WiFi and BLE tasks in millisecond slices, managed by the coexistence controller
The Coexistence Controller
Espressif's ESP-IDF includes a coexistence (coex) controller - a software component that arbitrates between WiFi and BLE when both have pending radio operations. It uses a priority-based scheduling system with two main modes:
- WiFi preferred: WiFi operations preempt BLE when there's a conflict. BLE advertising slots can be skipped if WiFi is actively transmitting or receiving.
- BLE preferred: BLE operations get priority. WiFi throughput drops to accommodate BLE timing requirements.
- Dynamic scheduling: The coex controller adjusts priorities based on what each subsystem actually needs right now.
The coex controller communicates with both the WiFi driver and the BLE controller through a shared grant/deny mechanism. When the WiFi driver wants to transmit, it requests a grant. If BLE has a connection event scheduled in the next few milliseconds, the coex controller may deny the WiFi request or force it to wait. The same applies in reverse.
This sounds clean in theory. In practice, the interaction between BLE connection interval timing, WiFi channel scan dwell times, and the coex scheduler creates a complex dance that Espressif has tuned across multiple SDK releases.
Time-Division Multiplexing in Practice
The fundamental mechanism is time-division multiplexing (TDM). The radio switches between WiFi and BLE on a millisecond timescale. Neither protocol "knows" it's sharing the hardware - they each get time slots, and the coex controller enforces them.
A typical BLE connection uses a connection interval of 7.5ms to 4000ms. During each connection event, the BLE controller needs the radio for approximately 1-2ms to send and receive packets. The coex scheduler reserves those windows and lets WiFi have the rest.
WiFi channel scanning adds another layer. When the BLEShark scans for nearby networks, it dwells on each channel for 100-300ms collecting beacon frames and probe responses. During a dwell, the radio is committed to that channel. BLE connection events can still interrupt a scan dwell if a connection event is due - the scan pauses, the BLE event completes, and the scan resumes (potentially missing some packets during the gap).
The key insight is that BLE has hard timing constraints (a missed connection event can break the link) while WiFi scanning is best-effort. The coex controller respects this hierarchy.
BLE Advertising During WiFi Scanning
BLE advertising is easier to coexist with WiFi than BLE connections are, because advertising has no strict timing requirement. If a BLE advertisement is delayed by 10ms, the scanner on the other end just might miss it - but the advertiser can retry on the next advertising interval. No connection drops, no protocol failure.
The BLESpam feature on BLEShark Nano exploits this. It sends rapid BLE advertising packets to nearby iOS and Android devices, cycling through spoofed device profiles. Because advertising is tolerant of delays, BLESpam can coexist with active WiFi scanning without either completely breaking the other. The WiFi scan may miss some beacons during BLE advertising bursts, and BLE advertisement packets may be delayed during channel dwells, but both functions continue running.
This is why you can run the BLE scanner (which does passive scanning on BLE advertising channels) and WiFi scanning at the same time on the BLEShark - the coex controller handles the scheduling, and the latency introduced is acceptable for both tasks.
Where It Breaks Down
There are three scenarios where the coexistence system creates real problems:
High-throughput WiFi with an active BLE connection. If the BLEShark is connected to a WiFi network and maintaining a BLE connection (like a Bad-BT session), the coex controller constantly interrupts WiFi for BLE connection events. WiFi throughput can drop to 30-50% of its uncontested rate. For downloading a large OTA firmware file, this matters.
BLE connections with short connection intervals. A BLE connection interval of 7.5ms means the radio needs to context-switch 133 times per second. At that rate, there's almost no room for WiFi operations. The BLEShark uses longer connection intervals where possible (typically 50-100ms for HID) to leave more time for WiFi.
Simultaneous BLE scan and WiFi active monitor mode. Running passive BLE scanning (which requires listening on BLE advertising channels 37, 38, 39) simultaneously with a WiFi channel dwell (which requires the radio locked to a specific 802.11 channel) creates a hardware conflict. The coex controller has to pick one. The BLEShark firmware resolves this by time-slicing the two operations rather than truly running them simultaneously.
The bottom line: "simultaneous" is a useful approximation at the user-facing feature level. At the hardware level, it's fast sequential switching with careful scheduling.
How BLEShark Nano Handles the Tradeoffs
The BLEShark firmware makes explicit tradeoffs based on what each app actually needs.
The WiFi scanner uses 120ms channel dwells and cycles through all 13 channels. BLE advertising continues during this scan, but BLE scan (passive listening for nearby BLE devices) pauses during channel dwells. When you open the BLE scanner, the WiFi scanner reduces its dwell time to 80ms to give BLE scanning more time slots. These are firmware-level decisions, not hardware constraints.
Deauth and handshake capture require the radio locked on a specific WiFi channel for extended periods. During an active deauth sequence, BLE operations are essentially paused except for brief windows between deauth frame bursts. This is a deliberate choice - a missed deauth frame is worse than a missed BLE advertisement. The BLE scanner will show stale results while deauth is running.
Captive portal mode is the opposite. When hosting the portal AP, WiFi is in AP mode (transmitting on a fixed channel), and BLE scanning can run more freely since the WiFi radio isn't hopping channels. This is one of the few modes where both subsystems have a comfortable amount of radio time.
The Shiver Mesh Complication
The Shiver mesh adds a third protocol to the mix: ESP-NOW, which runs on the same WiFi radio. ESP-NOW uses raw 802.11 frames sent at 1 Mbps or 250 kbps (Long Range mode). It's not a separate physical layer - it shares the WiFi radio with normal WiFi operations.
This creates an important constraint that the BLEShark is explicit about: BLE and mesh are mutually exclusive on a single device. The mesh requires the radio in a state that's incompatible with maintaining a persistent BLE connection. BLESpam can coexist with mesh because BLESpam hops back to mesh windows - it advertises BLE packets, then steps aside during the 500ms mesh window to forward any pending ESP-NOW frames, then goes back to BLE advertising. The 1500ms between mesh windows is enough time for substantial BLE advertising.
Bad-BT is different. Bad-BT requires a persistent BLE connection with specific timing guarantees. A BLE connection that gets interrupted for 500ms every 2 seconds will simply drop. So when you activate Bad-BT on a node that's part of a mesh, that node fully disconnects from the mesh for the duration of the Bad-BT session. It rejoins when Bad-BT is finished. The other mesh nodes continue operating normally.
This is not a bug or a limitation to work around - it's the correct behavior given the hardware constraints. The ESP32-C3 has one radio. Trying to hold a BLE connection and participate in a time-synchronized ESP-NOW mesh at the same time would result in both failing unreliably. The firmware picks a clear winner based on what you've asked it to do.
For multi-node deployments using the Shiver mesh (3 to 16 nodes with Shiver packs), the practical implication is simple: nodes assigned to Bad-BT testing work independently, nodes assigned to mesh-based scanning and monitoring stay in mesh mode. The mesh coordinator handles the assignment.
Why This Matters for Security Research
Understanding the radio architecture helps you set realistic expectations for what the BLEShark can do at the same time.
Running a WiFi scan and a BLE scan simultaneously? Works fine - the coex controller handles it and both give you useful results. Running deauth on one channel while maintaining a BLE connection? The BLE connection will degrade. Running the mesh and BLESpam? Supported, with the hop-back mechanism. Running the mesh and Bad-BT? The device picks mesh off and Bad-BT runs solo.
The ESP32-C3's single-radio architecture is what makes the BLEShark Nano small and affordable. The $36.99 price point exists partly because there's no dedicated Bluetooth chip, no separate WiFi chip, no RF switch for antenna sharing between separate ICs. Espressif solved the coexistence problem in software, and Espressif's coexistence controller is genuinely good. But it has limits, and knowing those limits makes you a better user of the tool.