Todo sobre Bluetooth en la Raspberry Pi Pico W

PiCockpit Pico W Bluetooth Título de la imagen

La Fundación Raspberry Pi ha anunciado recientemente Compatibilidad con Bluetooth con el lanzamiento de la versión 1.5.1 del C/C++ SDK con una nueva versión del SDK de C/C++ y de Micropython en Pico W.

¡Y adivina qué! Si tienes un Pico W, no necesitas comprar uno nuevo.

Y si aún no tienes un Pico W, puedes comprar uno aquí.

Ya tenemos un artículo sobre todo lo que necesita saber sobre el Pico W. Además, si eres principiante con el Pico W, puedes consulte este artículo.

Pero aquí cubrimos todo lo que necesita saber sobre Bluetooth en la Raspberry Pi Pico W.

Pico W Fondo

Veamos primero algunas de las especificaciones del Pico W.

El Pico W tiene capacidades inalámbricas gracias al chip inalámbrico CYW43439.

En el corazón de cada Pico W se encuentra el RP2040, que es el primer chip de silicio de Raspberry Pi.

El Infineon CYW43439 es compatible con IEEE 802.11 b/g/n WLAN (Wi-Fi) y Bluetooth 5.2. En el momento del lanzamiento, el firmware y el software solo admitían Wi-Fi.

El CYW43439 admite BLE y una única antena compartida entre Wi-Fi y Bluetooth.

Antenas Raspberry Pi y Pico W

Si observas de cerca el Pico W, te darás cuenta de la antena de PCB en forma de triángulo, similar a la de la Raspberry Pi 4. La Raspberry Pi utiliza una antena integrada con licencia de ABRACON.

Esto significa que no se necesita una antena adicional. La interfaz inalámbrica se conecta mediante SPI al RP2040.

El ficha técnica oficial también sugiere que, para obtener el mejor rendimiento inalámbrico, no coloques ningún metal debajo o cerca de la antena. Sin embargo, añadir metal conectado a tierra a los lados de la antena puede mejorar su ancho de banda.

El LED integrado se controla a través del pin WL_GPIO0 del chip Infineon 43439. En el Pico, el LED estaba conectado al pin GPIO 25.

Además, los pines de depuración SWD fueron movidos hacia el centro de la placa, para crear espacio para la antena del PCB. Puede encontrarlos entre el RP2040 y el CYW43439 y el orden de izquierda a derecha sigue siendo SWCLK, GND, SWDIO.

Con el Pico W, puedes programar en C/C++ y MicroPython.

Bluetooth clásico y BLE

Pico W funciona tanto con Bluetooth Classic como con Bluetooth Low Energy. Bluetooth Classic y Bluetooth Low Energy (BLE) son dos formas diferentes de comunicación entre dispositivos dentro de la especificación Bluetooth.

Bluetooth Classic, también conocido como Bluetooth Basic Rate/Enhanced Data Rate (BR/EDR), es la versión original de Bluetooth. Se diseñó para la transmisión de datos a alta velocidad, el streaming de audio y el emparejamiento de dispositivos. Bluetooth Classic se utiliza habitualmente para aplicaciones como altavoces de audio inalámbricos, teclados, ratones y transferencia de archivos entre dispositivos.

Bluetooth Low Energy (BLE), también conocido como Bluetooth Smart, es una variante de Bluetooth de bajo consumo. BLE se introdujo como parte de la especificación Bluetooth 4.0 y está optimizada para dispositivos de bajo consumo que requieren una batería de larga duración, como rastreadores de fitness, smartwatches, dispositivos de domótica y sensores inalámbricos.

Pico W puede funcionar tanto como dispositivo central como periférico.

Primeros pasos con Bluetooth en el Pico W

Empecemos con un proyecto rápido para asegurarnos de que el Bluetooth funciona correctamente.

Ejecutaremos un programa clásico para que se encienda el LED integrado en el Pico W, pero con Bluetooth.

Para ello, necesitarás un Pico W, un cable micro-USB y una protoboard.

Pico W

PRIMER PASO

Lo primero que necesita es descargar Thonny IDEsi aún no lo tiene.

Thonny es una forma súper fácil de programar MicroPython en el Pico W.

También debe descargar este archivo UF2que es compatible con Wi-Fi y BLE. Cuando lo tengas descargado, mantén pulsado el botón BOOTSEL del Pico W y conéctalo al ordenador por USB. Suelta el botón BOOTSEL después de unos 3 segundos.

Aparecerá una unidad remota llamada "RPI-RP2". Mueva el archivo UF2 a esta unidad.

Entonces la unidad desaparecerá.

SEGUNDO PASO

Ahora puedes desconectar y volver a conectar tu Pico W (esta vez, no mantengas pulsado el botón BOOTSEL).

Abre Thonny.

Imagen de Pico W Bluetooth el IDE de Thonny
Cambia el tema y el tipo de letra para salvar tus ojos.

Después de abrir Thonny, vaya a Herramientas > Opciones > Intérprete y asegúrese de que el intérprete está configurado como Micropython y que el puerto es su Pico W. Aquí tiene un ejemplo:

Puede que su Pico W aparezca con otro nombre.

Una vez hecho esto, haz clic en OK y estarás listo.

Ahora, copia el siguiente código y pégalo en la sección :

from micropython import const
import struct
import bluetooth

_ADV_TYPE_FLAGS = const(0x01)
_ADV_TYPE_NAME = const(0x09)
_ADV_TYPE_UUID16_COMPLETE = const(0x3)
_ADV_TYPE_UUID32_COMPLETE = const(0x5)
_ADV_TYPE_UUID128_COMPLETE = const(0x7)
_ADV_TYPE_UUID16_MORE = const(0x2)
_ADV_TYPE_UUID32_MORE = const(0x4)
_ADV_TYPE_UUID128_MORE = const(0x6)
_ADV_TYPE_APPEARANCE = const(0x19)

def advertising_payload(limited_disc=False, br_edr=False, name=None, services=None, appearance=0):
    payload = bytearray()

    def _append(adv_type, value):
        nonlocal payload
        payload += struct.pack("BB", len(value) + 1, adv_type) + value

    _append(
        _ADV_TYPE_FLAGS,
        struct.pack("B", (0x01 if limited_disc else 0x02) + (0x18 if br_edr else 0x04)),
    )

    if name:
        _append(_ADV_TYPE_NAME, name)

    if services:
        for uuid in services:
            b = bytes(uuid)
            if len(b) == 2:
                _append(_ADV_TYPE_UUID16_COMPLETE, b)
            elif len(b) == 4:
                _append(_ADV_TYPE_UUID32_COMPLETE, b)
            elif len(b) == 16:
                _append(_ADV_TYPE_UUID128_COMPLETE, b)

    if appearance:
        _append(_ADV_TYPE_APPEARANCE, struct.pack("<h", appearance))

    return payload


def decode_field(payload, adv_type):
    i = 0
    result = []
    while i + 1 < len(payload):
        if payload[i + 1] == adv_type:
            result.append(payload[i + 2 : i + payload[i] + 1])
        i += 1 + payload[i]
    return result


def decode_name(payload):
    n = decode_field(payload, _ADV_TYPE_NAME)
    return str(n[0], "utf-8") if n else ""


def decode_services(payload):
    services = []
    for u in decode_field(payload, _ADV_TYPE_UUID16_COMPLETE):
        services.append(bluetooth.UUID(struct.unpack("<h", u)[0]))
    for u in decode_field(payload, _ADV_TYPE_UUID32_COMPLETE):
        services.append(bluetooth.UUID(struct.unpack("<d", u)[0]))
    for u in decode_field(payload, _ADV_TYPE_UUID128_COMPLETE):
        services.append(bluetooth.UUID(u))
    return services


def demo():
    payload = advertising_payload(
        name="micropython",
        services=[bluetooth.UUID(0x181A), bluetooth.UUID("6E400001-B5A3-F393-E0A9-E50E24DCCA9E")],
    )
    print(payload)
    print(decode_name(payload))
    print(decode_services(payload))


if __name__ == "__main__":
    demo()

Guarde ese archivo en el Raspberry Pi Pico W como "ble_advertising.py". Este archivo está diseñado para que el Pico W pueda leer y ser leído por otros dispositivos.

A continuación, abre un nuevo archivo en Thonny y pega en él el siguiente código:

# PiCockpit.com

import bluetooth
import random
import struct
import time
from machine import Pin
from ble_advertising import advertising_payload

from micropython import const

_IRQ_CENTRAL_CONNECT = const(1)
_IRQ_CENTRAL_DISCONNECT = const(2)
_IRQ_GATTS_WRITE = const(3)

_FLAG_READ = const(0x0002)
_FLAG_WRITE_NO_RESPONSE = const(0x0004)
_FLAG_WRITE = const(0x0008)
_FLAG_NOTIFY = const(0x0010)

_UART_UUID = bluetooth.UUID("6E400001-B5A3-F393-E0A9-E50E24DCCA9E")
_UART_TX = (
    bluetooth.UUID("6E400003-B5A3-F393-E0A9-E50E24DCCA9E"),
    _FLAG_READ | _FLAG_NOTIFY,
)
_UART_RX = (
    bluetooth.UUID("6E400002-B5A3-F393-E0A9-E50E24DCCA9E"),
    _FLAG_WRITE | _FLAG_WRITE_NO_RESPONSE,
)
_UART_SERVICE = (
    _UART_UUID,
    (_UART_TX, _UART_RX),
)


class BLESimplePeripheral:
    def __init__(self, ble, name="mpy-uart"):
        self._ble = ble
        self._ble.active(True)
        self._ble.irq(self._irq)
        ((self._handle_tx, self._handle_rx),) = self._ble.gatts_register_services((_UART_SERVICE,))
        self._connections = set()
        self._write_callback = None
        self._payload = advertising_payload(name=name, services=[_UART_UUID])
        self._advertise()

    def _irq(self, event, data):
        if event == _IRQ_CENTRAL_CONNECT:
            conn_handle, _, _ = data
            print("New connection", conn_handle)
            self._connections.add(conn_handle)
        elif event == _IRQ_CENTRAL_DISCONNECT:
            conn_handle, _, _ = data
            print("Disconnected", conn_handle)
            self._connections.remove(conn_handle)
            self._advertise()
        elif event == _IRQ_GATTS_WRITE:
            conn_handle, value_handle = data
            value = self._ble.gatts_read(value_handle)
            if value_handle == self._handle_rx and self._write_callback:
                self._write_callback(value)

    def send(self, data):
        for conn_handle in self._connections:
            self._ble.gatts_notify(conn_handle, self._handle_tx, data)

    def is_connected(self):
        return len(self._connections) > 0

    def _advertise(self, interval_us=500000):
        print("Starting advertising")
        self._ble.gap_advertise(interval_us, adv_data=self._payload)

    def on_write(self, callback):
        self._write_callback = callback


def demo():
    led_onboard = Pin("LED", Pin.OUT)
    ble = bluetooth.BLE()
    p = BLESimplePeripheral(ble)

    def on_rx(v):
        print("RX", v)

    p.on_write(on_rx)

    i = 0
    while True:
        if p.is_connected():
            led_onboard.on()
            for _ in range(3):
                data = str(i) + "_"
                print("TX", data)
                p.send(data)
                i += 1
        time.sleep_ms(100)


if __name__ == "__main__":
    demo()

Ahora, igual que antes, guarda el archivo en el Pico W y, esta vez, puedes llamarlo "led_peripheral.py". Mientras que el archivo de publicidad permite al Pico W comunicarse con otros dispositivos, el archivo de periféricos le permite función como un dispositivo periférico. En este caso, esa función será encender el LED.

Ahora pulse "Ejecutar script actual" en la barra de herramientas de Thonny.

Imagen de Pico W Bluetooth el IDE de Thonny

Como puedes ver en la imagen, la consola mostrará el mensaje "Iniciando publicidad". En este punto, puedes conectarte con un dispositivo Bluetooth como tu teléfono. Busca y empareja con "mpy-uart".

Imagen de las conexiones Bluetooth en un teléfono Android

Una vez emparejados los dos, el LED del Pico W se encenderá y la consola Thonny empezará a contar cuánto tiempo se cuentan los dos:

Imagen de Pico W Bluetooth el IDE de Thonny

¡Enhorabuena! Ya has confirmado que el Bluetooth de tu Pico W funciona y puedes empezar a centrarte en tu próximo proyecto.

Proyectos Pico W Bluetooth

Cuando comience su próximo proyecto para Pico W, puede recurrir a algunos de los proyectos que otros han realizado. Dado que el Pico W acaba de recibir compatibilidad oficial con Bluetooth, están empezando a surgir nuevos proyectos.

He aquí una lista (cada vez mayor) de algunos de los proyectos que han aparecido hasta ahora:

  1. Pico W Bluetooth Mando a distancia
  2. Pico W Bluetooth Robot
  3. Pico W Bluetooth Ratón
  4. Pico W Bluetooth Luces
  5. Pico W USB a Bluetooth Adaptador de audio
  6. Pico W Bluetooth PicoDRO (lectura digital)

PREGUNTAS FRECUENTES

¿Puedo utilizar Bluetooth Classic con el Pico W?

Por supuesto, Pico W es compatible con Bluetooth Classic y BLE.

¿Puedo conectar varios dispositivos al Pico W simultáneamente?

Sí, Pico W puede actuar como dispositivo central y conectarse a varios periféricos Bluetooth simultáneamente. También puede utilizar Bluetooth Classic y BLE simultáneamente. Así que puedes crear sistemas ultracomplejos en los que Pico W se comunique con un montón de sensores o controle varios dispositivos a la vez.

¿Cuál es el alcance Bluetooth del Pico W?

Normalmente, hasta 30 metros en espacios abiertos. Sin embargo, el alcance puede variar en función de factores ambientales como obstáculos, interferencias e intensidad de la señal.

¿Puedo utilizar el Pico W como periférico Bluetooth?

Pico W puede funcionar como dispositivo central o periférico. Así, permite que otros dispositivos centrales Bluetooth (como smartphones, tabletas u ordenadores) se conecten a él. Todo esto funciona a la perfección con PiCockpit¡Por cierto!

¿Cómo programo la funcionalidad Bluetooth en el Pico W?

Puede programar la funcionalidad Bluetooth en el Pico W utilizando el Raspberry Pi Pico SDK versión 1.5.1. El SDK proporciona bibliotecas y ejemplos específicos para el desarrollo de Bluetooth. Le permite implementar servicios Bluetooth, características y manejar protocolos de comunicación.

¿Cuáles son los requisitos de alimentación para Bluetooth en el Pico W?

Bluetooth está diseñado para ahorrar energía. Por tanto, Pico W consume un mínimo de energía durante los periodos de inactividad y puedes optimizar aún más tu código utilizando técnicas como los modos de suspensión y los estados de bajo consumo. Obviamente, los requisitos específicos de consumo dependen de la aplicación y del escenario de uso.

12 Comentarios

  1. Marcos Gutierrez el agosto 4, 2023 a las 1:13 am

    Hola puedo adaptar la pico w a scoppy osciloscopy.agrdeceria su respuesta y como lo haria

  2. Electronikmx el agosto 17, 2023 a las 12:16 am

    Después de unos segundos el dispositivo indica un error y se desconecta al querer vincularlo

    • Adam el agosto 17, 2023 a las 6:51 am

      ¿En qué momento?

      • Electronikmx el agosto 17, 2023 a las 4:19 pm

        Como comentaba, al momento de darle en el móvil a "vincular" en solicitud de enlace por medio de bluetooth observo que sí, RPI pico W envía una serie de números propios del programa en la tarjeta "TX 1_, TX 2_ ..." , sin embargo después de varios segundos el celular o tablet (lo intenté con 3 dispositivos) me indica que hubo un error al intentar vincular y se desconecta el bluetooth del móvil aparece el mensaje "Disconected 64", y bajo esa línea nuevamente aparece "Starting advertising" y tengo que darle en conectar de nuevo.

        • Javier el octubre 5, 2023 a las 11:08 pm

          Me pasa lo mismo

  3. Alex el octubre 2, 2023 a las 8:00 am

    ¿Se puede tener una conexión wifi abierta al mismo tiempo que una conexión bluetooth en la pi pico W? Si no, ¿puedes cambiar entre ellas en tiempo real?

  4. Javier el octubre 5, 2023 a las 11:10 pm

    Me pasa lo mismo.... ya lo intenté de varios dispositivos y aplicaciones. No funcionó.

  5. Peter el noviembre 12, 2023 a las 11:33 am

    ¿Cómo configurar el controlador kitronik mini Pico para emparejarlo con la placa robótica kitronik Pico y controlarla?

  6. Brian el noviembre 27, 2023 a las 12:27 am

    Hola. He seguido tus instrucciones pero no encuentro el mpy-uart en mi iPhone en Bluetooth.

    Tengo un Pico W conectado por USB a mi ordenador.
    He flasheado tu UF2
    He copiado su código y guardar los archivos como se nombra en el pico W a través de Thonny
    Estoy ejecutando Thonny y la esquina inferior derecha es la fábrica llamada MicroPython (Raspberry Pi Pico) {dot. como hay rondando punto} Junta CDC @ COM3
    Ejecuto led_peripheral.py
    El intérprete de comandos emite "Starting advertising"
    No se puede ver en el iPhone

    ¿Alguna idea?

    Gracias por contribuir a la causa.

    • Anant el marzo 19, 2024 a las 2:31 pm

      Hola, tengo el mismo problema. ¿Fuiste capaz de resolver esto?

    • Steve el octubre 23, 2024 a las 9:32 pm

      Hola no se puede emparejar a través de iPhone, pero descarga microblue aplicación desde snappyxo.io y se puede conectar a pico.

  7. Paul B. el febrero 22, 2024 a las 3:04 pm

    En lugar de enlace BT con un teléfono, tengo un módulo GPS Arduino que transmite sus coordenadas a través de Bluetooth, ¿hay una manera de emparejar y leer esa señal con un Pico W?

Deja un comentario