adafruit / circuitpython

CircuitPython - a Python implementation for teaching coding with microcontrollers
https://circuitpython.org
Other
4.08k stars 1.21k forks source link

BLE HID does not fully connect on ESP32-S3 #9430

Closed BlitzCityDIY closed 1 month ago

BlitzCityDIY commented 3 months ago

CircuitPython version

Adafruit CircuitPython 9.1.0-rc.0 on 2024-07-09; Adafruit Feather ESP32S3 No PSRAM with ESP32S3

Code/REPL

import board
import keypad
from adafruit_hid.keyboard import Keyboard
from adafruit_hid.keycode import Keycode
import adafruit_ble
from adafruit_ble.advertising import Advertisement
from adafruit_ble.advertising.standard import ProvideServicesAdvertisement
from adafruit_ble.services.standard.hid import HIDService
from adafruit_ble.services.standard.device_info import DeviceInfoService

COLUMNS = 3
ROWS = 4
keys = keypad.KeyMatrix(
    row_pins=(board.D12, board.D11, board.D10, board.D9),
    column_pins=(board.A0, board.A1, board.A2),
    columns_to_anodes=False,
)

# connect to BLE
hid = HIDService()
device_info = DeviceInfoService(software_revision=adafruit_ble.__version__,
                                manufacturer="Adafruit Industries")
advertisement = ProvideServicesAdvertisement(hid)
# Advertise as "Keyboard" (0x03C1) icon when pairing
# https://www.bluetooth.com/specifications/assigned-numbers/
advertisement.appearance = 961
scan_response = Advertisement()
scan_response.complete_name = "BLE ESP32-S3 MacroPad"
# make a keyboard
kbd = Keyboard(hid.devices)

ble = adafruit_ble.BLERadio()
if not ble.connected:
    print("advertising")
    ble.start_advertising(advertisement, scan_response)
else:
    print("already connected")
    print(ble.connections)
while True:
    while not ble.connected:
        pass
    while ble.connected:
        key_event = keys.events.get()
        if key_event:
            if key_event.pressed:
                kbd.press(Keycode.SPACE)
            if key_event.released:
                kbd.release_all()
    ble.start_advertising(advertisement)

Behavior

Auto-reload is on. Simply save files over USB to run them or enter REPL to disable.
code.py output:
advertising

The Feather advertises the BLE connection and it appears as a device. When the connection is initiated, the Feather thinks that a connection is achieved. However, on the host device it will appear as still connecting (Windows) and eventually fail out or will show as connected but will not be shown as an active device (Mac). A keypress is never able to be sent.

Description

No response

Additional information

i also tried it without the keypad part of the code, but the same behavior occurred:

import board
import adafruit_ble
from adafruit_ble.advertising import Advertisement
from adafruit_ble.advertising.standard import ProvideServicesAdvertisement
from adafruit_ble.services.standard.hid import HIDService
from adafruit_ble.services.standard.device_info import DeviceInfoService

# connect to BLE
hid = HIDService()
device_info = DeviceInfoService(software_revision=adafruit_ble.__version__,
                                manufacturer="Adafruit Industries")
advertisement = ProvideServicesAdvertisement(hid)
# Advertise as "Keyboard" (0x03C1) icon when pairing
# https://www.bluetooth.com/specifications/assigned-numbers/
advertisement.appearance = 961
scan_response = Advertisement()
scan_response.complete_name = "BLE ESP32-S3 MacroPad"
# make a keyboard
kbd = Keyboard(hid.devices)

ble = adafruit_ble.BLERadio()
if not ble.connected:
    print("advertising")
    ble.start_advertising(advertisement, scan_response)
else:
    print("already connected")
    print(ble.connections)
while True:
    while not ble.connected:
        pass
    while ble.connected:
        print("connected")
        time.sleep(5)
    ble.start_advertising(advertisement)
rikkuness commented 3 months ago

Seeing the same thing, I've tried to pull the latest releases of both the adafruit_ble and adafruit_hid too and the same thing occurs.

Adafruit CircuitPython 9.1.0 on 2024-07-10; TinyS3 with ESP32S3
Board ID:unexpectedmaker_tinys3

Update: After posting this I noticed the board ID of tinys3 but my board is actually the Feather S3, once I reflashed with the correct build for my board, the BLE device now connects properly and shows as connected at least in MacOS.

BlitzCityDIY commented 1 month ago

just tested again with Adafruit CircuitPython 9.2.0-alpha.2350-23-ge5e9c5ca84 on 2024-08-21; Adafruit Feather ESP32S3 No PSRAM with ESP32S3 and i had the same result with windows 11

dhalbert commented 1 month ago

In the REPL, try doing:

import _bleio
_bleio.adapter.erase_bonding()

and see if that makes any difference.

BlitzCityDIY commented 1 month ago

i tried that and it did connect for a second but then disconnected and said "driver error" under devices. tried on macOS ventura and the same result occurred- connects for a second and then disconnects. i tried on iOS and it will connect but i can't get a key input to transfer and on the CircuitPython side the REPL is recognizing the button input

tannewt commented 1 month ago

Welp. I suspect this is due to not implementing Descriptor. HID uses this to distinguish different report characteristics.