1. 项目概述:为什么低功耗WiFi连接是物联网的“命门”
如果你玩过树莓派Pico或者类似的微控制器,大概率会碰到一个头疼的问题:想让它连上WiFi发个数据,结果发现它像个“电老虎”,几节新电池没几天就耗光了。这几乎是所有电池供电物联网(IoT)项目从“玩具”迈向“实用”的第一道坎。传统的ESP8266/ESP32模块虽然集成度高,但在需要设备常年待机、仅偶尔上报数据的场景下,其待机功耗依然不够理想。
这个项目的核心,就是解决这个痛点。它展示的不仅仅是如何让Pico连上WiFi,而是一套完整的超低功耗系统设计思路。我们不再让微控制器本身去维持一个高功耗的WiFi连接,而是引入了一个“外援”——Cricket WiFi模块。Pico作为主控,平时深度休眠,只在需要的时候(比如每5分钟)醒来,干两件事:闪一下LED(代表执行了某个传感器读数或逻辑判断),然后给Cricket模块发一个“起床干活”的信号。Cricket模块平时完全断电,只有收到这个信号时才上电、连WiFi、发送数据,然后迅速关机。这样一来,WiFi这个耗电大户绝大部分时间都处于“离线”状态,整体系统的平均电流可以降到微安级别,从而实现用普通AAA电池供电数月甚至数年的目标。
这套方案的价值在于其普适性。无论你是想做一个门窗开关传感器、一个温湿度记录仪,还是一个低功耗的定位器,其核心架构都是相通的:主控MCU负责低频次、低功耗的本地计算与逻辑判断,专用通信模块负责按需启动、完成高功耗的网络通信任务。通过Python和简单的硬件连接,我们就能搭建出这个架构的原型,为更复杂的项目打下坚实基础。
2. 核心思路与方案选型解析
2.1 功耗瓶颈分析与架构拆解
要理解为什么选择Pico + Cricket的组合,我们先得看看功耗都花在哪了。
一个典型的、由单一MCU(如ESP32)实现的物联网节点,其工作周期通常包含:休眠(微安级)-> 唤醒(毫安级)-> 连接WiFi(峰值可达上百毫安)-> 发送数据(数十毫安)-> 再次休眠。其中,连接WiFi是功耗最高的阶段,尤其是搜索和握手过程,耗时且电流大。即使使用深度睡眠,每次唤醒都需要重新经历完整的网络连接流程,对于数分钟甚至数小时才上报一次数据的设备来说,这个过程的能耗占比过高,效率低下。
因此,一个更优的架构是将计算与通信分离:
- 计算单元(树莓派Pico):负责执行核心业务逻辑,如读取传感器、进行简单判断或数据预处理。它的优势是编程简单(MicroPython)、接口丰富(GPIO, I2C, SPI, UART),且在休眠时功耗极低(可低于100µA)。
- 通信单元(Cricket模块):一个专为超低功耗优化的WiFi“触发器”。它内部集成了完整的TCP/IP协议栈和射频电路,但设计为仅在收到外部唤醒信号(一个GPIO高电平)时才启动。启动后,它会根据预先配置好的参数(目标URL、数据载荷)自动完成连接和发送,任务结束后立即彻底断电。
这种“按需唤醒通信模块”的模式,使得WiFi连接的时间被压缩到最短(通常仅1-2秒),从而将系统的平均功耗降低了一个数量级以上。
2.2 为什么是树莓派Pico和Cricket模块?
树莓派Pico的选择理由:
- 极低的静态功耗:RP2040芯片在休眠模式下功耗表现优秀,适合电池供电场景。
- 丰富的生态与易用性:MicroPython让开发变得异常简单,无需复杂的编译环境,串口直接写代码,对新手和快速原型开发极其友好。
- 充足且灵活的IO:大量的GPIO口可以连接各种传感器,为项目扩展预留了空间。
- 成本与可获得性:价格低廉,全球货源充足,是入门和原型设计的理想选择。
Cricket模块的选择理由:
- 真正的零待机功耗:模块在不被唤醒时,物理上处于断电状态,电流为零。这是它与许多宣称“低功耗”的WiFi模块最本质的区别。
- 配置即用,无需编程:通过Web界面进行配置(目标服务器、数据格式等),模块固件已经封装了完整的HTTP/MQTT客户端功能。这意味着你不需要在Pico上编写复杂的网络协议栈代码,Pico只需要发出一个简单的GPIO信号。
- 简化系统复杂度:将复杂的、与网络稳定性相关的处理(如重连机制)交给专用模块,让Pico的程序保持简单、健壮,更专注于业务逻辑。
备选方案与对比:
- ESP8266/ESP32独立工作:优点是单芯片方案更紧凑。缺点是需要自己实现深度睡眠和WiFi管理,整体功耗优化有上限,且开发复杂度稍高。
- Pico + ESP-01(AT指令模式):这是一个廉价的替代方案。你可以将ESP-01设置为Station模式,通过Pico的UART发送AT指令控制其连接和发送。但ESP-01的深度睡眠功耗仍在70µA左右,且需要Pico在大部分时间保持唤醒以通过串口控制它,整体功耗优化不如Cricket彻底。
- LoRa/NB-IoT等低功耗广域网模块:适用于传输距离远、数据量极小的场景,但需要额外的网关或蜂窝网络支持,初始成本和复杂度较高。
对于大多数需要WiFi覆盖、数据量不大、但对电池寿命有高要求的室内IoT项目(如家居传感器),Pico+Cricket的组合在功耗、开发难度和成本之间取得了很好的平衡。
3. 硬件准备与连接详解
3.1 物料清单与功能说明
除了原文提到的,这里补充一些选型细节和备选方案:
- 树莓派Pico:建议选择不带焊接排针的版本,这样你可以根据项目外壳自由选择焊接排针或直接焊接导线,使成品更紧凑。
- Cricket WiFi模块:确认你拿到的是3.3V工作电压的版本。它通常有多个引脚,本项目核心只用到了三个:
VCC、GND和WAKE_UP。 - 电池盒与电池:2xAAA电池盒(3V)是可行的,但AAA电池容量有限(约1000mAh)。对于需要更长时间续航的原型,我强烈建议考虑:
- 3.7V锂聚合物电池:搭配一个微型3.3V稳压模块(如AMS1117-3.3)。单节2000mAh的锂电池可以提供数倍于AAA电池的容量,且体积更小。
- CR2032纽扣电池座:对于电流极小的最终产品,可以考虑使用纽扣电池,但需要确保Pico在休眠时的电流足够低(可能需要禁用一些外设)。
- 连接线:杜邦线(公对公)用于原型连接很方便。对于更稳固的测试,可以使用鳄鱼夹测试线。最终产品当然建议焊接。
- 可选:电平转换器:虽然Pico和Cricket都是3.3V逻辑,理论上可以直接连接,但为了确保唤醒信号的绝对可靠,尤其是在电池电压下降时,可以在Pico的GPIO15和Cricket的WAKE_UP引脚之间串联一个1k-10kΩ的电阻,起到限流保护作用。这不是必须的,但属于“好习惯”。
3.2 电路连接原理图与实操要点
正确的连接是成功的一半。下面是一个清晰的连接表格:
| 元件 | 引脚/接口 | 连接到 | 说明 |
|---|---|---|---|
| 电池盒 (3V) | 正极 (VCC) | Pico的VSYS引脚 | 为Pico主板供电。切勿接3.3V引脚,那是输出引脚。 |
| 电池盒 (3V) | 负极 (GND) | Pico的任意GND引脚 | 电源地。 |
| 电池盒 (3V) | 正极 (VCC) | Cricket模块的VCC引脚 | 为Cricket模块供电。关键点:独立供电。 |
| 电池盒 (3V) | 负极 (GND) | Cricket模块的GND引脚 | 电源地。同时,需要用一根线将Cricket的GND与Pico的GND连接起来,确保两者共地,否则唤醒信号无法识别。 |
| 树莓派Pico | GP15(物理引脚20) | Cricket模块的WAKE_UP引脚 | Pico控制Cricket唤醒的信号线。 |
| 树莓派Pico | GP25(板载LED) | - | 内部连接,用于状态指示。 |
重要提示:共地操作。这是硬件连接中最容易出错的一步。Pico和Cricket虽然使用同一组电池供电,但它们的GND必须用导线直接连接在一起,形成一个共同的参考零电位点。否则,Pico的GPIO15输出的高电平(3.3V),在Cricket看来可能不是有效的“高电平”,导致无法唤醒。最简单的做法:用一根导线,将Pico的GND引脚和Cricket的GND引脚焊接或插接在一起。
连接检查清单:
- [ ] Pico的
VSYS和GND已接电池。 - [ ] Cricket的
VCC和GND已接电池(与Pico并联)。 - [ ] Pico的
GND和 Cricket的GND已用导线相连(共地)。 - [ ] Pico的
GP15已连接至Cricket的WAKE_UP。 - [ ] 所有连接牢固,无短路风险(特别是正负极不要碰在一起)。
4. 软件配置:从Pico编程到云端推送
4.1 Pico端MicroPython程序深度剖析
让我们逐行理解那个简单的main.py,并探讨如何让它更健壮、更实用。
from machine import Pin, Timer import time led = Pin(25, Pin.OUT) # 板载LED,用于视觉指示 cricket = Pin(15, Pin.OUT) # 连接Cricket WAKE_UP引脚的GPIO timer = Timer() # 创建一个硬件定时器 def foo(timer): """定时器回调函数:执行核心任务并唤醒Cricket""" # 1. 点亮LED,表示开始执行任务 led.value(1) # 2. 拉高GP15,给Cricket WAKE_UP引脚一个高电平信号,唤醒Cricket cricket.value(1) # 3. 保持唤醒信号一段时间,确保Cricket稳定检测到 time.sleep(0.8) # 0.8秒是一个经验值,通常足够 # 4. 关闭LED和唤醒信号 led.value(0) cricket.value(0) # 配置定时器:每5分钟(300秒)触发一次foo函数 # Timer.freq 参数是频率(Hz)。5分钟一次即 1 / 300 ≈ 0.00333 Hz timer.init(freq=0.00333, mode=Timer.PERIODIC, callback=foo)关键点与优化建议:
- 定时器频率计算:
freq=0.00333代表每秒触发0.00333次,即周期为1 / 0.00333 ≈ 300秒(5分钟)。你可以通过修改这个值来调整上报间隔。例如,每小时一次:freq=1/3600 ≈ 0.000278。 - 唤醒脉冲宽度:
time.sleep(0.8)这0.8秒很重要。Cricket模块从完全断电到启动、加载配置、连接WiFi需要一定时间。这个高电平脉冲必须持续足够长,以确保Cricket能完成整个发送流程。根据Cricket文档,通常500ms以上是安全的。你可以根据实际网络环境微调,但不宜过短。 - 错误处理与状态反馈:目前的代码非常基础。在实际项目中,你可能会在
foo函数内加入传感器读取(如import dht)、数据判断等逻辑。并且,可以考虑用不同的LED闪烁模式来表示不同状态(例如,快速闪烁3次表示传感器读取成功,长亮表示正在等待等)。 - 使用更低的功耗模式:上述代码中,Pico在定时器间隔期内其实仍在运行,虽然比全速运行功耗低,但并非最低。为了追求极致功耗,可以研究Pico的
machine.lightsleep()或machine.deepsleep()模式,并结合外部RTC或定时器中断来唤醒。但这需要更复杂的电路(如连接一个低功耗RTC芯片)和编程,对于入门项目,当前的简单定时器模式已能实现很长的续航。
如何将程序上传到Pico:
- 按住Pico板上的
BOOTSEL按钮,同时通过USB线连接到电脑。电脑上会出现一个名为RPI-RP2的U盘。 - 将编写好的
main.py文件直接拖入该U盘根目录。 - 安全弹出U盘,Pico会自动重启并运行新程序。此时,即使拔掉USB,用电池供电,程序也会自动运行。
4.2 Blynk平台配置与测试
Blynk在本项目中扮演了一个轻量级、免费的云通知网关角色。它的配置非常简单:
创建项目:在Blynk App中,点击“New Project”。
- Project Name: 起个名字,如“Pico Monitor”。
- Choose Device: 选择
Generic Board(通用板)。 - Connection Type: 选择
Wi-Fi。 - 点击“Create”。
获取Auth Token:项目创建后,Blynk会生成一个唯一的认证令牌(Auth Token)。点击界面上的“Email”按钮,这个令牌会发送到你的注册邮箱。请妥善保存这串字符,它是Cricket访问你项目的钥匙。
添加通知组件:在项目编辑界面,从组件库中拖拽一个
Notification组件到画布上。无需任何额外配置。进入运行模式:点击画布右上角的“Play”三角形按钮,项目进入运行模式。此时,你的手机就准备好了接收通知。
使用cURL进行快速测试:在电脑终端(或Postman等工具)中执行以下命令,可以立即验证Blynk配置是否正确:
curl -X POST “https://blynk.cloud/external/api/notify” \ -H “Content-Type: application/json” \ -d ‘{“token”: “你的AuthToken”, “body”: “Hello from Test!”}’请将你的AuthToken替换为刚才获取的真实令牌。如果配置正确,你的Blynk App会立刻收到一条通知。这个测试非常重要,它绕开了硬件,直接验证了云端链路是否通畅。
4.3 Cricket模块的Web配置详解
Cricket模块的配置是其“开箱即用”能力的体现。它通过一个临时的WiFi热点(AP模式)来提供Web配置界面。
- 进入配置模式:给Cricket模块上电(接上电池)。长按模块上的物理按钮约5秒钟,直到其状态灯开始闪烁特定模式(通常为快闪)。此时,Cricket会创建一个名为类似
toe_device_XXXX的WiFi热点。 - 连接热点:用手机或电脑的WiFi设置,连接到这个热点。连接后,通常会自动弹出配置页面,如果没有,在浏览器手动输入
http://192.168.4.1或http://setup.toe.io。 - 配置网络凭证:在配置页面,找到你家庭WiFi的SSID并输入密码,点击连接。Cricket会尝试连接,成功后其状态灯会变为常亮或缓慢闪烁,表示已接入你的局域网。
- 配置HTTP POST动作(核心):这是让Cricket知道“醒来后该做什么”的关键步骤。
- 连接类型 (Connectivity Type):选择
HTTP_POST。 - URL:填写Blynk的推送API地址。注意:Blynk已升级到新平台,旧版地址可能失效。请使用新版地址:
https://blynk.cloud/external/api/notify - Payload (请求体):填写JSON格式的数据。这里需要包含你的Auth Token和通知内容。
{"token": "你的AuthToken", "body": "Pico设备已触发!"} - Content-Type:设置为
application/json。 - Force Update (IO1):这个选项建议设置为
On。它确保每次唤醒(即每次收到GPIO高电平信号)都强制执行一次HTTP POST,而不是忽略重复信号。
- 连接类型 (Connectivity Type):选择
- 保存并退出:配置完成后,在页面右上角通常有“Save”、“Exit”或“Switch Off”按钮。点击后,Cricket会保存配置并重启,进入正常工作模式(等待唤醒信号)。
配置经验谈:在配置Cricket时,确保你的手机/电脑连接的是它的热点,而不是互联网。配置完成后,Cricket会尝试连接你指定的WiFi。如果连接失败(比如密码错误),它会再次进入AP模式等待重新配置。观察模块的LED指示灯状态是判断其工作阶段的好方法,具体闪烁模式请参考Cricket的官方文档。
5. 系统集成、测试与功耗实测
5.1 完整组装与上电测试
按照第3部分的连接图,将所有元件连接好。建议遵循以下顺序:
- 先分别测试:先单独用USB给Pico供电,看LED是否能按5分钟间隔闪烁,验证程序正确。再单独测试Cricket,手动短接其
WAKE_UP和VCC引脚,看手机是否能收到Blynk通知,验证网络和配置正确。 - 断电连接硬件:确保所有电源(电池和USB)都已断开,再进行线路连接。
- 先接电池,后观察:先接上Pico的电池,观察LED是否开始定时闪烁。然后接上Cricket的电池。此时,在下一个5分钟周期,你应该看到:
- Pico板载LED亮起。
- 几乎同时(或稍有延迟),Cricket模块上的LED可能会快速闪烁(表示正在连接WiFi和发送数据)。
- 几秒到十几秒内,你的手机收到Blynk推送的通知。
如果没收到通知,按以下步骤排查:
- 检查Cricket供电:用万用表测量Cricket的VCC和GND之间电压,是否在3V左右?电池电量是否充足?
- 检查唤醒信号:在Pico的LED亮起时,用万用表测量Pico的GP15引脚对GND的电压,是否从0V跳变到了3.3V左右,并持续了0.8秒?
- 检查共地:再次确认Pico的GND和Cricket的GND是否用导线可靠连接。
- 检查Cricket网络:长按Cricket按钮重置,重新配置WiFi,确保它能成功连接到你的路由器(配置时观察路由器后台的客户端列表)。
- 检查Blynk配置:再次使用cURL命令测试,确保Token和API地址无误。
5.2 功耗测量与续航估算
这是评估项目成功与否的硬指标。你需要一个万用表,切换到直流电流档(mA或µA档)。
测量Pico平均电流:
- 将万用表串联到Pico的供电回路中(例如,断开电池正极与VSYS的连接,将万用表红表笔接电池正极,黑表笔接VSYS)。
- 在Pico休眠期间(LED灭),观察电流值。对于运行简单定时器的Pico,电流可能在10-30mA之间(这其实不低)。这就是为什么追求极致续航需要考虑
deepsleep模式,那时电流可降至1mA以下甚至几百µA。 - 在Pico唤醒的0.8秒内(LED亮),电流会有一个峰值,可能达到50mA或更高。
测量Cricket平均电流:
- Cricket在休眠时(无唤醒信号),理论电流为0µA(完全断电)。你可以用万用表验证,应该测不到任何电流。
- Cricket在被唤醒的整个工作周期(假设3秒),电流会从0迅速爬升,连接WiFi时可能达到100-200mA的峰值,发送数据时略有下降。
系统续航估算(理论): 假设我们使用两节AAA碱性电池,总容量约2000mAh。
- Pico功耗:假设平均电流为20mA(这是一个较高的估算,为了简化)。每小时耗电 20mA * 1h = 20mAh。
- Cricket功耗:每5分钟工作3秒,峰值电流按150mA算。每小时工作
(60/5)*3 = 36秒 = 0.01小时。每小时耗电 150mA * 0.01h = 1.5mAh。 - 系统总平均电流≈ 21.5mA。
- 理论续航= 电池容量 / 平均电流 = 2000mAh / 21.5mA ≈93小时,约4天。
这个结果看起来并不“数月或数年”,原因在于我们的Pico程序没有使用真正的深度睡眠。优化方向:
- 优化Pico程序:使用
machine.deepsleep()并结合外部中断或RTC定时唤醒,可以将Pico休眠电流降至100µA (0.1mA)以下。 - 重新估算:Pico平均电流按0.1mA算,Cricket功耗不变(1.5mAh/h)。
- 总平均电流 ≈ 1.6mA。
- 理论续航 = 2000mAh / 1.6mA ≈1250小时,约52天。
- 使用更大容量电池:如一颗3400mAh的18650锂电池,续航可轻松超过3个月。
- 进一步降低上报频率:如果数据不需要每分钟上报,改为每小时或每天上报一次,Cricket的功耗占比将急剧下降,续航时间会呈数量级增长。
6. 项目扩展与高级应用思路
这个闪烁LED并发送通知的项目只是一个起点。它的架构可以轻松扩展成各种实用的物联网设备。
6.1 接入物理传感器
Pico的GPIO、I2C、SPI、ADC等接口可以连接几乎任何数字或模拟传感器。
示例:制作一个低功耗温湿度警报器
- 硬件:在Pico上连接一个DHT11或更精确的SHT30(I2C接口)温湿度传感器。
- 软件:修改
foo函数。import dht # 或使用I2C库导入SHT30 sensor = dht.DHT11(Pin(16)) # 假设数据线接GP16 def foo(timer): sensor.measure() temp = sensor.temperature() humidity = sensor.humidity() # 判断是否超过阈值 if temp > 30 or humidity > 80: led.value(1) # 报警指示 cricket.value(1) # 唤醒Cricket发送警报 time.sleep(0.8) led.value(0) cricket.value(0) # 否则,本次循环不唤醒Cricket,节省电量 - Cricket配置:修改Payload,将传感器数据发送出去。可以使用Blynk的API更新虚拟引脚值,或者在通知消息中携带数据。
你需要修改Pico程序,将数据通过某种方式(如修改GPIO脉冲宽度、使用多个GPIO进行简单编码)传递给Cricket,或者更高级地,让Pico通过UART在唤醒Cricket后发送数据。Cricket也支持在Payload中使用从IO引脚读取的模拟/数字值作为变量。{"token": "你的Token", "body": "高温警报!温度: {{TEMP}}°C, 湿度: {{HUM}}%"}
6.2 连接其他云平台或私有服务器
Cricket的HTTP POST功能非常灵活,不限于Blynk。你可以让它将数据发送到任何支持HTTP API的服务。
- IFTTT / Webhooks:可以触发更复杂的自动化流程,如发送邮件、记录到Google Sheets、控制智能家居设备。
- 私有服务器:发送到你自己搭建的、运行在本地或云端的服务器(如用Python Flask写的简单API)。Payload可以自定义任何JSON格式。
- ThingsBoard / Home Assistant:这些专业的IoT平台,都有完善的HTTP API用于设备数据接入。
6.3 优化功耗的进阶技巧
- Pico深度睡眠:使用
machine.deepsleep()并配合GPIO中断或RTC唤醒。这需要将GPIO16(GP20)连接到复位引脚,并在程序中配置RTC闹钟。唤醒后程序会从头开始执行,你需要将状态保存在Pico的RTC内存或外部EEPROM中。 - 降低工作电压:Pico和Cricket都能在稍低于3.3V的电压下工作。使用两节AA电池(3V)或单节锂电池(充满电4.2V,但大部分时间在3.7V)通过低压差稳压器(LDO)供电,比使用3节AAA电池(4.5V)经过降压效率更高。
- 优化Cricket发送:确保Cricket配置的WiFi信号强度良好,信号差会导致连接时间变长,功耗增加。如果数据量极小,可以尝试使用MQTT协议,它通常比HTTP的握手开销更小,发送更快。
- 电源路径管理:对于最终产品,可以考虑使用带有使能端(EN)的低功耗稳压器,由Pico的GPIO控制,在不使用传感器或Cricket时彻底切断它们的电源,实现零待机功耗。
这个项目就像一把钥匙,为你打开了低功耗物联网世界的大门。从简单的通知器到复杂的环境监测站,所有的核心思想都是一致的:让合适的模块在合适的时间工作,最大限度地减少不必要的能量消耗。动手去改造它,加入你想要的传感器,把它应用到你的具体场景中,这才是创客精神的所在。