内容提要:2023年6月14日,树莓派官方发布了对树莓派Pico W无线开发板(简称Pico W)MicroPython蓝牙功能的支持。本文首先介绍Pico W接口信号及蓝牙通信协议,然后通过Pico W接口信号扩展连接一只LED和一个按键,并给出Pico W蓝牙通信MicroPython编程示例。
一、Pico W接口信号
1. Pico W开发板介绍
Pico W是树莓派基金会于2022年6月底推出的搭载无线通信芯片的树莓派Pico开发板,主要技术规格如下:
•工作电压:1.8~5.5V;
•MCU:MCU采用树莓派基金会自研的型号为RP2040的芯片(该芯片于2021年1月随树莓派Pico开发板发布),芯片內部集成了32位双核ARM Cortex-M0+,运行时钟133MHz;
•SRAM大小:264KB;
•Flash存储器容量:2MB(QSPI接口);
•GPIO接口引脚:26个,包括3个模拟输入引脚、16个PWM通道;
•串行通信接口:2个UART、2个SPI控制器和2个I2C控制器;
•USB接口:内置USB 1.1控制器和PHY,支持主控端(host)和设备端(device);
•片内温度传感器:RP2040内置一个片内温度传感器(可用来测量RP2040芯片的温度,以便进行温度补偿或保护),可以通过ADC4读取片内温度传感器的值并转换为摄氏或华氏温度;
•WiFi无线通信功能:2.4GHz 802.11n
•Bluetooth 5.2蓝牙通信功能:2023年2月支持C程序蓝牙开发,2023年6月支持支持MicroPython蓝牙开发;
Pico W搭载英飞凌公司的AIROC CYW43439无线通信芯片,具备2.4GHz WiFi 4(802.11n,支持WPA3)和Bluetooth 5.2(可使用官方2023年2月推出的SDK 1.5编写C蓝牙程序,或使用官方2023年6月以后推出的支持Pico W蓝牙通信功能的MicroPython固件和MicroPython蓝牙库开发MicroPython蓝牙程序),带板载天线。
2.Pico W接口信号
Pico W的外观尺寸和接口信号引脚也跟Pico开发板一样,两侧各有20個接口信号引脚(如图1所示),这些引脚采用邮票孔设计,以方便下游厂商以表面粘着方式将Pico W开发板焊接到产品的主板中。
Pico W接口信号引脚说明如下:
•VSYS:2V~5V电源输入引脚。
•VBUS:从Micro USB接口获得的5V电源输出,可供电给需要5V电源的电子元件。
•3V3:3.3V电源,与Pico W的工作电压相同。
•3V3_EN:使能或禁止电源;使能或禁止Pico W以及3V3引脚的电源输出。
•RUN/RESET:启用或停用Pico∕重置,输入低电平将使Pico W停止运行。
•GP0-GP28:GPIO(通用输入/输出)引脚,板载LED与WL_GPIO0相连。
•ADC0 ~ ADC2:具备模拟输入功能的GPIO引脚,可当作模拟输入或数字输入/输出引脚。
•ADC_VREF:模数转换器(ADC)的参考电压输入。
•GND:模数转换器的接地引脚,与ADC_VREF引脚配合使用。
图1
特别说明的是,Pico W板载(On-board)LED引脚与Pico板载LED引脚接GPIO25不同,在MicroPython中,Pico W板载LED引脚就叫做‘LED’或者‘WL_GPIO0’(均为字符串类型),下面两行典型的MicroPython语句都表示建立控制Pico W板载LED对象:
led = Pin(‘LED’, Pin.OUT)
或
led = Pin(‘WL_GPIO0’, Pin.OUT)
二、低功耗蓝牙(BLE)简介
低功耗蓝牙(Bluetooth Low Energy, 简称BLE)是蓝牙无线通信技术的一种改进变体,其显著特点是省电。 与经典蓝牙不同的是,BLE 在不收发数据时可以保持在休眠状态。 BLE非常适合于使用电池供电的设备,如可穿戴式设备、安全监控设备等。
1.BLE通信拓扑结构
BLE通信拓扑结构如下:
(1)点对点(Point-to-Point):网络中两个结点(设备)之间的通信;服务器-客户机通信。
(2)Mesh网络:使用Mesh网络,多个结点可以相互通信。
(3)广播模式(Broadcast Mode):服务器通过网络广播可供许多设备读取的数据。
2.BLE设备状态机
BLE设备状态机定义了设备通信时的某些状态:
(1)待机状态(Standby state):设备既不发送也不接收数据,开机上电就是该状态。
(2)初始化状态(Initiating state):用于对其他设备发起连接。
(3)广播状态(Advertising state):发送广播数据包,告诉其他设备一些信息,以方便其他设备查找自己或连接自己。当然,并非所有广播设备都是可连接或可扫描的。
(4)连接状态(Connection state):与其他设备连接。
(5)扫描状态(Scanning state):扫描正在进行广播的设备。
(6)同步广播状态(Isochronous broadcasting state):广播同步数据包。
(7)同步状态(Synchronization state):用于周期性广播的数据同步。
BLE设备状态机如图2所示。
图2
从图2可知,一个BLE设备进入连接(Connection)状态时,之前的状态要么是广播(Advertising)状态, 要么是初始化(Initiating)状态。从Initiating到Connection状态的BLE设备就变成BLE主设备。从Advertising到Connection状态的BLE设备就变成BLE从设备。BLE从设备最初处于广播状态,当它接受来自BLE主设备的连接请求时,它就转换到连接状态。
这里将Pico W作为BLE从设备,并通过低功耗蓝牙与 Android 设备(Android智能手机)建立点对点通信。
三、Pico W扩展LED和按键硬件接口电路
本文实践需要的硬件材料如下:
(1)Pico W×1;
(2)Micro-USB数据线×1;
(3)面包板×1;
(4) 470Ω电阻×1;
(5)LED发光二极管×1;
(6)轻触按键×1;
(7)跳线×4。
Pico W扩展一只小功率LED和一个按键的硬件接口电路原理图如图3(a)所示,面包板按线实物图如图3(b)所示。
图3
四、Pico W蓝牙通信MicroPython编程
1.Pico W MicroPython固件下载与安装
首先,在Pico W上安装支持 WiFi 和BLE的Pico W MicroPython UF2 固件文件。我们可从树莓派官网https://www.raspberrypi.com/documentation/microcontrollers/micropython.html或MicroPython官网https://micropython.org/download/RPI_PICO_W/下载支持 WiFi 和BLE最新版本的Pico W MicroPython UF2文件,这里下载MicroPython固件文件名为“RPI_PICO_W-20240105-v1.22.1.uf2”,将其安装到Pico W中(具体安装方法可参见上面的树莓派官网或博主以前在CSDN发布的树莓派Pico/Pico W系列相关博文)。
2. Pico W BLE MicroPython模块
我们需要在Pico W中保存两个 MicroPython 模块,以便实现低功耗蓝牙通信功能。
这里从网站https://datasheets.raspberrypi.com/picow/connecting-to-the-internet-with-pico-w.pdf下载文件名为“connecting-to-the-internet-with-pico-w.pdf”的PDF电子书。
Pico W第1个BLE MicroPython模块见PDF电子书的Page 34-36,模块1命名为“ble_advertising.py”文件,这里使用Thonny IDE MicroPython开发环境将Page 34-36的代码粘贴(需去掉行号)并存储到Pico W中(Thonny使用方法可参考博主以前在CSDN发布的树莓派Pico/Pico W系列相关博文)。
模块1程序清单如下:
# Filename: ble_advertising.py
# Helpers for generating BLE advertising payloads.from micropython import const
import struct
import bluetooth# Advertising payloads are repeated packets of the following form:
# 1 byte data length (N + 1)
# 1 byte type (see constants below)
# N bytes type-specific data_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)# Generate a payload to be passed to gap_advertise(adv_data=...).
def advertising_payload(limited_disc=False, br_edr=False, name=None, services=None, appearance=0):payload = bytearray()def _append(adv_type, value):nonlocal payloadpayload += struct.pack("BB", len(value) + 1, adv_type) + value_append(_ADV_TYPE_FLAGS,