基于Nordic BLE SoC的智能水处理系统设计与实现

发布时间:2026/8/27 13:31:34
基于Nordic BLE SoC的智能水处理系统设计与实现 我家正在用一台老款RO净水器前阵子滤芯到期了都没察觉出水TDS都飙到80多了才反应过来。更糟的是有一次管线漏水泡了半个厨房。后来我干脆自己动手给水处理系统加了一个基于Nordic BLE SoC的IoT智能控制模块把水质监测、滤芯寿命管理、漏水保护、远程控制全做进去了。这个项目做完之后效果很理想我把完整的设计思路、硬件选型、协议实现和踩坑记录整理出来希望能给正在做智能净水器、鱼缸水处理或类似水质监测设备的朋友一些参考。这篇内容适合三类人看一是做IoT硬件产品开发、正在纠结无线方案选型的工程师二是想给自己的水处理设备做智能化改造的动手党三是对BLE低功耗设计和传感器信号链感兴趣、想了解完整落地细节的嵌入式开发者。文章会从方案选型开始讲一直到最后的问题排查整个过程都是我在实机上验证过的。1. 方案选型为什么最终锁定Nordic BLE SoC1.1 先把需求盘清楚再选型做硬件产品最忌讳一上来就选芯片。我先把智能水处理系统的需求列了一遍再根据这些需求去反推无线方案。水处理系统的数据特征很鲜明传感器数据量小一次上报也就几十个字节采集频率低水温、TDS、pH这些参数变化很慢10分钟采一次完全够用但产品对稳定性和实时告警有要求漏水这种事件几秒钟内就要推给用户。另外这类设备通常部署在厨房、卫生间、户外鱼池这些环境供电条件不确定有些地方有插座有些地方要用电池低功耗能力必须强。还有一个容易被忽略的点使用场景是室内而且人就在设备附近活动。手机App操作距离不会超过10米这决定了短距离无线通信完全够用没必要追求几公里的覆盖。1.2 几种无线方案的横向对比我做了个对比表格业内几个主流方案都拉进来比了一遍方案功耗传输距离手机直连网关依赖典型应用场景BLE极低µA级睡眠10-100m支持无可穿戴、健康设备、智能家居Wi-Fi高mA级常态30-100m支持无连路由器智能家电、摄像头Zigbee较低10-100m不支持需要网关智能家居Mesh网络NB-IoT较低但模块贵几公里不支持需要运营商网络水表、气表、资产追踪Wi-Fi这个方案最先被我排除了。虽然Wi-Fi模块技术成熟、手机无缝接入但功耗实在扛不住。一个ESP8266跑起来平均电流70-80mA如果还要维持TCP长连接电流更难看。水处理设备如果靠电池供电Wi-Fi方案几天就得换电池这产品没法用。而且Wi-Fi配网流程极其反人类用户体验差。Zigbee的功耗不错但手机不直接支持Zigbee协议必须通过网关桥接。我做的这个项目是单品智能不想额外拖一个网关设备整个架构会复杂化用户成本也更高。直接排除。NB-IoT适合水务公司做远程抄表那种场景资费问题、模块成本、还有信号覆盖家庭用户很难接受。排除。BLE在这个场景下几乎是完美的手机直连、不需要网关、功耗低、协议栈成熟而且水处理设备和用户通常就在同一个房间里BLE通信距离完全覆盖。最终我锁定了BLE方案。1.3 为什么是Nordic而不是其他BLE芯片BLE芯片选型时我重点比较了Nordic、TI、Dialog、Silicon Labs这几家。最后选了Nordic nRF52832原因是多方面的。首先是协议栈成熟度。Nordic的SoftDevice协议栈是业界公认做得最稳的它比TI的协议栈更容易上手API文档详实社区活跃度高。说得直接一点遇到问题时Google一搜Nordic的解决方案基本都能找到这种生态成熟度对产品开发效率影响极大。其次是外设资源。nRF52832自带12位SAADC多通道可以满足pH、TDS这些模拟传感器的采集需求有TWII2C兼容接口接数字温湿度传感器很方便有PWM输出可以产生交流激励信号给电导率传感器还有RTC、GPIOTE这些低功耗外设做事件驱动非常灵活。一颗芯片搞定主控加无线系统BOM成本更低。再就是低功耗特性。nRF52832在System OFF模式下电流约0.3µA带RTC唤醒的System ON模式约1.9µA再加上NRF52全系内置DCDC降压转换器能进一步把峰值电流降下来。这个数据在同级别芯片里是第一梯队对电池供电的机型来说非常关键。具体选nRF52832还是nRF52840我纠结了一下。nRF52840性能更强、flash更大还带USB和NFC但价格也贵了不少。我的设计不需要USB、不需要复杂MeshnRF52832的512KB flash和64KB RAM完全够用。最终从成本角度选了nRF52832省下来的钱可以用在传感器和泵阀这些直接影响体验的部件上。2. 硬件设计从传感器信号链到电源功耗2.1 传感器选型与信号链设计水处理系统的传感器是整个产品的感知层选型和质量直接决定了数据的准确性。我用了这几类传感器配合工作TDS传感器测溶解性固体总量、pH传感器测酸碱度、NTC热敏电阻测水温、霍尔流量计测实时流速和累计流量、电极式漏水检测传感器测漏水。TDS传感器的核心是电导率测量。水的电导率和TDS呈一定线性关系但直接用直流电测量会导致电极极化产生严重误差。正确做法是用交流激励信号驱动电极通过测量交流电流计算出水的电导率。我用nRF52832的PWM模块产生约1kHz的方波作为激励源通过运放电路做信号调理再送进SAADC采样。采样时要注意相位问题必须在激励信号的稳定区间采样不能采在边沿跳变处否则数据噪声很大。pH传感器的信号链路更讲究。pH电极输出阻抗极高几十到几百兆欧不能直接接ADC必须经过高输入阻抗的运放缓冲。我用了一个低偏置电流的JFET输入运放做电压跟随再经同相放大电路把pH对应的微弱电压变化放大到SAADC的满量程范围内。pH传感器需要偶联校准两点校准这个后面在固件部分详细讲。流量计是霍尔脉冲式的。水流推动叶轮旋转内置霍尔传感器输出与流量成正比的脉冲信号一个典型的参数是1升水约等于450个脉冲。这个信号直接接nRF52832的GPIOTE通道用硬件计数方式处理不占用CPU时间。2.2 供电架构与功耗控制供电架构我设计了两种方案适配不同机型插电版用AC-DC适配器提供5V输入电池版用18650锂电池加充放电管理。nRF52832有个高端特性它内部集成了DCDC降压转换器只需要外接一个10mH电感就能工作。启用DCDC后工作模式下的TX电流能从约5.3mA降到约4.5mA整体功耗降低约15%-25%这个功能必须在硬件上预留电感位置。关键的功耗设计技巧传感器的供电要独立可控。我用一颗P-MOS管做传感器电源开关平时所有传感器完全断电只有在采样周期到来时才打开电源等信号稳定后再采集。这个设计能极大地降低系统平均功耗因为传感器工作电流动辄十几毫安如果一直通电电池再大也不够用。采样完成后关断传感器电源系统进入睡眠状态等待下一次RTC唤醒。供电电路里的几个坑一是nRF52832的电源去耦必须做好每个电源引脚都要有100nF陶瓷电容紧贴放置还要有1µF以上的大电容做储能二是DCDC电感不能用普通的绕线电阻替代必须用额定电流足够的功率电感三是模拟传感器信号的参考地要和数字地单点连接避免地环路噪声影响ADC精度。2.3 PCB布局与天线设计要点BLE是2.4GHz频段射频部分的设计直接决定了通信质量和整机功耗表现。天线布局是重中之重nRF52832在ANT引脚输出射频信号需要经过匹配网络接到天线。原厂参考设计用的π型匹配网络预留了三颗0402封装的匹配电容/电感焊盘方便调试时调整阻抗。PCB设计时我特别注意了几个位置天线下方区域必须净空正反面都不能铺铜、不能走线天线要放在PCB边缘或角落让辐射方向不会被金属外壳遮挡多层的PCB射频走线要走在顶层走线下方要有完整的参考地平面阻抗按50Ω控制。晶体振荡器的布局也很关键。32MHz高速晶振和32.768kHz低频晶振都必须尽量靠近芯片摆放。距离过远会导致信号完整性下降。有一次我调试时设备广播距离始终上不去排查了半天最后发现是32MHz晶振的负载电容虚焊了频率偏移导致发射频率不准确接收端灵敏度大幅下降。我在实际设计过程中体会最深的一点即使硬件原理图、PCB看起来都没问题射频性能也可能因为工艺、物料批次不同而出现偏差。批量生产前务必用网分或者频谱仪验证一下射频性能这步绝对不能省。3. BLE通信协议GATT服务与广播设计3.1 GATT服务让数据按规范流动BLE协议栈的数据通信基于GATTGeneric Attribute Profile模型核心是服务Service和特征值Characteristic两层结构。我设计的智能水处理系统定义了以下几个服务和特征值服务特征值属性说明水质数据服务pHNotify实时pH值2字节放大100倍传输水质数据服务TDSNotify实时TDS值2字节水质数据服务水温Notify温度数据2字节扩大100倍传输设备信息服务滤芯寿命Read百分比0-100设备信息服务电池电量Read百分比控制服务冲洗开关Write写0x01触发冲洗控制服务系统模式Write写0x00关机、0x01自动告警服务漏水警报Notify/Indicate漏水时主动推送Notify和Indicate的区别在于Notify发送后不需要接收方确认速度快但可能丢包Indicate要求接收方确认可靠性高但吞吐低。漏水报警我用的是Indicate因为这种数据必须确保送达。正常的水质数据用Notify偶尔丢一帧实时数据不影响用户体验。UUID我用的是自定义128位UUID。虽然BLE标准定义了很多标准服务UUID但水质监测这个领域没有直接对应的标准服务自定义是合理的做法。每个特征值还要配置属性描述符CCCD因为客户端需要先写CCCD才能开启Notify/Indicate通道。3.2 广播设计让手机快速发现设备BLE广播设计直接影响用户配网体验。广播包最多31字节合理的分配策略是设备名称占一部分服务UUID占一部分Manufacturer Specific Data占一部分。我把广播名称设为SmartWaterCare通过完整16位UUID广播来声明水质数据服务同时把设备ID和当前状态放在Manufacturer Specific Data区域。设备ID用于云端识别状态字段的低四位放了当前工作模式高四位放了告警标志。手机App扫描到广播包后即使未连接也能先判断设备是否正在漏水这个设计让App的首页可以秒级显示设备告警状态。广播间隔的选择也有讲究。广播间隔越短设备被发现的速度越快但功耗越高。我设置了两种广播模式配网模式下用100ms短间隔广播方便快速被发现正常运行时用1s长间隔广播平衡功耗和可发现性。设备进入配网模式的方式很简单长按实体按键5秒即可。3.3 连接参数与吞吐量权衡BLE连接建立后决定通信速率和功耗的关键参数有连接间隔Connection Interval、从机延迟Slave Latency和超时时间Supervision Timeout。连接间隔是主机两次poll从机的时间间隔范围7.5ms到4s。间隔越短实时性越好、吞吐越高但设备需要频繁醒来收发数据功耗越高。我的配置是正常数据同步场景连接间隔设为60ms这样一次数据包往返就能完成一包数据大约20字节足够承载pH加TDS加温度加流量累计值。如果要做DFU升级这种大数据量传输场景我会额外配置一个快速参数连接间隔缩短到15ms把吞吐提上去。从机延迟这个参数常常被忽略但它对功耗优化非常关键。它允许从机在指定次数内不响应主机的poll从而保持睡眠。我把它设为2意味着连续两个连接事件都可以不醒来功耗能降三分之一。代价是丢包率会略有升高因为如果传感器数据刚好在跳过的连接间隔中产生就得等下个周期才能发出去。但对于水处理这种低实时性场景完全没问题。连接参数不是单方面说了算的主机手机有最终决定权从机可以发送连接参数更新请求由主机决定是否采纳。iOS和Android对这个过程的处理差别很大Android的兼容性尤其要注意有些手机驱动会自动拒绝连接参数更新请求导致设备只能按默认参数工作。针对这个问题我在固件里加了一个重试机制持续请求参数更新直到成功为止。4. 低功耗策略从电池寿命估算到事件驱动4.1 功耗预算与电池寿命估算低功耗设计的起点是功耗预算。没有定量分析的低功耗都是拍脑袋我现在把整个计算过程分享出来。假定采样周期为10分钟采样过程持续100ms传感器供电电流15mA主控采集和数据处理时电流5mA射频发送0dBm电流约5.3mA睡眠状态下整个系统电流约5µA。单次采样能耗大概是1555.3mA × 0.1s 2.53mAs。10分钟内平均电流是2.53mAs / 600s ≈ 0.0042mA加上睡眠5µA再加DCDC的转换损耗总平均电流约10µA以内电池供电的机型就可以按这个数字估算。电池容量按2000mAh18650电池典型容量计算2000mAh / 0.01mA 200000小时约等于22年。这个理论寿命很长但是实际应用要考虑三个因素电池自放电每年约2%-5%极端低温下容量衰减以及用户频繁连接手机带来的额外功耗。手机连接时从机需要全速工作假设用户每天打开App看10次每次连接20秒连接时平均电流15mA每天额外功耗就是300mAs折合平均电流3.5µA影响不大整体下来2到3年没有任何压力。4.2 定时采集与事件驱动机制系统的低功耗核心是事件驱动架构。平时主控处于System ON模式只有RTC在运行CPU停止执行指令电流降到µA级别。当RTC定时器溢出触发中断时CPU被唤醒执行一次完整的传感器数据采集和上报流程然后重新进入睡眠。RTC的配置有个技术细节。nRF52832的RTC模块使用32.768kHz时钟源我通过设置PRESCALER寄存器把频率降到每秒一次再配合比较寄存器产生10分钟周期中断。API使用的是sdk_app_timer更简单方便。漏水检测走的是另一条路径它必须实现真正的事件触发不能依赖轮询。我把漏水检测传感器的输出连接到nRF52832的GPIOTE通道配置为低电平触发事件。当检测到漏水时GPIOTE事件直接唤醒CPUCPU立即读取状态、启动警报上报整个过程不需要等待下一个采样周期。这套机制能保证漏水发生几秒钟内手机App就能收到告警通知。4.3 实测功耗数据与优化记录理论算得再好也要实测验证。我用J-Link的功耗测量工具实测了几组数据状态理论值实测值System OFF0.3µA0.6µASystem ON RTC1.9µA2.3µA采样射频发送峰值约25mA27mA实际平均功耗10µA8.4µA实测值和理论值基本符合但System OFF比理论高了一点排查发现是有颗GPIO引脚配置成了输入且悬空引脚漏电导致电流上升。把悬空引脚配置为输入上拉后电流恢复到了正常水平。GPIO引脚配置这个细节非常容易被忽略几乎所有低功耗产品的实测电流偏高都跟它有关。另外我强烈建议批量生产前对每块板子做功耗测试。功耗异常能在产线上就测出来远比等产品到用户手上才发现要划算得多。生产测试项里加一个待机电流小于15µA的判断逻辑一次测试只要几秒钟成本很低。5. 固件实现从SDK到业务逻辑再到DFU升级5.1 开发环境与工程结构我用的开发环境是SEGGER Embedded Studio配合nRF5 SDK 17.1.0SoftDevice用的S132。这套组合是目前最成熟稳定的方案。nRF Connect SDKNCS搭配Zephyr RTOS是新趋势如果是新项目我建议优先考虑NCS但老项目的SDK方案足够成熟没必要迁移。工程结构上我把代码分成了几个模块便于维护和复用project/ ├── ble/ # BLE服务实现、广播、连接管理 ├── app_sensors/ # 传感器驱动和数据处理 ├── app_business/ # 业务逻辑滤芯寿命、告警判断 ├── app_power/ # 低功耗管理与唤醒源处理 └── main.c # 主流程与事件分发业务逻辑不要在中断处理函数里执行这是个基本原则。我的做法是统一的Event Queue机制中断里只做事件标记主循环处理具体业务。这样避免了中断嵌套和阻塞也让代码更清晰。5.2 传感器读取与数据处理的关键代码逻辑传感器读取的核心是先稳定再采样。TDS传感器为例void tds_enable(bool on) { // 控制P-MOS开关给传感器供电 nrf_gpio_pin_write(TDS_POWER_PIN, on ? 0 : 1); if (on) { // 启动PWM输出1kHz交流激励 nrf_drv_pwm_enable(pwm_instance); } else { nrf_drv_pwm_disable(pwm_instance); } } uint16_t tds_read_mv(void) { uint16_t mv 0; // 传感器上电后延时200ms等待信号稳定 nrf_delay_ms(200); for (int i 0; i 8; i) { nrfx_saadc_sample(); mv nrfx_saadc_result_convert(adc_buffer[i]); } return mv / 8; // 多次采样取平均滤除干扰 }多次采样取平均可以有效抑制工频干扰和随机噪声。实测下来单次采样的TDS值波动有±30ppm取8次平均后波动降到±10ppm以内。条件允许的话在采样期间关闭Wi-Fi等干扰源设备数据会更稳定。pH值要做温度补偿。pH电极的输出电位受温度影响同一个溶液在不同温度下pH读数可能差0.1-0.3。我的处理方式是用NTC测水温在固件里用温度系数公式对pH做补偿。5.3 滤芯寿命算法与告警逻辑滤芯寿命是智能水处理系统的核心卖点之一。不能简单地按使用天数算因为不同家庭的用水量差别巨大。我的算法结合了使用天数累计流量两个维度。累计流量通过计数流量计脉冲得到。每次采样周期结束后固件读取累计流量值累加到当天流量中。滤芯剩余寿命按如下方式计算设定一个滤芯额定处理水量比如8000升同时设定一个最长使用周期比如12个月剩余寿命 min(剩余水量百分比, 剩余时间百分比)当剩余寿命低于10%时在App状态页提示即将更换滤芯当剩余寿命为0时推送请立即更换滤芯通知并允许用户选择已换新滤芯来重置寿命计数每次换完滤芯用户通过App写一个重置命令到控制服务特征值固件将累计流量计数清空重新开始计算。漏水告警增加了防抖机制。电极式传感器在沾水、凝露等情况下可能导致短暂误触发直接上报会造成用户困扰。我在固件里做了2秒防抖GPIOTE事件触发后启动一个软件定时器持续检测状态只有2秒后状态仍然是漏水才正式上报告警。5.4 DFU升级支持后续固件迭代产品出货后必然要面对固件升级的需求DFUDevice Firmware Update能力必须在一开始就设计进去。Nordic提供了Secure DFU bootloader方案支持手机App通过BLE空中升级固件。我的工程里把Flash做了分区Secure Bootloader占用一段区域SoftDevice占用一段Application占用其余区域。升级流程是App端先通过BLE写入新固件包到DFU临时区域校验无误后重启进入Bootloader模式完成固件替换然后重新启动运行新固件。这个过程中有几个注意点一是升级过程中绝对不能断电否则可能变砖所以我在App端做了电量检查低于30%禁止DFU二是DFU传输数据量大要用优化的连接参数缩短连接间隔来提高吞吐量三是DFU必须加签名认证防止恶意固件被刷入设备Nordic的Secure DFU支持基于公钥的签名校验。我在实际开发中遇到过一个问题DFU过程大约需要1-2分钟传输大固件时偶发失败。排查后确认原因是手机系统在后台挂起了BLE连接。解决办法是在DFU过程中使用Indicate方式确认每个包都收到同时增大发送的packet count减少ack开销。6. 常见问题与排查技巧实录6.1 App扫描不到设备怎么办这个问题我从调试到量产前前后后遇到过好几次原因各不相同。最典型的几个诱因第一广播没开。SoftDevice协议栈启动后默认不会自动广播必须在事件回调里调用广播初始化函数而且要在协议栈事件处理完成后才能调用。如果代码里漏了这步设备就隐形了。第二天线问题。天线匹配网络焊接不良、净空区被遮挡、PCB改版后匹配参数失效都会导致发射功率大幅下降。调试时用频谱仪看射频发射功率正常应该在0dBm附近如果差得太多就要查天线链路。第三32MHz晶振起振失败或频率偏移。晶振没起振芯片根本无法正常发射。这个比较隐蔽我吃过亏排查时可以用示波器测晶振引脚正常会看到正弦波如果频率不对就要检查负载电容和晶体参数。6.2 连接后频繁断开或数据延迟连接稳定性和手机系统有很大关系。Android系统的BLE协议栈兼容性层次不齐我在多台手机上测试发现某些老旧的华为、小米机型容易出现连接一段时间后自动断开的问题。排查思路是先抓包分析Nordic官方提供了BLE sniffer工具配合Wireshark可以分析连接参数协商过程、链路的RSSI变化以及是否有重传风暴。连接断开的常见原因还有供电问题。供电电压跌落会导致SoC在不稳定状态下运行。特别是电机泵启动瞬间电流尖峰可能导致电源电压跌落到3V以下。nRF52832的工作电压范围是1.7V-3.6V但如果电机泵和射频共用电源轨射频发射功率会在电压跌落时明显下降。我的解决办法是把RF的电源轨和电机的电源轨分开。RF部分用一个LDO单独供电并且在地平面做了分割。同时给电机驱动的MOS管加了软启动电路降低启动瞬间的电流冲击。6.3 TDS数据漂移与pH校准问题速查现象可能原因排查步骤TDS读数偏高且持续上漂电极极化检查激励信号是否为交流频率是否正常TDS读数波动大采样时机不对/未做平均检查采样是否在激励稳定区间增加采样子样数pH读数越来越不准电极老化/污染重新校准必要时更换电极pH校准无法通过温度补偿未启用确认温度传感器读数正常补偿公式正确漏水频繁误报凝露/水膜残留延长防抖时间检查检测电极间距流量计数不准确传感器安装位置不当确认叶轮转动方向与水流方向一致排除气泡干扰水质传感器的长期稳定性是个大问题。pH电极寿命有限通常6-12个月用户需要定期校准。我在App端加了校准引导功能提示用户把电极浸泡在标准缓冲液中App会读取稳定值并写入固件校准参数。这个功能上线后用户反馈非常好因为以前要打电话找售后现在自己就能完成。TDS传感器的长期漂移主要是电极污染造成的。我在硬件设计上把TDS传感器放在过滤系统的前置位置通过定期反冲洗的方式来清洁电极表面实测可以把传感器稳定寿命延长2倍以上。6.4 功耗异常偏高的排查经验如果实测待机电流超过几十µA优先按照这几条去排查用J-Link或万用表逐个测量关键节点的电流先断开传感器供电确认是否传感器漏电检查GPIO配置所有未使用引脚必须配置为输出低电平或输入上拉悬空的输入引脚是漏电重灾区检查DCDC是否真的启用了SoftDevice初始化时有一个专用于DCDC配置的调用如果没有调用芯片会强制运行在LDO模式功耗高30%左右检查是否有外设没有关闭。SDK里的TWI、SPI外设初始化后如果没有de-init会在背后持续消耗电流我印象最深的一次调试待机电流始终比理论值高20µA排查了很多天最后发现是SPI片选引脚被配置成输出高电平而SPI从设备芯片的电源是通过这个引脚拉高的导致从设备一直在工作。把片选引脚改回正常逻辑后待机电流一下降到2.5µA问题解决。这类问题通常会把人折磨到怀疑人生。我做这个项目的整体感受是IoT智能水处理系统的核心不只是把传感器数据传给手机更重要的是选对合适的无线方案、把功耗设计做到极致、把用户真正在意的告警和滤芯管理功能做好。Nordic这颗BLE SoC从芯片资源到协议栈成熟度都让我很满意尤其是在低功耗和DFU升级这两个环节帮我省了不少精力。最后分享一个实用的小技巧在样机调试阶段把RTC的唤醒周期改成30秒这样每次功耗测量、传感器数据验证都能快速看到结果不用等10分钟。正式发布时再改回10分钟的采样周期。这个方法能节省大量调试时间我从别的项目里学来的实测非常好用。