1. 项目背景与核心需求
去年帮朋友公司做智能箱包方案时,发现市面上大多数防丢器要么续航差,要么连接不稳定。于是决定自己动手开发一款基于BLE蓝牙的低功耗防丢器,核心指标要求:待机半年以上、20米稳定连接、支持双向查找。这个方案最终实测待机时间达到8个月,成本控制在30元以内。
防丢器这类产品看似简单,实际涉及射频电路设计、低功耗编程、移动端开发等多个技术领域的交叉。我选择STM32WB55作为主控,这颗芯片内置双核Cortex-M4/M0+和蓝牙5.0射频模块,特别适合需要长续航的蓝牙设备开发。
2. 硬件设计关键点
2.1 主控选型与电路设计
对比过nRF52系列和TI的CC2640后,最终选择STM32WB55主要基于三点考虑:
- 内置巴伦电路,射频部分外围元件少
- 双核架构方便实现功耗隔离
- 开发工具链成熟,有现成的BLE协议栈
原理图设计时特别注意了这些细节:
- 天线部分采用倒F型PCB天线,预留π型匹配网络
- 电源路径上串联10Ω电阻配合示波器测电流
- 预留SWD调试接口和串口测试点
重要提示:蓝牙射频电路对阻抗匹配极其敏感,建议做好以下准备:
- 至少打样3版不同天线长度的PCB
- 准备网络分析仪做阻抗调校
- 购买标准蓝牙测试板作为参照
2.2 低功耗实现方案
实测发现影响续航的主要因素有:
- 广播间隔设置
- 连接事件周期
- 唤醒源配置
我的优化方案:
c复制// 广播参数配置(单位0.625ms)
#define ADV_INTERVAL 1600 // 1秒间隔
#define ADV_TIMEOUT 0 // 持续广播
// 连接参数(从设备延迟)
#define CONN_INTERVAL_MIN 160 // 100ms
#define CONN_INTERVAL_MAX 160
#define CONN_LATENCY 4
#define SUPERVISION_TIMEOUT 600 // 6秒
配合硬件上的措施:
- 所有GPIO初始状态设为模拟输入
- 移除调试用的LDO改用直接供电
- 添加MOS管控制外围电路电源
3. 固件开发实战
3.1 BLE服务设计
自定义了两个服务:
-
防丢报警服务(UUID: 0xAF00)
- 特征1:连接强度阈值(可写)
- 特征2:报警开关(可写带通知)
-
设备信息服务(标准UUID)
- 电池电量(通知)
- 固件版本(只读)
服务注册代码示例:
c复制static const struct svc_def services[] = {
{ // 防丢服务
.uuid = {0x00,0xAF},
.chars = {
{.uuid={0x01,0xAF}, .props=WRITE, .max_len=1}, // 阈值
{.uuid={0x02,0xAF}, .props=NOTIFY|WRITE}, // 报警开关
{0}
}
},
{0}
};
3.2 功耗优化技巧
通过STM32CubeMonitor实测发现几个耗电大户:
- 未使用的GPIO浮空:每个引脚约0.5μA
- 调试接口未禁用:整体多耗电20μA
- 广播数据过长:每字节增加约0.3μA
最终采用的解决方案:
- 在HAL_Init()后立即调用__HAL_RCC_DBGMCU_CLK_DISABLE()
- 所有未用GPIO配置为模拟输入
- 广播数据精简到12字节(含设备名和电量)
4. 手机APP开发要点
4.1 Android端核心实现
使用Android Studio开发,关键类说明:
java复制public class BleScanner {
private BluetoothLeScanner scanner;
private ScanSettings settings;
void startScan() {
settings = new ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
.setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES)
.build();
List<ScanFilter> filters = new ArrayList<>();
filters.add(new ScanFilter.Builder()
.setServiceUuid(ParcelUuid.fromString("0000af00-..."))
.build());
scanner.startScan(filters, settings, scanCallback);
}
}
连接管理特别注意:
- 每次扫描不超过5秒
- 发现设备后立即停止扫描
- 使用Handler延时队列管理重连
4.2 iOS端特殊处理
iOS平台需要特别注意:
- 后台模式需声明bluetooth-central
- 扫描时需指定serviceUUIDs
- 状态恢复需要实现restoreIdentifier
Swift示例:
swift复制let options: [String: Any] = [
CBCentralManagerOptionRestoreIdentifierKey: "myAppRestoreId",
CBConnectPeripheralOptionNotifyOnDisconnectionKey: true
]
centralManager = CBCentralManager(
delegate: self,
queue: nil,
options: options)
5. 实测数据与优化记录
5.1 功耗测试对比
| 配置项 | 电流(μA) | 改进措施 |
|---|---|---|
| 默认广播 | 28.5 | 优化广播间隔 |
| 全功能运行 | 156.2 | 禁用未用外设 |
| 深度睡眠 | 1.8 | 优化IO状态 |
| 最终方案 | 9.4 | 综合所有优化 |
按照CR2032电池容量220mAh计算:
理论续航 = 220000 / 9.4 / 24 ≈ 975天(实际考虑自放电约8个月)
5.2 常见问题排查
-
连接频繁断开
- 检查CONN_INTERVAL是否过小
- 确认射频匹配网络参数
- 测试环境是否有2.4G干扰
-
手机搜索不到设备
- 确认广播数据未超过31字节
- 检查天线阻抗是否50Ω
- 验证TX功率设置(建议+4dBm)
-
距离短于预期
- 用频谱仪检查谐波干扰
- 尝试降低广播频率
- 检查PCB天线周围是否有金属
6. 生产注意事项
小批量生产时踩过的坑:
-
不同批次CR2032电池电压曲线差异
- 解决方案:在代码中添加电压校准功能
-
塑胶外壳对信号的影响
- 实测数据:ABS外壳衰减约3dB
- 应对措施:预留+8dBm的发射功率余量
-
FCC认证要点
- 必须测试的项:传导辐射、谐波、频偏
- 建议预留2个月认证周期
- 天线效率需大于30%
这个项目最让我意外的是,优化后的PCB天线性能竟然比某些外接天线还要好。在空旷场地实测距离达到38米,远超最初的20米设计目标。关键点在于:
- 天线周围净空区严格保持5mm以上
- 匹配网络用0Ω电阻+焊盘,方便调试
- 最终用网分校准到50.2Ω阻抗