基于Zigbee协议的分布式漏水检测系统设计与实
前言
最近公司接了一个智慧楼宇的项目,需要在机房、卫生间、厨房等多个位置部署漏水检测装置。考虑到布线成本和后期维护问题,决定采用无线方案。经过几轮技术选型,最终选择了Zigbee协议——功耗低、组网稳定、适合多节点部署。
整个系统跑下来效果不错,这里把踩过的坑和关键实现分享出来。
系统架构
整个系统采用星型拓扑结构:
- 1个协调器(Coordinator):负责组网、数据汇聚、上报云端
- N个终端节点(End Device):部署在各个点位,检测漏水并上报
云平台/本地服务器|[Zigbee协调器]/ | \/ | \[节点1] [节点2] [节点3]...(厨房) (卫生间) (机房)
硬件选型
协调器端
- 主控: STM32F103C8T6
- Zigbee模块: CC2530(德州仪器)
- 通信接口: UART转USB,用于连接上位机
- 电源: 220V转5V适配器
检测节点
- 主控: STM32L051(低功耗系列)
- Zigbee模块: CC2530
- 漏水传感器: 自制电极式传感器
- 电源: 2节18650锂电池 + TP4056充电模块
- 报警: 蜂鸣器 + LED指示灯
核心原理
1. 漏水检测原理
采用电极式检测,两个金属电极间距5mm。正常情况下电极间电阻无穷大,当有水渗入时,水的导电性使电阻急剧下降。通过ADC采集分压电路的电压变化判断是否漏水。
硬件电路:
VCC(3.3V) ---[10K电阻]--- 检测点(ADC输入) ---[电极探头]--- GND
当有水时,电极短路,ADC读到的电压接近0V;无水时为3.3V左右。
2. Zigbee组网流程
协调器启动后建立PAN网络,终端节点扫描信道加入网络。这里用的是Z-Stack协议栈,版本是2.5.1a。
协调器端代码实现
主要文件结构
Coordinator/
├── main.c // 主程序
├── zigbee_coord.c // Zigbee协调器逻辑
├── uart_protocol.c // 与上位机通信协议
└── data_process.c // 数据处理
main.c - 协调器主程序
#include "stm32f10x.h"
#include "zigbee_coord.h"
#include "uart_protocol.h"
#include "systick.h"// 设备状态结构体
typedef struct {uint16_t short_addr; // 设备短地址uint8_t ieee_addr[8]; // IEEE地址uint8_t leak_status; // 漏水状态: 0-正常 1-漏水uint16_t battery_volt; // 电池电压(mV)uint32_t last_update; // 最后更新时间uint8_t online; // 在线状态
} device_info_t;#define MAX_DEVICES 32
device_info_t device_list[MAX_DEVICES];
uint8_t device_count = 0;// 系统初始化
void System_Init(void)
{NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);SysTick_Init();USART1_Init(115200); // 与上位机通信USART2_Init(115200); // 与Zigbee模块通信printf("Zigbee漏水检测协调器启动...\r\n");
}// 设备管理 - 添加或更新设备
void Device_Update(uint16_t short_addr, uint8_t *ieee_addr, uint8_t leak, uint16_t battery)
{int i;// 查找是否已存在for(i = 0; i < device_count; i++) {if(device_list[i].short_addr == short_addr) {device_list[i].leak_status = leak;device_list[i].battery_volt = battery;device_list[i].last_update = get_tick_ms();device_list[i].online = 1;return;}}// 新设备if(device_count < MAX_DEVICES) {device_list[device_count].short_addr = short_addr;memcpy(device_list[device_count].ieee_addr, ieee_addr, 8);device_list[device_count].leak_status = leak;device_list[device_count].battery_volt = battery;device_list[device_count].last_update = get_tick_ms();device_list[device_count].online = 1;device_count++;printf("新设备加入: 0x%04X\r\n", short_addr);}
}// 检查设备在线状态(超过60秒未上报视为离线)
void Device_CheckOnline(void)
{uint32_t now = get_tick_ms();for(int i = 0; i < device_count; i++) {if(device_list[i].online) {if(now - device_list[i].last_update > 60000) {device_list[i].online = 0;printf("设备离线: 0x%04X\r\n", device_list[i].short_addr);// 上报离线事件Upload_Device_Offline(device_list[i].short_addr);}}}
}int main(void)
{System_Init();Zigbee_Coord_Init(); // 初始化Zigbee协调器printf("开始建立网络...\r\n");Zigbee_StartNetwork();uint32_t last_check = 0;while(1){// 处理Zigbee接收数据Zigbee_Process();// 处理上位机命令UART_Process();// 定时检查设备在线状态if(get_tick_ms() - last_check > 5000) {Device_CheckOnline();last_check = get_tick_ms();}