0

Bluefruit SPI Friend as HID Device with Rapsberry Pi Pico
Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.

Bluefruit SPI Friend as HID Device with Rapsberry Pi Pico

by AngryChihuahua04 on Fri Feb 26, 2021 9:05 pm

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.
resized pico.jpg
Picture of the wired up Pico
resized pico.jpg (452.64 KiB) Viewed 364 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 | TOGGLE FULL SIZE
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!

AngryChihuahua04
 
Posts: 20
Joined: Mon Aug 19, 2019 6:26 pm

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

by adafruit2 on Wed Apr 07, 2021 1:35 pm

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?

adafruit2
Site Admin
 
Posts: 20055
Joined: Fri Mar 11, 2005 7:36 pm

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

by AngryChihuahua04 on Thu May 13, 2021 11:29 am

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.

AngryChihuahua04
 
Posts: 20
Joined: Mon Aug 19, 2019 6:26 pm

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

by adafruit2 on Thu May 13, 2021 11:44 am

hmm not sure - you could try it in arduino?

adafruit2
Site Admin
 
Posts: 20055
Joined: Fri Mar 11, 2005 7:36 pm

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

by AngryChihuahua04 on Thu May 13, 2021 12:51 pm

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?

AngryChihuahua04
 
Posts: 20
Joined: Mon Aug 19, 2019 6:26 pm

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

by adafruit2 on Thu May 13, 2021 1:00 pm

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

adafruit2
Site Admin
 
Posts: 20055
Joined: Fri Mar 11, 2005 7:36 pm

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

by ChliHug on Fri May 14, 2021 6:23 pm

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 | TOGGLE FULL SIZE
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.

ChliHug
 
Posts: 41
Joined: Sun Feb 16, 2020 4:54 pm

Please be positive and constructive with your questions and comments.