arduino-pico
arduino-pico copied to clipboard
BLE can't pair to new host after initial pairing
After messing around with the auruino-pico I thought I was doing something weird, however I found that if you pair it everything will work as intended. But if you unpair it from the same device and try to pair with something else it completely stops outputting. You have to turn off the pico unpair then turn it on and pair to the new device. I figure this is not a intended function. I tried this on multiple versions. They basic code I was using to find that out is as follows:
#include <KeyboardBLE.h>
const int pin = 2; // GPIO pin number
char key = 'w'; // Key to send
void setup() {
pinMode(pin, INPUT_PULLUP);
KeyboardBLE.begin();
}
void loop() {
if (digitalRead(pin) == LOW) {
KeyboardBLE.write(key);
delay(1000); // Add a delay to avoid key spamming
}
}
Edit: It's almost like it needs to not be paired to anything when you turn it off if you are switching devices. It also happens if it is already connected to the pc and you update the firmware when it reboots it will auto reconnect to the what it was paired to and will not function until you unpair, then turn it off then back on and re-pair it.
Interesting observation, thanks for testing and giving a succinct explanation.
What has me scratching my head is this:
...It also happens if it is already connected to the pc and you update the firmware when it reboots it will auto reconnect ...
The BLE pairing information is actually part of the application binary, so when you flash a new app it gets cleared out. So there are no shared keys available immediately after flashing. No comms would then be possible, I imagine. Maybe the PC is assuming the same BLE MAC already has the key and not negotiating a new one...
This is a very good issue. Found several things already:
- Infinite loop if there's data to send but no connection
- TLV storage is busted. Tries to write a 1-byte boundaries while the flash SDK only supports 256byte alignment. The SDK fixed it, but I copied an older version of their file which didn't have this fix.
That was just looking during lunch. Let me implement some fixes for these two and see if that clears things up. The TLV alignment might explain why only the 1st connection works...the 2nd and subsequent ones would not be stored properly...
Did some digging around and it looks like this is a BTstack internal thing, and only occurs in BLE mode.
Ths following classic BT sketch pairs with multiple computers in a row without incident:
#include <KeyboardBT.h>
void setup() {
KeyboardBT.begin();
}
void loop() {
if (BOOTSEL) {
KeyboardBT.write('w');
while (BOOTSEL) delay(100);
}
}
Only the BLE version has an issue:
#include <KeyboardBLE.h>
void setup() {
KeyboardBLE.begin();
}
void loop() {
if (BOOTSEL) {
KeyboardBLE.write('w');
while (BOOTSEL) delay(100);
}
}
Tracing the callbacks shows that BTStack is not calling us with a "new connection handle" event after negotiating with a new BLE host after the initial connection.
https://github.com/earlephilhower/arduino-pico/blob/39a2bbd78811be87edac56b545d8b3a3b3b5bca4/libraries/HID_Bluetooth/src/PicoBluetoothBLEHID.h#L179-L186
So the core here can't actually send or receive anything and isn't even aware things are connected.
The infinite loop potential has been removed, and the TLV database is actually okay so those two things are not part of the issue here (TLV issues would affect classic BT too).
Looks like this really is in BTStack or the CYW43 chip FW as others seem to run into it even with the raw SDK (https://github.com/joba-1/PicoW_A2DP/tree/main ). Given that, there's not anything we can do other than hope for a new PicoSDK and FW...