BLE Connection to Raspberry Pico

I am trying to connect my Vivoactive 5 to a Raspberry Pi Pico 2 W. My app is based on CIQpi https://forums.garmin.com/developer/connect-iq/b/news-announcements/posts/would-you-like-some-raspberry-pi-with-your-connect-iq.

I cant connect to the Raspberry Pi Pico. I can call Ble.pairDevice(scanResult) and get a device back, but onConnectedStateChanged never gets called.

This is my Pi code:

import sys
sys.path.append("")
from micropython import const
import uasyncio as asyncio
import aioble
import bluetooth

SERVICE_UUID = bluetooth.UUID("0F3DF50F-09C0-40A5-8208-9836C6040B00")
CHAR_UUID = bluetooth.UUID("0F3DF50F-09C0-40A5-8208-9836C6040B23")
ADV_APPEARANCE = const(128)
ADV_INTERVAL_MS = 100000

service = aioble.Service(SERVICE_UUID)
characteristic = aioble.Characteristic(
    service, CHAR_UUID, read=True, notify=True, write=True, capture=True
)
aioble.register_services(service)

async def peripheral_task():
    while True:
        async with await aioble.advertise(
                ADV_INTERVAL_MS,
                name="mpy-temp",
                services=[SERVICE_UUID],
                appearance=ADV_APPEARANCE,
        ) as connection:
            print("Connection from", connection.device)
            while connection.is_connected():
                try:
                    _, data = await characteristic.written(timeout_ms=10000)
                    print("Received", data)
                except asyncio.TimeoutError:
                    print("Timeout waiting for write")
                await asyncio.sleep(1)

asyncio.run(peripheral_task())

  • The forum feels a bit broken, I cant post my monkeyc code...

  • since posting the real code doesnt work, ai to the help...

    chatgpt, convert my code to pseudocode:

    Function onScanResults(scanResults):
        For each result in scanResults until no more results:
            result = scanResults.next()

            If result contains _profiles.PI_SERVICE:
                Display "found" on _view.text
                Set Ble scan state to OFF
                Display "connecting" on _view.text
                
                device = Ble.pairDevice(result)
                
                If device is null:
                    Display "pairing failed" on _view.text
                Else:
                    Display "paired" on _view.text
                    _device = device
                    
                    service = device.getService(_profiles.PI_SERVICE)
                    
                    If service is not null:
                        Display "service found" on _view.text
                        
                        char = service.getCharacteristic(_profiles.PI_LEDS)
                        
                        If char is not null:
                            Display "char found" on _view.text
                            Write value [1] to char with default write type
                            Display "writing" on _view.text
                            
                Break from loop

        Request update on _view

    Function onConnectedStateChanged(device, state):
        If state equals Ble.CONNECTION_STATE_CONNECTED:
            Display "connected" on _view.text
            connected = true
            // Call view.setService() (commented out)
        Else:
            Display "not connected" on _view.text

    The last thing I see is "paired". It never goes to "service found". onConnectedStateChanged does not get called.
    On my phone using nRF connect I can see the Pi and write data to it.

  • What do you see for the device with the BleScan app?  You can scan and then connect, but can't do reads or writes, as those UUIDs need to be hard coded in CIQ.

    https://apps.garmin.com/apps/9bcc8b66-8385-4afb-b93e-f69e01422284

    With a regular pi, you'll see from my blog post I use JS for the Ble stuff.  I'm also using a ESP32 with the Arduino IDE and c++ and i'm not familiar with what you are using with the pico. 

    Maybe bonding is required? A secure connection....

  • There are a number of things you can do with nRFConnect you can't do with CIQ.  For one, it will discover the UUIDs.  That doesn't happen with CIQ.  You may also see the name and the UUID there, but you can't always see those with CIQ.

    With BleScan you can see exactly what CIQ can see,

    You might try hacking the NordicThingy52 sample in the SDK, starting with using your UUIDs in the profile manager instead of those for the thingy52

    What is it you are trying to write?  Turning on notify or something?

    To test in the sim you need the Nordic HW and it needs to be flashed correctly.  The dongle is $12-$15 last I looked and worth every penny.

  • With the scan app I see:
    Name: null
    RSSI: -50
    Raw: 25 bytes
    UUID matches
    When I click connect the text turns orange and there is a countdown from 15. Since it doesnt turn green, connect fails. I guess it turns green when onConnectStateChanged gets calleed sucessfully? So it gets stuck at the same position as my app.

    My final goal is to simply send a float/integer to the pico. But atm Im happy with anything.

  • Yes, green when onConnectStatueChanged if it connects.  With that callback, you can also see if the connection was lost

    What do you see on the pico when CIQ attempts to connect?  You may want to add more detail so see what's happening

  • I see no connection attempt. If I connect with nRF, I see my phones MAC in the console.

  • Just a guess, but the pico may not like that CIQ can only read/write about 20 bytes at a time 

  • I switched to this library:
    https://github.com/earlephilhower/arduino-pico/tree/master/libraries/BTstackLib

    With the LEPeripheral example I was able to get the HDI log of the connection attempt. Over the 15 seconds it keeps repeating this:

    [00:00:35.015] EVT <= 3E 13 01 00 40 00 01 00 BC 7D 29 F5 F9 38 06 00 00 00 90 01 01
    [00:00:35.016] LOG -- hci.c.3381: LE Connection_complete (status=0) type 0, xxxxxx
    [00:00:35.016] LOG -- hci.c.326: create_connection_for_addr xxxxxx,  type 0
    [00:00:35.016] LOG -- hci.c.1675: state 4, role 1, le_con 1
    [00:00:35.016] LOG -- hci.c.1681: Num LE Peripheral roles: 1 of 1
    [00:00:35.017] LOG -- hci.c.3495: New connection: handle 64, xxxxxx
    [00:00:35.017] LOG -- hci.c.666: ACL classic buffers: 0 used of 3
    [00:00:35.017] LOG -- att_server.c.411: SM_EVENT_IDENTITY_RESOLVING_STARTED
    [00:00:35.017] LOG -- sm.c.2314: LE Device Lookup: not found
    [00:00:35.018] LOG -- att_server.c.431: SM_EVENT_IDENTITY_RESOLVING_FAILED
    [00:00:35.018] LOG -- hci.c.8176: BTSTACK_EVENT_NR_CONNECTIONS_CHANGED 1
    [00:00:35.018] LOG -- hci.c.666: ACL classic buffers: 0 used of 3
    Connection complete, con_handle 0x0040
    Device connected callback
    [00:00:35.018] LOG -- hci.c.666: ACL classic buffers: 0 used of 3
    [00:00:35.019] EVT <= 3E 04 14 40 00 01
    [00:00:35.019] LOG -- hci.c.666: ACL classic buffers: 0 used of 3
    [00:00:35.020] LOG -- hci.c.666: ACL classic buffers: 0 used of 3
    [00:00:35.060] ACL <= 40 20 0B 00 07 00 04 00 10 01 00 FF FF 00 28
    [00:00:35.060] LOG -- att_server.c.1004: ATT Packet, handle 0x0040
    [00:00:35.060] LOG -- hci.c.666: ACL classic buffers: 0 used of 3
    [00:00:35.060] LOG -- l2cap.c.1115: L2CAP_EVENT_CHANNEL_CAN_SEND_NOW local_cid 0x4
    [00:00:35.061] LOG -- att_db.c.994: ATT_READ_BY_GROUP_TYPE_REQUEST: from 0001 to FFFF, buffer size 23, type:
    [00:00:35.061] LOG -- btstack_util.c.284: 0x00, 0x28,
    [00:00:35.061] LOG -- hci.c.666: ACL classic buffers: 0 used of 3
    [00:00:35.061] LOG -- l2cap.c.1090: l2cap_send_prepared_connectionless handle 64, cid 0x04
    [00:00:35.062] LOG -- hci.c.666: ACL classic buffers: 0 used of 3
    [00:00:35.062] LOG -- hci.c.895: hci_send_acl_packet_fragments entered
    [00:00:35.062] LOG -- hci.c.901: hci_send_acl_packet_fragments loop entered
    [00:00:35.062] LOG -- hci.c.926: hci_send_acl_packet_fragments loop before send (more fragments 0)
    [00:00:35.062] ACL => 40 00 1A 00 16 00 04 00 11 14 01 00 06 00 51 B5 0A E8 6A 20 31 92 BA 41 AD 62 67 60 E0 B8
    [00:00:35.063] LOG -- hci.c.666: ACL classic buffers: 0 used of 3
    [00:00:35.063] CMD => 35 0C 05 01 40 00 01 00
    [00:00:35.064] LOG -- hci.c.666: ACL classic buffers: 0 used of 3
    [00:00:35.064] LOG -- hci.c.954: hci_send_acl_packet_fragments loop after send (more fragments 0)
    [00:00:35.064] LOG -- hci.c.963: hci_send_acl_packet_fragments loop over
    [00:00:35.065] LOG -- hci.c.666: ACL classic buffers: 0 used of 3
    [00:00:35.065] LOG -- hci.c.666: ACL classic buffers: 0 used of 3
    [00:00:35.065] LOG -- hci.c.666: ACL classic buffers: 0 used of 3
    [00:00:35.082] EVT <= 3E 0B 07 40 00 1B 00 48 01 FB 00 48 08
    [00:00:35.083] LOG -- hci.c.666: ACL classic buffers: 0 used of 3
    [00:00:35.112] ACL <= 40 20 0B 00 07 00 04 00 10 07 00 FF FF 00 28
    [00:00:35.113] LOG -- att_server.c.1004: ATT Packet, handle 0x0040
    [00:00:35.113] LOG -- hci.c.666: ACL classic buffers: 0 used of 3
    [00:00:35.113] LOG -- l2cap.c.1115: L2CAP_EVENT_CHANNEL_CAN_SEND_NOW local_cid 0x4
    [00:00:35.113] LOG -- att_db.c.994: ATT_READ_BY_GROUP_TYPE_REQUEST: from 0007 to FFFF, buffer size 23, type:
    [00:00:35.113] LOG -- btstack_util.c.284: 0x00, 0x28,
    [00:00:35.114] LOG -- hci.c.666: ACL classic buffers: 0 used of 3
    [00:00:35.114] LOG -- l2cap.c.1090: l2cap_send_prepared_connectionless handle 64, cid 0x04
    [00:00:35.114] LOG -- hci.c.666: ACL classic buffers: 0 used of 3
    [00:00:35.114] LOG -- hci.c.895: hci_send_acl_packet_fragments entered
    [00:00:35.114] LOG -- hci.c.901: hci_send_acl_packet_fragments loop entered
    [00:00:35.114] LOG -- hci.c.926: hci_send_acl_packet_fragments loop before send (more fragments 0)
    [00:00:35.115] ACL => 40 00 09 00 05 00 04 00 01 10 07 00 0A
    [00:00:35.115] LOG -- hci.c.666: ACL classic buffers: 0 used of 3
    [00:00:35.115] CMD => 35 0C 05 01 40 00 01 00
    [00:00:35.116] LOG -- hci.c.666: ACL classic buffers: 0 used of 3
    [00:00:35.116] LOG -- hci.c.954: hci_send_acl_packet_fragments loop after send (more fragments 0)
    [00:00:35.117] LOG -- hci.c.963: hci_send_acl_packet_fragments loop over
    [00:00:35.117] LOG -- hci.c.666: ACL classic buffers: 0 used of 3
    [00:00:35.117] LOG -- hci.c.666: ACL classic buffers: 0 used of 3
    [00:00:35.117] LOG -- hci.c.666: ACL classic buffers: 0 used of 3
    [00:00:35.127] ACL <= 40 20 0B 00 07 00 04 00 10 07 00 FF FF 00 28
    [00:00:35.128] LOG -- att_server.c.1004: ATT Packet, handle 0x0040
    [00:00:35.128] LOG -- hci.c.666: ACL classic buffers: 0 used of 3
    [00:00:35.128] LOG -- l2cap.c.1115: L2CAP_EVENT_CHANNEL_CAN_SEND_NOW local_cid 0x4
    [00:00:35.128] LOG -- att_db.c.994: ATT_READ_BY_GROUP_TYPE_REQUEST: from 0007 to FFFF, buffer size 23, type:
    [00:00:35.129] LOG -- btstack_util.c.284: 0x00, 0x28,
    [00:00:35.129] LOG -- hci.c.666: ACL classic buffers: 0 used of 3
    [00:00:35.129] LOG -- l2cap.c.1090: l2cap_send_prepared_connectionless handle 64, cid 0x04
    [00:00:35.129] LOG -- hci.c.666: ACL classic buffers: 0 used of 3
    [00:00:35.129] LOG -- hci.c.895: hci_send_acl_packet_fragments entered
    [00:00:35.130] LOG -- hci.c.901: hci_send_acl_packet_fragments loop entered
    [00:00:35.130] LOG -- hci.c.926: hci_send_acl_packet_fragments loop before send (more fragments 0)
    [00:00:35.130] ACL => 40 00 09 00 05 00 04 00 01 10 07 00 0A
    [00:00:35.130] LOG -- hci.c.666: ACL classic buffers: 0 used of 3
    [00:00:35.131] CMD => 35 0C 05 01 40 00 01 00
    [00:00:35.131] LOG -- hci.c.666: ACL classic buffers: 0 used of 3
    [00:00:35.132] LOG -- hci.c.954: hci_send_acl_packet_fragments loop after send (more fragments 0)
    [00:00:35.132] LOG -- hci.c.963: hci_send_acl_packet_fragments loop over
    [00:00:35.132] LOG -- hci.c.666: ACL classic buffers: 0 used of 3
    [00:00:35.132] LOG -- hci.c.666: ACL classic buffers: 0 used of 3
    [00:00:35.132] LOG -- hci.c.666: ACL classic buffers: 0 used of 3
    [00:00:35.133] EVT <= 13 05 01 40 00 02 00
    [00:00:35.133] LOG -- hci.c.666: ACL classic buffers: 0 used of 3
    [00:00:35.143] EVT <= 13 05 01 40 00 01 00
    [00:00:35.143] LOG -- hci.c.666: ACL classic buffers: 0 used of 3
    [00:00:35.144] EVT <= 05 04 00 40 00 13
    [00:00:35.144] LOG -- hci.c.1675: state 7, role 1, le_con 1
    [00:00:35.145] LOG -- hci.c.1681: Num LE Peripheral roles: 0 of 1
    Disconnected callback
    [00:00:35.145] LOG -- hci.c.666: ACL classic buffers: 0 used of 3
    gattWriteCallback , value 0
    [00:00:35.145] LOG -- gatt_client.c.1524: GATT Client: HCI_EVENT_DISCONNECTION_COMPLETE
    [00:00:35.145] LOG -- hci.c.1292: Connection closed: handle 0x40, xxxxxx
    [00:00:35.146] LOG -- hci.c.8176: BTSTACK_EVENT_NR_CONNECTIONS_CHANGED 0
    [00:00:35.146] CMD => 0A 20 01 01
    [00:00:35.148] EVT <= 0E 04 01 0A 20 00


    ChatGPT says that the disconnect event (05) has reason 13, which means the watch wanted to disconnect. I could not confirm this information yet.