ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

基于IN100与SHT40的低功耗蓝牙温湿度传感器设计与实现

基于IN100与SHT40的低功耗蓝牙温湿度传感器设计与实现 1. 项目概述用IN100打造一个无线温湿度传感器最近在捣鼓一些低功耗的物联网小玩意儿发现InPlay的IN100这颗芯片挺有意思。它是一个超低功耗的蓝牙5.1 SoC自带NanoBeacon功能非常适合用来做那些需要长时间待机、偶尔上报一下数据的传感器节点。正好手头有个项目需要监测几个储物柜内部的温湿度布线不方便电池供电还得撑个大半年IN100就成了我的首选。这个项目说白了就是利用IN100读取SHT40温湿度传感器的数据然后通过蓝牙广播Beacon的方式把数据“喊”出来让附近的手机或者网关设备能接收到。整个过程不建立复杂的蓝牙连接功耗极低实现起来也相对简单。你可能要问为什么选IN100和SHT40这个组合IN100的核心优势在于其极低的待机电流和集成的NanoBeacon协议栈你几乎不用写复杂的蓝牙协议代码配置一下就能发广播包。SHT40则是Sensirion新一代的温湿度传感器精度不错功耗也低关键是它使用I2C接口和IN100通信起来非常方便。这个项目适合那些想入门低功耗蓝牙传感、或者需要快速搭建一个无线数据采集原型的开发者。即使你对蓝牙协议栈不熟跟着这个思路走也能很快把东西跑起来。2. 核心硬件选型与电路设计思路2.1 主角解析IN100与SHT40为何是黄金搭档选择IN100最看中的就是它的“懒人”模式。传统的蓝牙芯片你要想发个数据得先初始化协议栈处理连接事件管理功耗状态一堆事。而IN100的NanoBeacon模式把它配置成一个信标Beacon它就会按照你设定的时间间隔周期性地广播一个特定的数据包。这个数据包里可以携带自定义的信息比如我们的温湿度读数。芯片大部分时间在深度睡眠只有到点广播和读取传感器时才醒来一下平均电流可以做到微安级一颗纽扣电池用上一年不是梦。SHT40是数字温湿度传感器里的“优等生”。它提供了±1.8%RH的湿度精度和±0.2°C的温度精度对于大多数环境监测应用完全足够。它的功耗非常低一次测量消耗约0.4mA电流耗时不到10ms测完就可以进入休眠模式。通信接口是标准的I2C只有两根线SCL和SDA节省IO资源。最重要的是它的工作电压范围是1.08V到3.6V和IN100的供电电压完美匹配可以直接用同一颗电池供电不需要额外的电平转换电路。2.2 供电与外围电路设计要点整个系统的供电方案是设计的重中之重直接决定了续航能力。我推荐使用一颗CR2032纽扣电池3V220mAh作为主电源。IN100的工作电压范围是1.8V到3.6VSHT40是1.08V到3.6V电池电压从满电的3.2V放到2.0V两者都能正常工作可以充分利用电池容量。注意虽然理论上电压可以低至1.8V但考虑到电池内阻和瞬间电流建议设置一个稍高的截止电压比如2.2V以保护电池并保证系统稳定。电源电路需要一颗滤波电容通常用一个10µF的钽电容或陶瓷电容并联一个0.1µF的陶瓷电容分别滤除低频和高频噪声确保IN100射频部分和数字内核的稳定。对于SHT40在其VDD和GND引脚之间也需要加一个0.1µF的去耦电容位置尽可能靠近传感器引脚。复位电路方面IN100有专用的复位引脚RSTn。为了保证上电稳定和必要时的手动复位建议连接一个标准的阻容复位电路一个100kΩ的上拉电阻接到VCC一个0.1µF电容接地。同时可以引出一个轻触开关到地实现手动复位。2.3 I2C通信线路连接与上拉电阻选择IN100和SHT40通过I2C总线连接这是本项目唯一的数字通信线路。连接非常简单IN100的某个GPIO配置为I2C_SCL接SHT40的SCL引脚。IN100的另一个GPIO配置为I2C_SDA接SHT40的SDA引脚。两者共享VCC和GND。这里有个关键细节I2C总线是开漏输出必须加上拉电阻。上拉电阻的阻值需要仔细计算它影响了总线速度、功耗和信号上升时间。公式主要考虑总线电容C_bus和上升时间t_r。总线电容包括走线电容和所有连接在总线上的器件引脚电容对于这种简单电路估计在10-50pF之间。标准模式100kHz下上升时间要求小于1µs。假设VCC3V使用经典的公式R_pullup t_r / (0.8473 * C_bus)。如果C_bus取50pFt_r要求1µs计算出的R_pullup最大值约为23.6kΩ。考虑到留有余量和降低功耗我通常选择10kΩ的电阻。这个阻值在3V电压下高电平时每条线电流约0.3mA功耗可以接受同时也能保证在100kHz甚至400kHz快速模式下可靠的信号上升。实操心得如果你追求极致的低功耗可以考虑使用更大的阻值比如47kΩ甚至100kΩ但这会限制总线速度并增加对噪声的敏感性。对于本项目中每秒才读取一次数据的场景100kHz速度绰绰有余使用10kΩ或22kΩ是一个稳健的选择。务必使用精度为1%或5%的金属膜电阻。3. 软件架构与IN100 NanoBeacon配置3.1 工程初始化与时钟配置首先需要在InPlay提供的开发环境通常是基于Keil或IAR中创建一个新工程选择正确的IN100型号。第一步是配置系统时钟。IN100内部有多个时钟源低速内部RC振荡器32.768kHz、高速内部RC振荡器16MHz以及高频晶体振荡器可选。为了平衡精度和功耗我们这样配置低频时钟LFCLK使用内部32.768kHz RC振荡器为实时计数器RTC和睡眠定时器提供时钟这是实现周期性唤醒的关键。高频时钟HFCLK在需要运行射频和高速处理时比如广播瞬间切换到16MHz内部RC振荡器。广播完成后立即切换回低频时钟并进入睡眠。这种动态时钟切换是低功耗设计的核心。在代码中你需要初始化时钟树设置好这些时钟源以及它们之间的切换条件。InPlay的SDK里通常有相应的API例如sysclk_init()和pmu_switch_to_low_power()。3.2 NanoBeacon广播数据包格式设计NanoBeacon广播的数据包格式是自定义的我们需要把温湿度数据塞进去。一个标准的蓝牙广播包最大是31字节。其结构通常包括前导码和接入地址由协议栈自动处理。广播报文头Header包含广播类型、地址类型等。广播地址AdvA6字节的广播者蓝牙地址可以自定义或随机生成。广播数据AdvData这是我们放自定义数据的地方。长度可变最多28字节左右扣除报文头和地址。CRC校验协议栈自动添加。我们的重点是设计AdvData。它由若干个「AD Structure」组成每个结构包含1字节长度、1字节AD Type和N字节的AD Data。我们可以利用“制造商特定数据”AD Type 0xFF来携带我们的数据。例如长度假设我们数据总长8字节则AD Structure长度为1(长度字节)1(类型字节)8(数据)10所以第一个字节是0x0A。AD Type0xFF 表示制造商特定数据。AD Data接下来的8字节我们可以定义如下字节1-2制造商ID自定义例如0x1234。字节3数据包类型/版本例如0x01表示温湿度数据。字节4-5温度数据16位有符号整数单位0.01°C。字节6-7湿度数据16位无符号整数单位0.01%RH。字节8电池电压单位0.01V或校验和。这样接收端如手机App在扫描到广播包后识别制造商ID为0x1234且类型为0x01就能正确解析出温度、湿度和电池电压。3.3 低功耗任务调度与睡眠管理程序的主循环将是一个典型的“事件驱动深度睡眠”架构。流程图的核心逻辑如下系统上电初始化时钟、GPIO、I2C、NanoBeacon参数。进入主循环。检查RTC定时器是否到期例如每10秒唤醒一次。如果未到期则调用pmu_enter_deep_sleep()进入深度睡眠模式。此时CPU停止仅RTC和唤醒电路工作电流在1µA级别。RTC定时器到期系统唤醒。唤醒后首先将系统时钟切换到高速模式16MHz。通过I2C读取SHT40的温湿度数据。将读取到的原始数据如温度ADC值按照传感器数据手册中的公式转换为实际物理值°C和%RH。将转换后的温湿度值以及可能读取的电池电压按照预设格式打包到NanoBeacon的广播数据缓冲区。启动一次或连续几次蓝牙广播例如快速广播3次以提高被接收的概率。广播完成将系统时钟切换回低速模式。重置RTC定时器开始下一个睡眠周期。跳回步骤3。这个循环中99.9%以上的时间芯片都在深度睡眠只有不到100ms的时间处于活跃状态从而实现了超低功耗。4. I2C驱动实现与SHT40数据读取详解4.1 IN100的I2C外设初始化IN100的I2C控制器配置相对直接。你需要配置相关的GPIO引脚为I2C功能模式通常是开漏输出模式。然后初始化I2C控制器设置时钟频率SHT40支持标准模式100kHz和快速模式400kHz。为了可靠性和低功耗我们先使用100kHz。对应的时钟分频系数需要根据系统高频时钟频率计算。如果系统时钟是16MHz要产生100kHz的SCL计算公式涉及I2C时钟控制寄存器的分频设置具体值需参考IN100用户手册。配置自身地址由于IN100是主设备SHT40是从设备所以IN100的主地址模式可以简单设置。使能I2C控制器。这里有个坑要注意IN100的I2C引脚功能映射可能不是固定的需要查看数据手册的“引脚复用”章节将对应的GPIO配置为I2C_SCL和I2C_SDA功能。4.2 SHT40的测量指令与读取流程SHT40的通信协议非常简洁。它有一个7位的I2C从机地址默认是0x44二进制1000100。测量温湿度有两种精度模式我们选择高精度模式对应的命令字是0xFD。一次完整的测量读取流程如下发送测量命令IN100作为主设备发起START条件发送SHT40的地址0x441 | 0写收到ACK后发送命令字节0xFD再收到ACK后发送STOP条件。这条指令会触发SHT40内部进行一次温湿度测量测量时间大约10ms。等待测量完成发送命令后需要延迟至少10ms确保测量完成。这里可以用一个简单的delay_ms(12)函数。读取数据再次由IN100发起START条件发送SHT40的地址0x441 | 1读然后连续读取6个字节的数据。这6个字节分别是温度数据高字节Temp_MSB温度数据低字节Temp_LSB温度数据的CRC8校验和Temp_CRC湿度数据高字节Hum_MSB湿度数据低字节Hum_LSB湿度数据的CRC8校验和Hum_CRC主设备在读完第6个字节后发送NACK和STOP条件结束传输。重要提示SHT40返回的数据附带了CRC8校验这是保证数据在I2C传输过程中不出错的有效手段。在实际产品代码中强烈建议实现CRC校验函数在解析数据前先校验如果校验失败应丢弃本次数据或重试。4.3 数据解析与物理量转换读取到的6个字节是原始数据需要转换成实际的温度和湿度值。转换公式在SHT40的数据手册中有明确给出。温度转换将温度高字节和低字节组合成一个16位无符号整数raw_tempTemp_MSB 8 | Temp_LSB。计算实际温度temperature_degC -45 175 * (raw_temp / 65535)这个公式将原始ADC值范围0~65535线性映射到-45°C到130°C的范围。计算时注意使用浮点数或进行定点数运算以避免精度损失。湿度转换将湿度高字节和低字节组合成一个16位无符号整数raw_humHum_MSB 8 | Hum_LSB。计算实际相对湿度humidity_RH -6 125 * (raw_hum / 65535)这个公式将原始ADC值线性映射到-6%RH到119%RH的范围。通常结果在0-100%RH之间。在资源受限的MCU上直接进行浮点运算可能比较耗时和耗能。可以采用定点数运算来优化。例如将公式变形为temperature_degC (-45 * 65535 175 * raw_temp) / 65535。可以先计算分子一个32位整数再除以65535相当于右移16位最后除以100得到带两位小数的温度值单位0.01°C方便存入之前设计的16位整数广播字段。5. 系统集成、功耗测试与优化5.1 代码集成与广播触发逻辑将上述模块整合起来。在主循环的唤醒分支中依次调用sht40_read_data(temp_raw, hum_raw)封装好的读取函数内部包含I2C通信、延迟和CRC校验。convert_to_physical_values(temp_raw, hum_raw, temp_phy, hum_phy)转换函数输出定点数格式的物理量。prepare_beacon_data(temp_phy, hum_phy, beacon_buffer)将物理量按照预设格式如2字节温度、2字节湿度填充到广播数据缓冲区。nanobeacon_update_adv_data(beacon_buffer, length)调用IN100 SDK的API更新广播数据。nanobeacon_start_adv(3)启动广播参数3表示连续广播3个周期后自动停止。广播触发后IN100的射频模块会工作电流会瞬间上升到几个毫安甚至十几毫安。广播完成后SDK会产生一个事件我们在事件处理函数中可以再次将系统置于准备睡眠状态。5.2 实际功耗测量与电池寿命估算理论计算很重要但实测才是王道。你需要一个能测量微安级电流的万用表或功耗分析仪如Joulescope。将仪器串联在电池和电路板之间。测试方法睡眠电流让设备进入深度睡眠模式测量此时的平均电流I_sleep。理想情况下应小于2µA。活动窗口电流与时间触发一次完整的“唤醒-读取-广播”流程用示波器或功耗分析仪捕获电流波形。测量出唤醒及读取传感器阶段的平均电流I_active1和持续时间t_active1约15ms。广播阶段的平均电流I_active2和持续时间t_active2假设广播3次约10ms。计算平均电流假设广播间隔为T_interval如10秒。每次循环总电荷量Q_cycle I_active1 * t_active1 I_active2 * t_active2 I_sleep * (T_interval - t_active1 - t_active2)。平均电流I_avg Q_cycle / T_interval。举例I_sleep1.5µA I_active12mA (15ms) I_active210mA (10ms) T_interval10s。 计算得Q_cycle ≈ 2mA*0.015s 10mA*0.01s 1.5µA*9.975s ≈ 0.03 0.1 0.01496 0.14496 mAs。I_avg 0.14496 mAs / 10s ≈ 14.5 µA。使用一颗CR2032电池标称容量220mAh考虑到低温、自放电等因素取可用容量200mAh。 理论续航时间T_life 200mAh / 14.5µA ≈ 13793小时 ≈ 574天。超过一年半5.3 深度优化技巧与常见陷阱优化技巧调整广播间隔根据应用需求在数据更新频率和功耗之间权衡。从10秒延长到30秒平均电流几乎成比例下降。减少广播次数每次唤醒不一定需要广播3次。在信号环境好的地方广播1次成功率就很高。可以动态调整例如连续3次广播失败后下次唤醒增加广播次数。降低广播功率IN100的射频发射功率是可调的。降低发射功率如从0dBm降到-20dBm能显著降低广播时的峰值电流代价是通信距离缩短。对于柜内监测这种短距离场景完全可行。优化传感器读取频率如果不是每次都需要新数据可以多次唤醒只读取一次传感器其他时间广播旧数据。断开所有无用负载确保不用的GPIO设置为输入模式并内部上拉或下拉关闭所有未使用的外设时钟。常见陷阱I2C总线锁死如果程序异常或电源不稳可能导致I2C从设备SHT40挂起拉低SDA线造成总线锁死。解决方法是在I2C初始化函数或发生超时后增加一个“恢复序列”手动控制SCL引脚产生9个时钟脉冲同时检测SDA是否被释放。广播被干扰在2.4GHz频段Wi-Fi、蓝牙其他设备都可能造成干扰。如果发现数据接收不稳定可以尝试轻微改变广播间隔如从1000ms改为1050ms避免与环境中周期性的干扰源同步。电池电压监测为了预警电池电量低可以定期用IN100内部的ADC测量电池电压通过分压电阻。但ADC转换本身也耗电约几百微安持续几十微秒。需要权衡监测频率比如每100个循环约16分钟测一次。软件看门狗在长期运行的项目中一定要启用硬件或软件看门狗防止程序跑飞。但注意在进入深度睡眠前需要暂停或妥善处理看门狗否则它会阻止睡眠或唤醒后复位。6. 数据接收端方案与项目扩展思路6.1 手机App接收与解析示例数据发出来了还得有接收端。对于手机可以开发一个简单的App使用Android的BluetoothLeScanner或iOS的CoreBluetooth来扫描和解析我们的自定义Beacon。以Android为例在扫描回调onLeScan或ScanCallback中你会拿到一个ScanRecord对象。遍历其中的ScanRecord.getManufacturerSpecificData()方法返回的SparseArray。查找制造商ID我们之前定义的0x1234对应的字节数组。拿到这个数组后按照我们约定的格式解析第0字节数据包类型应是0x01。第1-2字节温度值有符号short需转换为温度值/100.0f得到摄氏度。第3-4字节湿度值无符号short需转换为湿度值/100.0f得到百分比。第5字节电池电压需转换为电压值/100.0f得到伏特。解析后就可以在UI上显示实时数据并可以记录历史数据形成曲线图。6.2 网关集中采集与云端同步对于需要集中管理多个传感器的场景如仓库、实验室可以使用树莓派、ESP32或其他带蓝牙的Linux网关设备。网关设备上运行一个后台服务可以用Python的bluepy或pybluez库持续扫描周围的Beacon过滤出我们设备的制造商ID解析数据然后通过Wi-Fi或以太网上传到云平台如阿里云IoT、ThingsBoard、自建MQTT服务器。这种架构的优势在于传感器节点极度简单、省电复杂的网络连接和数据聚合由一直供电的网关负责。网关还可以进行初步的数据校验和过滤。6.3 功能扩展与变体设计这个基础框架可以衍生出很多变体多传感器集成IN100有多个GPIO和ADC可以同时连接多个传感器。例如加上一个光照传感器BH1750也是I2C或一个PIR运动传感器GPIO中断。在广播数据包中增加相应的字段即可。注意功耗管理非必要时不唤醒这些传感器。触发式上报除了定时上报还可以由事件触发。比如用门磁开关连接到GPIO中断监测柜门开关开门时立即唤醒并密集上报一段时间的数据。数据加密如果数据涉及隐私可以在IN100端对广播数据进行简单的加密如AES-128接收端需要密钥才能解密。虽然广播本身是公开的但加密后内容不可读。OTA固件升级IN100支持通过蓝牙进行固件升级DFU。可以设计一个模式当设备收到特定的升级指令Beacon时进入DFU模式等待手机或网关发送新的固件包。这是产品化必备的功能。更长的续航如果使用更大容量的电池如AA锂铁电池并结合太阳能板进行微能量收集可以实现理论上的“永久”续航适用于野外环境监测。这个项目从硬件选型、电路设计到软件驱动、功耗优化涵盖了一个低功耗无线传感节点开发的核心环节。IN100的NanoBeacon特性让蓝牙广播应用的门槛降低了很多而SHT40提供了可靠的环境数据。把这两者结合起来你就能快速搭建起一个稳定、省电的无线监测点。在实际部署中最关键的就是功耗的精细测量和优化以及通信可靠性的测试。多准备几块板子放在不同的位置跑上几天看看数据接收是否连续电池消耗是否符合预期这些实地测试的经验远比理论计算来得宝贵。
返回列表