☰
基于ZigBee的温室大棚智能监控系统:毕业设计完整方案与C源码解析
2026/10/28 16:15:23 网站建设 项目流程

简介:这份资源是面向计算机、通信工程、自动化等专业学生与嵌入式初学者的ZigBee温室大棚智能监控系统完整毕业设计资料,可用于课程设计、项目立项演示或实际开发参考。项目采用C语言编写,下位机由两个搭载DHT11的ZigBee终端节点完成温湿度采集,上位机通过协调器连接GEC6818开发板接收并显示远程数据,实现环境监控、超温报警与LED灯光控制:温度超过27度时自动熄灭全部灯光、蜂鸣器报警并显示具体节点与即时温度信息。压缩包共24个文件,约7.08MB,包含C源码、头文件、Makefile、驱动模块、字体库、位图素材及项目说明文档,代码均经测试运行成功,答辩评审平均分达94.5分。目前已有1275人学习下载,适合在现有代码基础上二次开发扩展功能。

1. 温室大棚智能监控系统:ZigBee 方案为什么在毕业设计里还能打

如果你正在做物联网工程毕业设计或者电子信息工程毕业设计,大概率刷到过这个标题——基于 ZigBee 的温室大棚智能监控系统,附带完整 C 源码、代码注释和项目说明文档。它解决的是一个非常具体的问题:把大棚里的温度、湿度、光照、土壤水分这些参数采集上来,通过无线网络汇总到网关,再在本地或上位机上做显示、报警和简单控制。适合谁?适合单片机毕业设计、物联网毕业设计方向,手头有 CC2530 或类似 ZigBee 模块,想找一个能跑通、能写论文、能答辩的完整方案的人。

为什么现在 ESP32-C6 都带 ZigBee 了,还在讲老方案?因为毕业设计的核心不是追新,是可控。ZigBee 自组网、低功耗、多节点这几个特性,恰好能撑起论文里的“系统设计”章节。你不需要从零造轮子,但必须理解每一层在干什么,否则代码注释写得再全,答辩时一问就露馅。这篇笔记就按“这是什么→怎么跑→坑在哪→怎么改”的顺序,把整套东西拆开讲清楚。

2. ZigBee 温室监控系统的组网逻辑与最小硬件清单

2.1 为什么是 ZigBee 而不是 Wi-Fi 或蓝牙

大棚环境有几个硬约束:节点分散、供电不方便、金属棚架多、需要穿墙。Wi-Fi 功耗高,组网数量一多路由器就撑不住;蓝牙距离太短,穿墙更差。ZigBee 工作在 2.4GHz,虽然也怕金属遮挡,但支持 Mesh 自组网,一个节点挂了其他节点还能绕路,这是它在农业场景里最实在的优势。

从协议栈看,ZigBee 建立在 IEEE 802.15.4 之上,物理层和 MAC 层由芯片硬件处理,你写的 C 代码主要跑在应用层和网络层。常见做法是用 TI 的 Z-Stack 协议栈,CC2530 作为协调器或终端节点。协调器负责建网,终端节点负责采集和发送,路由器节点负责中继。毕业设计里通常一个协调器加两到三个终端,够演示就行。

提示:如果你用的是 CC2530 模块,注意它分 CC2530F32/F64/F128/F256,Flash 大小决定你能不能跑完整 Z-Stack。F256 最稳,F128 勉强,F32 基本只能跑精简版。

2.2 最小系统硬件清单与接线

一套能跑通的最小系统,硬件清单如下表。别急着买最贵的,先确认手头模块的引脚定义。

部件常见型号作用注意点
ZigBee 模块CC2530 核心板组网与数据传输确认带天线座还是 PCB 天线
传感器DHT11 / DS18B20温湿度采集DHT11 时序敏感,DS18B20 更稳
光照传感器BH1750光照强度I2C 接口,注意上拉电阻
土壤湿度电阻式或电容式土壤水分电阻式易腐蚀,电容式贵一点
网关主控STM32 或 USB 转串口协调器数据汇总协调器可直接接电脑串口
电源5V 转 3.3V给模块供电CC2530 必须 3.3V,5V 会烧

接线逻辑:终端节点上,传感器接 CC2530 的 GPIO 或 ADC 引脚,DHT11 接一个普通 IO,DS18B20 接另一个 IO 并加 4.7k 上拉。协调器通过串口和电脑或 STM32 通信,波特率一般设 115200。如果你用 USB 转串口模块,TX/RX 要交叉接,GND 必须共地。

2.3 数据流从传感器到上位机的完整路径

数据流向是这样的:终端节点上电后加入协调器创建的网络,然后周期性读取传感器,把数据打包成 ZigBee 应用层帧,通过无线发给协调器。协调器收到后,通过串口把数据转发给上位机。上位机可以是 Qt 写的桌面程序,也可以是 Python 脚本,甚至串口助手。

这里的关键是数据格式。常见做法是自定义一个简单的帧结构,比如:帧头 0xAA + 节点地址 + 温度 + 湿度 + 光照 + 土壤 + 校验和。协调器不做复杂解析,直接透传,上位机再拆包。这样终端节点的 C 代码最简单,也最容易调试。

注意:ZigBee 模块的短地址是协调器分配的,不是固定的。如果你在上位机里用短地址区分节点,每次重启网络地址可能变。稳妥做法是用 IEEE 地址,或者让终端节点主动上报自己的编号。

3. 终端节点 C 源码拆解:传感器读取与无线发送

3.1 传感器驱动层的写法与参数

先看 DHT11 的读取。DHT11 是单总线协议,对时序要求很高,Z-Stack 里如果直接关中断读,可能影响网络通信。常见做法是读的时候短暂关中断,读完立刻开。下面是一个可用的 DHT11 读取函数框架:

// DHT11 数据引脚定义,根据实际接线修改 #define DHT11_PIN P0_7 // 读取 DHT11 温湿度,成功返回 0,失败返回 1 uint8 dht11_read(uint8 *temp, uint8 *humi) { uint8 buf[5] = {0}; uint8 i, j; // 主机发送开始信号:拉低至少 18ms DHT11_PIN = 0; delay_ms(20); DHT11_PIN = 1; // 等待 DHT11 响应,超时则退出 delay_us(30); if (!DHT11_PIN) { while (!DHT11_PIN); // 等待 80us 低电平结束 while (DHT11_PIN); // 等待 80us 高电平结束 // 读取 40 位数据 for (i = 0; i < 5; i++) { for (j = 0; j < 8; j++) { while (!DHT11_PIN); // 等待 50us 低电平 delay_us(40); // 延时 40us 判断高电平长短 buf[i] <<= 1; if (DHT11_PIN) { buf[i] |= 1; while (DHT11_PIN); // 等待剩余高电平结束 } } } // 校验:前四字节之和等于第五字节 if (buf[0] + buf[1] + buf[2] + buf[3] == buf[4]) { *humi = buf[0]; *temp = buf[2]; return 0; } } return 1; }

逻辑说明:先拉低总线至少 18ms 让 DHT11 检测到开始信号,然后释放总线,DHT11 会拉低 80us 再拉高 80us 作为响应。之后每一位数据以 50us 低电平开始,高电平持续时间决定是 0 还是 1——26-28us 是 0,70us 是 1。代码里用delay_us(40)采样,如果还是高电平就判为 1。参数上,delay_ms和delay_us的精度直接影响成功率,建议用定时器做延时,不要用空循环。

DS18B20 的读取更稳定,因为它有 CRC 校验,时序容错更好。如果你对稳定性要求高,优先用 DS18B20。光照 BH1750 走 I2C,直接读寄存器就行,注意初始化时发送连续测量命令。

3.2 ZigBee 应用层发送函数的参数配置

传感器数据读完后,要发给协调器。Z-Stack 里发送数据用AF_DataRequest,这是应用框架层的接口。下面是一个发送示例:

// 发送传感器数据到协调器 void send_sensor_data(uint8 temp, uint8 humi, uint16 light, uint8 soil) { uint8 payload[8]; afAddrType_t dstAddr; // 目标地址:协调器短地址固定为 0x0000 dstAddr.addrMode = afAddr16Bit; dstAddr.addr.shortAddr = 0x0000; dstAddr.endPoint = 10; // 目标端点,需与协调器一致 // 组装数据帧 payload[0] = 0xAA; // 帧头 payload[1] = temp; // 温度 payload[2] = humi; // 湿度 payload[3] = (uint8)(light >> 8); // 光照高字节 payload[4] = (uint8)(light & 0xFF); // 光照低字节 payload[5] = soil; // 土壤湿度 payload[6] = 0x55; // 帧尾 // 发送:端点 10,簇 ID 0x0001,长度 7,不等待应答 AF_DataRequest(&dstAddr, &endPointDesc, 0x0001, 7, payload, &transID, AF_DISCV_ROUTE, AF_DEFAULT_RADIUS); }

逻辑说明:afAddrType_t里addrMode设为afAddr16Bit表示用短地址寻址,协调器短地址固定 0x0000。endPoint是端点号,终端和协调器必须一致,否则收不到。AF_DataRequest的参数依次是目标地址、源端点描述、簇 ID、数据长度、数据指针、事务 ID、发现路由选项、最大跳数。簇 ID 可以自定义,比如 0x0001 表示传感器数据。

参数怎么改:如果网络节点多,AF_DEFAULT_RADIUS可以设大一点,默认是 5 跳。AF_DISCV_ROUTE表示发送前先发现路由,如果网络稳定可以去掉这个选项加快发送。transID是事务 ID,每次发送后自增,用来匹配应答。

提示:如果你发现协调器收不到数据,先检查端点号是否一致,再检查簇 ID 是否匹配。这两个是最容易翻车的地方。

3.3 低功耗与发送周期的取舍

终端节点如果电池供电,发送周期不能太短。DHT11 一次采集加发送大概几十毫秒,如果每 2 秒发一次,纽扣电池撑不了几天。常见做法是 30 秒到 1 分钟发一次,中间让 CC2530 进入 PM2 低功耗模式。但要注意,进入低功耗后定时器唤醒要配置好,否则一睡不醒。

如果你只是做毕业设计演示,直接 USB 供电,发送周期设 2 秒也没问题,数据刷新快,答辩好看。但论文里要提一句低功耗设计,把 PM2 模式和唤醒机制写进去,这是加分项。

4. 协调器与上位机联调:串口协议和数据显示

4.1 协调器串口转发代码的关键配置

协调器收到无线数据后,要通过串口发给上位机。Z-Stack 里串口初始化一般在MT_UartInit或自己写的HalUARTInit里。关键参数:波特率 115200,8 位数据位,1 位停止位,无校验。下面是一个串口发送函数:

// 协调器串口发送数据到上位机 void uart_send_to_pc(uint8 *data, uint8 len) { uint8 i; for (i = 0; i < len; i++) { // 等待发送缓冲区空 while (!(U0CSR & 0x02)); U0DBUF = data[i]; } }

逻辑说明:U0CSR是 CC2530 的串口控制寄存器,bit1 是 TX 完成标志。U0DBUF是发送缓冲区。这个函数是阻塞式的,数据量小没问题,数据量大建议用中断或 DMA。参数上,波特率由U0GCR和U0BAUD寄存器决定,115200 对应的值在 Z-Stack 里有宏定义,直接改宏就行。

协调器收到数据后,在应用层回调函数里调用uart_send_to_pc,把 payload 原样转发。上位机收到后按帧头帧尾拆包。

4.2 上位机 Python 解析脚本与显示

上位机用 Python 最省事,pyserial 加 matplotlib 就能做实时曲线。下面是一个最小解析脚本:

import serial import struct # 打开串口,根据实际端口修改 ser = serial.Serial('COM3', 115200, timeout=1) def parse_frame(data): """解析传感器帧:0xAA + 温度 + 湿度 + 光照高 + 光照低 + 土壤 + 0x55""" if len(data) == 7 and data[0] == 0xAA and data[6] == 0x55: temp = data[1] humi = data[2] light = (data[3] << 8) | data[4] soil = data[5] return temp, humi, light, soil return None while True: # 读取 7 字节 raw = ser.read(7) if len(raw) == 7: result = parse_frame(raw) if result: print(f"温度:{result[0]}℃ 湿度:{result[1]}% 光照:{result[2]}lx 土壤:{result[3]}")

逻辑说明:ser.read(7)每次读 7 字节,和帧长度一致。parse_frame先检查帧头帧尾,再按大端模式合成光照值。参数上,COM3要改成你电脑上实际的串口号,Windows 在设备管理器看,Linux 一般是/dev/ttyUSB0。timeout=1防止读不到数据时卡死。

如果要画实时曲线,用 matplotlib 的FuncAnimation,每 100ms 更新一次。注意串口读取要放在单独线程,否则界面会卡。

4.3 联调时先看串口助手再看代码

联调顺序很重要。先别急着跑上位机,先用串口助手看协调器有没有输出。如果没有,检查三件事:协调器有没有建网成功、终端有没有入网、端点号是否一致。串口助手能看到原始字节,比上位机更容易定位问题。

如果串口助手有数据但上位机解析不出来,多半是帧头帧尾对不上,或者波特率不一致。用十六进制模式看,确认 0xAA 和 0x55 的位置。这一步是血泪经验,很多人卡在“数据明明发了但上位机没反应”,最后发现是上位机读的字节数不对。

5. 避坑与排查:ZigBee 温室监控系统最常见的 5 个翻车点

5.1 终端节点入不了网,协调器一直显示 0 个节点

现象:协调器上电后串口打印“网络建立成功”,但终端节点上电后一直入不了网,协调器显示节点数为 0。

原因:最常见的是 PAN ID 和信道不匹配。协调器建网时随机选了一个信道,终端节点如果固定了信道,可能对不上。另外,终端节点的DEVICE_TYPE如果设成了协调器,也会冲突。

解决:把协调器和终端的 PAN ID 都设成固定值,比如 0x1234,信道也固定,比如 11。在f8wConfig.cfg里改-DZDAPP_CONFIG_PAN_ID=0x1234和-DDEFAULT_CHANLIST=0x00000800(对应信道 11)。改完重新编译烧录。

5.2 DHT11 读出来全是 0 或者 255

现象:终端节点发送的数据里,温度湿度一直是 0 或者 255,其他传感器正常。

原因:DHT11 时序没对上,或者引脚定义错了。DHT11 对延时精度要求高,如果delay_us用空循环实现,编译器优化等级一变,延时就不准了。

解决:把延时函数改成定时器实现,或者用_nop_()精确控制。另外确认 DHT11 的数据引脚和代码里DHT11_PIN定义一致。如果还不行,换 DS18B20,时序容错好很多。

5.3 协调器串口输出乱码

现象:串口助手收到一堆乱码,不是预期的十六进制帧。

原因:波特率不对,或者串口时钟配置错了。CC2530 的波特率由U0GCR和U0BAUD决定,如果用了 32MHz 晶振但配置按 26MHz 算,就会乱码。

解决:确认晶振频率,在hal_board_cfg.h里检查HAL_UART_BAUDRATE宏。常见做法是直接用 Z-Stack 提供的MT_UartInit,它会根据系统时钟自动算。如果自己写,参考 CC2530 数据手册的波特率表。

5.4 上位机曲线卡顿或数据丢包

现象:Python 上位机画曲线时界面卡死,或者数据跳变严重。

原因:串口读取和绘图在同一个线程,绘图阻塞了串口读取。另外,如果发送周期太短,串口缓冲区溢出也会丢包。

解决:串口读取放单独线程,用队列传给绘图线程。发送周期建议不低于 1 秒。如果还丢包,在协调器端加一个简单的流控,或者降低发送频率。

5.5 烧录后模块不工作,但仿真正常

现象:代码在 IAR 里仿真跑得好好的,烧录到模块后没反应。

原因:仿真时用的是调试器供电,烧录后模块可能供电不足。CC2530 发射时电流能到 30mA,如果 USB 转串口模块供电不够,就会复位。

解决:给模块单独供电,或者用带外部供电的 USB Hub。另外检查烧录选项里有没有勾选“擦除后编程”,有时候没擦干净会导致运行异常。

6. 从能跑到能答辩:把 ZigBee 温室监控系统改出论文亮点

6.1 加一个简单的阈值报警和自动控制

基础版跑通后,加报警和控制是性价比最高的改动。在协调器或上位机里设阈值,比如温度高于 35℃ 就报警,土壤湿度低于 30% 就打开水泵。硬件上加一个继电器模块,终端节点收到控制命令后拉高 GPIO。

代码改动很小:在协调器的应用层回调里判断数据,超过阈值就通过串口发一个报警帧给上位机,同时可以反向发一个控制命令给终端。终端节点加一个AF_DataRequest的接收回调,收到命令后控制继电器。这样论文里就有了“闭环控制”章节,比纯采集高一个档次。

6.2 用 IEEE 地址替代短地址做节点标识

前面提过短地址会变,答辩时如果老师问“你怎么区分不同大棚的节点”,用短地址就答不上来。改成 IEEE 地址,每个模块出厂有唯一的 64 位地址,在终端节点入网后主动上报自己的 IEEE 地址和编号,协调器维护一个映射表。

实现上,在终端节点入网回调里调用NLME_GetExtAddr()获取 IEEE 地址,然后通过AF_DataRequest发给协调器。协调器收到后存到数组里,上位机显示时用编号而不是短地址。这个改动不大,但论文里可以写“节点身份管理”,显得有设计。

6.3 数据存储与历史查询的轻量方案

上位机加一个 SQLite 数据库,每秒或每分钟存一条记录。Python 自带sqlite3模块,不用装额外东西。建一张表:CREATE TABLE sensor_data (id INTEGER PRIMARY KEY, node_id INTEGER, temp INTEGER, humi INTEGER, light INTEGER, soil INTEGER, time TIMESTAMP DEFAULT CURRENT_TIMESTAMP);插入语句用参数化查询,防止注入。

查询时按时间范围查,用 matplotlib 画历史曲线。这样论文里就有了“数据存储与查询”模块,而且 SQLite 文件可以直接放进答辩材料里,老师能看到实际数据。

6.4 答辩时老师最可能问的三个问题

第一个:“为什么用 ZigBee 不用 Wi-Fi?” 答:低功耗、自组网、节点容量大,适合大棚这种分散场景。第二个:“数据丢了怎么办?” 答:ZigBee 有应答机制,应用层也可以加帧序号和重传。第三个:“你的创新点在哪?” 答:加了阈值报警和自动控制,做了 IEEE 地址管理,上位机有历史数据存储。这三个问题提前准备好,答辩基本稳。

我自己的习惯是,每次做完一个毕业设计,都把踩过的坑记在一个文本文件里,下次直接翻。ZigBee 这套东西不新,但胜在稳定、资料多、能复现。如果你手头有模块,今晚就能把终端节点和协调器跑通。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询