Repository navigation
Description
CircuitPython version and board name
cp 10.0.3
waveshare esp32-s3 touch lcd-2Code/REPL
# code.py -- ESP32-S3 Reverse TFT Feather
# Minimal BLE HID keyboard: D0, D1, D2 send A, B, C
import time
import board
import digitalio
import adafruit_ble
from adafruit_ble.advertising.standard import ProvideServicesAdvertisement
from adafruit_ble.services.standard.hid import HIDService
from adafruit_hid.keyboard import Keyboard
from adafruit_hid.keycode import Keycode
# -----------------------------
# Buttons on ESP32-S3 Reverse TFT
# -----------------------------
# Per guide:
# - D0 uses Pull.UP -> active LOW when pressed
# - D1, D2 use Pull.DOWN -> active HIGH when pressed [oai_citation:2‡Adafruit Learning System](https://learn.adafruit.com/esp32-s3-reverse-tft-feather?view=all&utm_source=chatgpt.com)
button0 = digitalio.DigitalInOut(board.D0)
button0.switch_to_input(pull=digitalio.Pull.UP)
button1 = digitalio.DigitalInOut(board.D1)
button1.switch_to_input(pull=digitalio.Pull.DOWN)
button2 = digitalio.DigitalInOut(board.D2)
button2.switch_to_input(pull=digitalio.Pull.DOWN)
prev0 = button0.value
prev1 = button1.value
prev2 = button2.value
# -----------------------------
# BLE HID setup (minimal)
# -----------------------------
ble = adafruit_ble.BLERadio()
ble.name = "RevTFT HID"
hid = HIDService()
advertisement = ProvideServicesAdvertisement(hid)
advertisement.short_name = "RevTFT" # keep adv payload small
# You can add: advertisement.appearance = 961 # keyboard icon
# but skip it at first if you're still hitting memory issues
kbd = Keyboard(hid.devices)
print("BLE HID starting; device name:", ble.name)
while True:
# Start advertising and wait for a connection
print("Advertising...")
ble.start_advertising(advertisement)
while not ble.connected:
# Just idle while waiting for a connection
time.sleep(0.05)
print("Connected!")
# Now we're connected: scan buttons and send keys
while ble.connected:
v0 = button0.value
v1 = button1.value
v2 = button2.value
# Helper: send a key once on the press edge
def send_key(keycode, label):
try:
kbd.send(keycode)
print(f"{label} key sent")
except OSError as e:
# connection might have dropped mid-send
print("Send error:", e)
# D0: active LOW -> press edge = high -> low
if prev0 and not v0:
send_key(Keycode.A, "D0 (A)")
# D1: active HIGH -> press edge = low -> high
if not prev1 and v1:
send_key(Keycode.B, "D1 (B)")
# D2: active HIGH -> press edge = low -> high
if not prev2 and v2:
send_key(Keycode.C, "D2 (C)")
prev0 = v0
prev1 = v1
prev2 = v2
time.sleep(0.01) # debounce
print("Disconnected; will re-advertise")
# Loop repeats, re-calling start_advertising()Behavior
after a few days working with esp32-s3 and ble hid(and midi). i noticed that if i forget settings in windows and clear binding on esp, i can get a stable ble connection, but, if i turn off ble in windows( or drop the connection in anyway). it may reconnect, but no longer works. also, once power cycle of device happens, any pairing still shows, but device never reconnects and works again, unitil i forget ble settings again, unbind device, reboot, and re-pairing then works again. obviously this isnt correct, as it shoukd survive reboots and signal drops/reconnects. I noticed as soon as i pkug in device, windows shows esp device as available bluetooth even before any code runs... is there a ble stack in the tinybootloader? that may be causing the conflict, and causing problems with ble resources/ mismatches while trying to reconnect. i dont know much how the bootloader, u2f file is configured for this board, and how its ble may or may not be in some kind ofauto mode on boot. this behavior is exactly same on ipad and mac as well, just curious if any headway on this or info is available, i just wanted to add my observations. btw, i was testing using Mikey's stripped down ble hid test code from this post, which avoids the nimbe memory bug. one more note, after once working, and powercycle, the code tryies to run but hangs...doesnt crash...and if i turn off blutooth in windows, code resumes. and if i turn on blutooth again, it hangs again. its like the esp is blocking on trying to connect, very odd. thanks for any help,
andy
Description
No response
Additional information
No response
Activity
ThomasAtBBTF commentedon Jan 1, 2026
Same problem here !
I do this:
And it works as long as I do not reset / power off my ESP32S3.
(It works to stop the code with ctrl-c makes changes to the code and restart. After that the BLE connection will come back successfully.)
dhalbert commentedon Sep 4, 2026
I believe this is fixed by #11237, which is in 10.3.0 and later. I'm closing this, but if you are still having trouble, we can reopen.
jlubin2001 commentedon Sep 26, 2026
Still seeing this on 10.3.1 (which should include #11237) with an Android host. It reproduces every time, and I'm happy to test a fix.
Setup
Adafruit CircuitPython 10.3.1 on 2026-09-14; Adafruit Feather ESP32-S3 Reverse TFT with ESP32S3(board IDadafruit_feather_esp32s3_reverse_tft)combined.bin, full flash erase first)10.x-mpy-20260910:adafruit_ble10.1.3,adafruit_hid6.1.10import test_ble) with nothing else running._bleio.adapter.erase_bonding()at start; the phone's old pairing was removed before the test.Minimal code
What happens
connection.pair()returns in ~0.3 s withpaired=True.paired=True, and also on the first attempt before I added the explicitpair()call.paired=False: the bond from the previous connection isn't kept. So it loops (connect → pair → drop) every few seconds until advertising stops.Log from my full test script, which has the same logic plus a 5-line limit (test_ble.py). Connections 6–8 are shown; #6 through #11 look identical.
Expected: the bond persists, reconnects come back already paired, and the connection stays up.
Context: this is for an assistive sip-and-puff Morse keyboard (AeroMorse) used as someone's only way to operate a computer, so a working BLE HID keyboard on ESP32-S3 would open up phones and tablets for them. Happy to try a test build.
dhalbert commentedon Sep 26, 2026
Could you test with 11.0.0-alpha.1? There were some further BLE fixes since 10.3.1. Thanks.
jlubin2001 commentedon Sep 27, 2026
Thanks — tested with 11.0.0-alpha.1 (2026-09-24 build) on the same setup: Adafruit Feather ESP32-S3 Reverse TFT (#5691), TinyUF2 0.35.0, adafruit_ble + adafruit_hid from the 10.x bundle, host = Samsung Galaxy A15 (Android 16). Same minimal HID keyboard test as before (
HIDService+DeviceInfoService, appearance 961,conn.pair()if not paired, thenlayout.write()five lines, 3 s apart).Summary: pairing and the connection are now much better, but keystrokes still never arrive on the phone.
Run 1 — bonds erased on the board at start, fresh pairing
Afterwards the phone keeps "AeroMorse Blue" under Paired devices (10.3.1 didn't), and the endless connect/drop/reconnect loop from 10.3.1 is gone.
Run 2 — board keeps its bond, phone reconnects to the saved pairing: same pattern (paired=True after
pair(), drops after 12.6 s and 6.6 s).Run 3 — phone's per-device "Text input" switch turned ON. In Android's settings for the paired device, Text input was OFF, and it can only be switched on while the board is connectable. With it ON:
So the drops seem to come from Android dropping the link while Text input is off. But even in run 3 — connected, paired, stable, notes app focused — no text appears on the phone, and
layout.write()raises no error on the board. The status bar flickersBLE:Ok/BLE:Reconnectingwhile typing, if that's relevant.Run 4 — Windows 11 PC host (Intel Bluetooth), to rule out Android: paired and connected (
paired=True), typed 5/5 lines, stayed connected — but nothing appeared in Notepad (focused) either. Device Manager shows a "Bluetooth Low Energy GATT compliant HID device" for it, so Windows does see a keyboard. Two things that may be clues:CIRCUITPYb93e, not the name set withble.name = "AeroMorse Blue"(the phone showed "AeroMorse Blue"). After the test,_bleio.adapter.namereadsCIRCUITPYb93eagain.ADAF0001…,ADAF0004…, and 0xFEBB) on the same device.supervisor.disable_ble_workflow()isn't available on this build, so I couldn't test with the workflow off.So it's not Android-specific: two different hosts pair, connect and enumerate a HID keyboard, but receive no keystrokes.
Happy to test another build or add logging if that helps.
jhonasn commentedon Oct 17, 2026
I'm having the same problem here, tested both on 10.3.1 and in 11.0.0-alpha.1
board: VCC-GND YD-ESP32-S3 N16R8
adafruit_ble and adafruit_hid bundle version 10.x and 11.x
In my Linux (Arch) it works fine, but in my phone Android 10 (Xiaomi Redmi Note 8) and Fire TV fail.
I will describe with my words what I think is the same problem on the devices that fail:
My minimal testing code was this: