Breadboard
docs
Example project · ESP32

Bluetooth LE: scan, connect, discover

Two ESP32-C6 boards run the full BLE story through the real vendor controller: one registers a Battery Service and advertises connectably, the other scans, hears the advertisement, connects as central over a genuine LE link, and discovers the server's GATT services. One script runs on both boards; each derives its role from its own MAC. Watch the serial tabs narrate both sides, follow ADV_IND / CONNECT_IND / ATT frames in the 📡 Sniffer, and click either board's Bluetooth tab for its live link state.

The Bluetooth LE: scan, connect, discover circuit as rendered by the simulator

What's on the bench

  • 2× Battery
  • 2× ESP32-C6

The code

This MicroPython script runs on the emulated board every boot; edit it in the Code tab.

import bluetooth, time
b = bluetooth.BLE()
b.active(1)
server = b.config('mac')[1][-1] % 2 == 0
if server:
    S = (bluetooth.UUID(0x180F), ((bluetooth.UUID(0x2A19), bluetooth.FLAG_READ | bluetooth.FLAG_WRITE),))
    ((h,),) = b.gatts_register_services((S,))
    def cb(e, d):
        if e == 1:
            print('SRV ' + 'central connected')
        elif e == 2:
            print('SRV ' + 'central disconnected')
    b.irq(cb)
    b.gap_advertise(50000, b'\x02\x01\x06\x05\xffCAFE', connectable=True)
    print('SRV ' + 'advertising battery service')
else:
    tgt = []
    cn = []
    def cb(e, d):
        if e == 5 and not tgt:
            tgt.append((d[0], bytes(d[1])))
            print('CLI ' + 'found advertiser')
        elif e == 7:
            cn.append(d[0])
            print('CLI ' + 'connected')
        elif e == 9:
            print('CLI ' + 'service', d[3])
        elif e == 10:
            print('CLI ' + 'discovery done')
    b.irq(cb)
    b.gap_scan(0, 30000, 30000)
    while not tgt:
        time.sleep_ms(50)
    b.gap_scan(None)
    time.sleep_ms(50)
    b.gap_connect(tgt[0][0], tgt[0][1])
    while not cn:
        time.sleep_ms(50)
    time.sleep_ms(300)
    b.gattc_discover_services(cn[0])
    print('CLI discovering services')