Bluefruit SPI Friend as HID Device with Rapsberry Pi Pico

For CircuitPython issues, ask in the Adafruit CircuitPython forum.

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
User avatar
AngryChihuahua04
 
Posts: 27
Joined: Mon Aug 19, 2019 6:26 pm

Bluefruit SPI Friend as HID Device with Rapsberry Pi Pico

Post by AngryChihuahua04 »

Hello to all! I am semi-new to the world of coding and electronics as I have some experience with normal Raspberry Pi boards, but new to microcontroller boards such as the Pico. I am also very new to Bluetooth commands and protocol, so please forgive me for any errors in the code. I am currently working on a project that uses the Pico with the Adafruit Bluefruit SPI Friend. The main purpose is to have some buttons connected to the Pico and to broadcast the HID commands such as VOLUME+ and VOLUME- from the Pico to a connected device. I have it wired up to the Pico as shown in the picture below.
Picture of the wired up Pico
Picture of the wired up Pico
resized pico.jpg (452.64 KiB) Viewed 513 times
I am able to successfully power the board and broadcast a new name for the Bluetooth module. However, the error I am running into is when I use the AT+BLEKEYBOARDEN=1 command. When this command is run, the console gets an error that says "RuntimeError ('Timed out waiting for a response.',) If this command is omitted, my device can connect to it just fine. Any suggestions on how to fix this?

Code: Select all

import board
import busio
import digitalio
from adafruit_bluefruitspi import BluefruitSPI
import time

spi_bus = busio.SPI(clock=board.GP2, MOSI=board.GP3, MISO=board.GP4)
cs = digitalio.DigitalInOut(board.GP5)
irq = digitalio.DigitalInOut(board.GP6)
rst = digitalio.DigitalInOut(board.GP1)
bluefruit = BluefruitSPI(spi_bus, cs, irq, rst, debug=False)

connected = None

print("Initializing Bluetooth module")
bluefruit.init()
bluefruit.command_check_OK(b"AT+FACTORYRESET", delay=1)

#Print Bluetooth Module Info
print(str(bluefruit.command_check_OK(b"ATI"), "utf-8"))

bluefruit.command_check_OK(b"AT+GAPDEVNAME=Glasses")
bluefruit.command_check_OK(b"AT+BLEPOWERLEVEL=0")

#Main Loop
while True:
    try:
        print("Waiting for a connection to Bluefruit LE Connect ...")
        # Wait for a connection ...
        dotcount = 0
        while not bluefruit.connected:
            print(".", end="")
            dotcount = (dotcount + 1) % 80
            if dotcount == 79:
                print("")
            time.sleep(0.5)

        connected = bluefruit.connected
        print("Connected to Glasses!")

        connection_timestamp = time.monotonic()
        while True:
            # Check our connection status every 3 seconds
            if time.monotonic() - connection_timestamp > 3:
                connection_timestamp = time.monotonic()
                if not bluefruit.connected:
                    break

            bluefruit.command_check_OK(b"AT+BLEKEYBOARDEN=1")
            bluefruit.command_check_OK(b"ATZ")
            
    except RuntimeError as e:
        print(e)
        continue
Any help is appreciated!

User avatar
adafruit2
 
Posts: 22148
Joined: Fri Mar 11, 2005 7:36 pm

Re: Bluefruit SPI Friend as HID Device with Rapsberry Pi Pic

Post by adafruit2 »

hmm we really dont recommend this technique anymore, but it sounds like its mostly working. did you try upgrading the module BLE firmware via the app?

User avatar
AngryChihuahua04
 
Posts: 27
Joined: Mon Aug 19, 2019 6:26 pm

Re: Bluefruit SPI Friend as HID Device with Rapsberry Pi Pic

Post by AngryChihuahua04 »

adafruit2 wrote:hmm we really dont recommend this technique anymore, but it sounds like its mostly working. did you try upgrading the module BLE firmware via the app?
I just upgraded the BLE firmware to the latest version. It updated successfully, however the same issue still persists. It prints the runtime error and the module disconnects (The blue LED turns off and goes back to flashing red). What is the recommended way to do this now? I based my code off of the examples in the GitHub repository for the SPI friend.

User avatar
adafruit2
 
Posts: 22148
Joined: Fri Mar 11, 2005 7:36 pm

Re: Bluefruit SPI Friend as HID Device with Rapsberry Pi Pic

Post by adafruit2 »

hmm not sure - you could try it in arduino?

User avatar
AngryChihuahua04
 
Posts: 27
Joined: Mon Aug 19, 2019 6:26 pm

Re: Bluefruit SPI Friend as HID Device with Rapsberry Pi Pic

Post by AngryChihuahua04 »

adafruit2 wrote:hmm not sure - you could try it in arduino?
I cannot because I don't have an Arduino capable board available and the Pico is not Arduino compatible. Sorry for the inconvenience. Do you have any suggestions for making this work with CircuitPython?

User avatar
adafruit2
 
Posts: 22148
Joined: Fri Mar 11, 2005 7:36 pm

Re: Bluefruit SPI Friend as HID Device with Rapsberry Pi Pic

Post by adafruit2 »

nope, it ought to work but we haven't tested it in a long time.

User avatar
ChliHug
 
Posts: 42
Joined: Sun Feb 16, 2020 4:54 pm

Re: Bluefruit SPI Friend as HID Device with Rapsberry Pi Pic

Post by ChliHug »

AngryChihuahua04 wrote:Any suggestions on how to fix this?
First off, I have used the Bluefruit SPI Friend only a few times and am new to Python. The wiring in the picture looks correct for the selected pins in your code.

Not exactly sure why you get a timeout, but when a device connects, your code sets BLEKEYBOARDEN to 1 and resets the Bluefruit immediately. You only need to set BLEKEYBOARDEN once. The Bluefruit will stay in this mode until you set it to 0 and reset it. You may need to give it a few milliseconds before you interact with it again after a reset. That might actually explain why it times out. The Pico wants to immediately talk to it again, but it isn't ready yet and then the Pico just gives up.

I tested this code with my Pico and Bluefruit SPI Friend and I got it working with Android, iOS, and Windows 10. (Note that I use different pins.)

Code: Select all

import board
import busio
import digitalio
from adafruit_bluefruitspi import BluefruitSPI
import time

spi_bus = busio.SPI(clock=board.GP2, MOSI=board.GP3, MISO=board.GP4)
cs = digitalio.DigitalInOut(board.GP6)
irq = digitalio.DigitalInOut(board.GP7)
rst = digitalio.DigitalInOut(board.GP8)

while True:
    bluefruit = BluefruitSPI(spi_bus, cs, irq, rst, debug=False)
    while True:
        try:
            print("Initializing Bluetooth module")
            bluefruit.init()

            print("Checking information")
            print(str(bluefruit.command_check_OK(b"ATI"), "utf-8"))

            devname = bluefruit.command_check_OK(b"AT+GAPDEVNAME?")
            keyen = bluefruit.command_check_OK(b"AT+BLEKEYBOARDEN?")
            print("Device name:", devname)
            if devname != b'Glasses\r\n' or keyen == b'0\r\n':
                print("Devname not as expected. Setting device up as keyboard.")
                bluefruit.command_check_OK(b"AT+FACTORYRESET", delay=1)
                bluefruit.command_check_OK(b"AT+BLEKEYBOARDEN=1")
                bluefruit.command_check_OK(b"AT+GAPDEVNAME=Glasses")
                bluefruit.command_check_OK(b"ATZ")
                time.sleep(1)
                print("Reset complete.")
                break

            bluefruit.command_check_OK(b"AT+BLEPOWERLEVEL=0")

            print("Waiting for a connection to Bluefruit LE Connect ...")
            # Wait for a connection ...
            dotcount = 0
            while not bluefruit.connected:
                print(".", end="")
                dotcount = (dotcount + 1) % 80
                if dotcount == 79:
                    print("")
                time.sleep(0.5)

            print("\nConnected to Glasses!")

            volume_cmd = b"AT+BLEHIDCONTROLKEY=VOLUME"
            connection_timestamp = time.monotonic()
            volume_timestamp = time.monotonic() + 0.75
            volume_counter = 0
            while True:
                # Check our connection status every 3 seconds
                now = time.monotonic()
                if now - connection_timestamp > 3:
                    connection_timestamp = now
                    if not bluefruit.connected:
                        print("Device disconnected.")
                        break

                # Every 750 ms: Increase volume for three times, then decrease
                # it again, then pause for a short moment.
                if volume_timestamp < now:
                    volume_timestamp = now + 0.75
                    volume_counter += 1
                    volume_step = volume_counter % 10
                    if volume_step < 3:
                        print("Volume up:", bluefruit.command(volume_cmd + "+"))
                    elif volume_step > 3 and volume_step < 7:
                        print("Volume down:", bluefruit.command(volume_cmd + "-"))

        except RuntimeError as e:
            print(e)
            break
If something looks weird, it's probably because I don't know enough about Python.

Locked
Please be positive and constructive with your questions and comments.

Return to “Wireless: WiFi and Bluetooth”