蓝牙模组产品概览
BLE 技术基础
BLE(Bluetooth Low Energy,低功耗蓝牙)是蓝牙 4.0 引入的低功耗版本,专为 IoT 设计。
BLE vs 经典蓝牙
| 特性 | 经典蓝牙(BR/EDR) | BLE |
|---|---|---|
| 速率 | 1-3Mbps | 125kbps-2Mbps |
| 功耗 | 高(1W) | 极低(1mW) |
| 延迟 | 100ms | 6ms |
| 覆盖 | 10-100m | 10-400m |
| 主要用途 | 音频、文件传输 | IoT 传感器、可穿戴 |
| 配对时间 | 慢(秒级) | 快(毫秒级) |
BLE 5.x 新特性
| 版本 | 新增特性 | 关键改进 |
|---|---|---|
| BLE 5.0 | 2× 速率、4× 覆盖、8× 广播容量 | 长距离模式(125kbps,+20dB) |
| BLE 5.1 | 方向查找(AoA/AoD) | 厘米级室内定位 |
| BLE 5.2 | LE Audio、EATT | 低功耗音频、多流传输 |
| BLE 5.3 | 增强连接更新 | 更低功耗 |
| BLE 5.4 | 广播加密 | 安全性提升 |
移远 BLE 产品
移远的 BLE 模组主要以组合形式出现(BLE + 蜂窝 或 BLE + Wi-Fi):
| 型号 | BLE 版本 | 组合 | 芯片 | 特点 |
|---|---|---|---|---|
| BG95-Mini | BLE 5.0 | NB-IoT + Cat.M + BLE | 高通 | 超小尺寸 |
| BC660K | BLE 5.0 | NB-IoT + BLE | 高通 | 低功耗 |
| FC41D | BLE 5.0 | Wi-Fi 6 + BLE | 联发科 | 高速组合 |
BLE 协议栈
GATT 架构
GATT(Generic Attribute Profile)是 BLE 数据交换的核心:
Profile(配置文件)
└── Service(服务)
└── Characteristic(特征值)
├── Value(值)
├── Descriptor(描述符)
└── Properties(属性:Read/Write/Notify/Indicate)
示例:心率服务(Heart Rate Service)
Service UUID: 0x180D
Characteristic: Heart Rate Measurement(0x2A37)
Properties: Notify
Value: [心率值, RR间期...]
Characteristic: Body Sensor Location(0x2A38)
Properties: Read
Value: [位置:手腕/胸部/手指...]BLE 广播(Advertising)
BLE 广播用于设备发现和数据广播(无需连接):
广播类型:
ADV_IND:可连接无向广播(最常用)
ADV_NONCONN_IND:不可连接广播(Beacon)
ADV_DIRECT_IND:可连接定向广播
广播数据格式(AD Structure):
Length | Type | Data
常用 Type:
0x01:Flags(LE General Discoverable Mode)
0x02/0x03:16位 UUID 列表
0x08/0x09:设备名称(缩写/完整)
0xFF:厂商自定义数据(iBeacon 使用此类型)
iBeacon 数据格式:
公司标识:0x004C(Apple)
类型:0x02
长度:0x15
UUID:16字节
Major:2字节
Minor:2字节
TX Power:1字节(用于距离估算)BLE 开发示例
Python BLE 扫描(树莓派/Linux)
python
import asyncio
from bleak import BleakScanner, BleakClient
async def scan_devices():
"""扫描附近 BLE 设备"""
print("扫描 BLE 设备...")
devices = await BleakScanner.discover(timeout=5.0)
for device in devices:
print(f"设备: {device.name or '未知'}")
print(f" 地址: {device.address}")
print(f" RSSI: {device.rssi} dBm")
print(f" 距离估算: {estimate_distance(device.rssi):.1f} m")
print()
def estimate_distance(rssi, tx_power=-59, n=2.0):
"""基于 RSSI 估算距离(粗略)"""
if rssi == 0:
return -1
ratio = rssi / tx_power
if ratio < 1.0:
return ratio ** 10
else:
return 0.89976 * (ratio ** 7.7095) + 0.111
async def read_heart_rate(device_address):
"""读取心率设备数据"""
HEART_RATE_SERVICE = "0000180d-0000-1000-8000-00805f9b34fb"
HEART_RATE_CHAR = "00002a37-0000-1000-8000-00805f9b34fb"
async with BleakClient(device_address) as client:
print(f"已连接: {device_address}")
# 读取设备信息
services = await client.get_services()
# 订阅心率通知
def heart_rate_handler(sender, data):
# 解析心率数据
flags = data[0]
if flags & 0x01: # 16位心率值
heart_rate = int.from_bytes(data[1:3], 'little')
else: # 8位心率值
heart_rate = data[1]
print(f"心率: {heart_rate} bpm")
await client.start_notify(HEART_RATE_CHAR, heart_rate_handler)
await asyncio.sleep(30) # 监听30秒
await client.stop_notify(HEART_RATE_CHAR)
asyncio.run(scan_devices())Android BLE 开发
java
// Android BLE 扫描和连接
public class BLEManager {
private BluetoothAdapter bluetoothAdapter;
private BluetoothLeScanner scanner;
private BluetoothGatt gatt;
// 扫描回调
private ScanCallback scanCallback = new ScanCallback() {
@Override
public void onScanResult(int callbackType, ScanResult result) {
BluetoothDevice device = result.getDevice();
int rssi = result.getRssi();
Log.d("BLE", "Found: " + device.getName() +
" (" + device.getAddress() + ") RSSI: " + rssi);
// 找到目标设备后连接
if ("MyDevice".equals(device.getName())) {
scanner.stopScan(scanCallback);
connectToDevice(device);
}
}
};
public void startScan() {
ScanSettings settings = new ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
.build();
scanner.startScan(null, settings, scanCallback);
}
private void connectToDevice(BluetoothDevice device) {
gatt = device.connectGatt(context, false, new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt,
int status, int newState) {
if (newState == BluetoothProfile.STATE_CONNECTED) {
Log.d("BLE", "Connected!");
gatt.discoverServices();
}
}
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
// 获取心率服务
BluetoothGattService hrService = gatt.getService(
UUID.fromString("0000180d-0000-1000-8000-00805f9b34fb")
);
if (hrService != null) {
BluetoothGattCharacteristic hrChar = hrService.getCharacteristic(
UUID.fromString("00002a37-0000-1000-8000-00805f9b34fb")
);
// 开启通知
gatt.setCharacteristicNotification(hrChar, true);
}
}
@Override
public void onCharacteristicChanged(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic) {
byte[] data = characteristic.getValue();
int heartRate = data[1] & 0xFF;
Log.d("BLE", "Heart Rate: " + heartRate + " bpm");
}
});
}
}