
简介一份基于Python的大棚监测系统毕业设计项目面向计算机、物联网或农业信息化相关专业学生适用于课程设计、毕业设计及物联网入门实践。项目围绕现代农业温室场景覆盖环境数据采集、传感器驱动、设备自动控制等核心环节包含温湿度采集、步进电机驱动、DHT11传感器读取等Python实现并配套完整的设计说明书方便理解系统架构与编码思路。资源包共4个文件包含3个Python源文件和1个Word文档整体压缩包大小仅8.64MB脚本负责具体功能实现文档用于描述需求分析、模块划分与测试结果。目前该资源已有655人学习下载适合正在筹备毕业设计或希望结合Python与硬件开发的学习者。通过此项目可以快速搭建大棚监测原型掌握PySerial、DHT11库、设备控制及简易界面设计等关键技能为后续扩展云端平台或更多传感器提供清晰基础。同时还能锻炼系统集成与调试能力对智慧农业相关实践有直接帮助。1. 为什么说Python大棚监测系统是毕业设计里的“硬核选题”很多人接到“Python大棚监测系统毕业设计”这个题目后第一反应是先画页面再处理传感器数据这个顺序恰恰反了。真正的难点在传感器数据经由串口进入Python之后的这一段帧怎么解析、设备断线程序会不会假死、连续采集几个小时数据库还扛不扛得住。这篇内容按一条完整数据链路展开从单片机采集温度、湿度、土壤水分和光照经USB转串口进入Python程序再由SQLite存储最后用Flask完成可视化与阈值告警。代码和参数按“先说明取舍原因、再给可运行片段”的方式组织可以直接抄进自己的工程也能用来回答答辩现场关于边界和参数的追问。2. 硬件选型与串口链路传感器信号怎么稳妥进Python2.1 先把系统拆成三层再谈选型大棚监测系统本质上是一条数据管道不是“网页加接口”两级结构就能写清楚的。我一般把链路分成三层各层之间只通过固定格式的帧传递数据不在代码里互相调用。底层是传感器与MCU把空气温湿度、土壤湿度、光照强度这些物理量统一采集按固定周期整理成一条文本帧经USB转TTL发给上位机中间层是Python的串口采集程序只负责读帧、验帧、入SQLite不做业务判断应用层再做阈值计算、告警推送和页面展示。这样划分之后“传感器断电了”和“采集程序崩了”就分属两个独立的故障域。答辩问“某层出了问题系统怎么表现”可以直接指到代码里对应的try/except位置。很多毕业设计失控就是因为把这几层职责揉在同一个while循环里传感器一断开告警和Web接口全部跟着卡死这种代码在评阅阶段就会被画问号。2.2 传感器选型与信号输出方式的取舍毕设选传感器要挑“输出方式清晰”的贵的传感器不如接口好懂的传感器。监测参数常用元件数据出口选型注意点空气温湿度DHT22 / SHT30由MCU统一出帧DHT22便宜但读取间隔不要小于2秒土壤湿度电容式土壤湿度模块ADC数字量电容式不易生锈供电稳定后输出才稳定光照强度BH1750I2C转串口帧直接读lux不必校准LDR需要自己标定CO2浓度MH-Z19BUART直接输出上电后需2-3分钟预热预热数据不要入库我习惯让MCU统一以JSON文本帧方式输出每帧形如{temp:25.3,humi:60.2,soil:38,lux:12000}2秒一封。这样Python端只处理串口文本协议不必去解析DHT22那种复杂的单总线时序也方便后面用模拟数据源替换真实MCU。2.3 串口参数匹配与最小连接程序连接之前两侧的串口参数必须一致这是毕业设计里最常见的“乱码源头”。import serial ser serial.Serial( portCOM4, # Windows下填设备管理器里的COM号 baudrate115200, # 必须和MCU固件里设置的波特率相同 bytesize8, parityN, # 无校验位也有设备用E偶校验 stopbits1, timeout1.0 # 无数据时1秒返回避免readline一直阻塞 ) raw ser.readline() print(raw.hex()) ser.close()串口参数的五个值对应PySerial里的baudrate、bytesize、parity、stopbits、timeout任何一个不匹配都读不到可解析内容。先打印十六进制而不是直接按字符串解码是为了确认设备发的真是文本还是带有二进制头如果输出是空列表优先检查驱动有没有让系统识别出COM口。3. 采集、入库与调度把温湿度数据稳定写进SQLite3.1 建表结构与写入数量级SQLite在毕业设计里是足够的选择单文件可带走宿主机不需要额外装数据库服务。表结构建议按“原始数据表加聚合表”两条路走先建原始表CREATE TABLE sensor_readings ( id INTEGER PRIMARY KEY AUTOINCREMENT, ts TEXT DEFAULT (datetime(now, localtime)), temp REAL, humi REAL, soil INTEGER, lux INTEGER ); CREATE INDEX idx_ts ON sensor_readings(ts);datetime(now,localtime)把时区换算交给SQLite避免Python侧对时间做偏移。idx_ts的用途是加快时间范围查询页面趋势图的SQL基本都是WHERE ts BETWEEN ? AND ? ORDER BY ts。数据量只有几百条时索引作用不明显连采48小时表里上万行索引带来的差异就能体现出来。3.2 带重连与容错的采集主循环采集进程是系统里运行时间最长的一段主循环只处理三件事过滤非法帧、串口重连、保持写入顺序。import json import sqlite3 import time import serial def parse_frame(line: bytes): try: text line.decode(utf-8).strip() data json.loads(text) # 强制类型转换避免字符串25.3直接进入REAL字段 return { temp: float(data[temp]), humi: float(data[humi]), soil: int(data[soil]), lux: int(data[lux]), } except (UnicodeDecodeError, ValueError, KeyError, json.JSONDecodeError): return None def insert_one(conn, row): conn.execute( INSERT INTO sensor_readings(temp, humi, soil, lux) VALUES (?, ?, ?, ?), (row[temp], row[humi], row[soil], row[lux]), ) conn.commit() def main(): conn sqlite3.connect(greenhouse.db) while True: try: with serial.Serial(COM4, 115200, timeout2) as port: while True: line port.readline() row parse_frame(line) if row: insert_one(conn, row) except serial.SerialException: # 串口拔掉或驱动异常时不退出进程5秒后重试 time.sleep(5) if __name__ __main__: main()这段代码有两个容易抄错的地方。第一float()和int()的强制转换放在try块内原始帧里出现非法值时只丢这一帧不会中断主循环第二内层循环用with语句保证异常时串口资源能释放,外层的大while True负责重新建立连接。贴到毕业设计里时“串口拔出再插回程序能自动恢复”会是一个很加分的演示点。提示采集频率不要轻易改成1秒一帧先确认MCU串口输出能力和SQLite写入速度。2秒一帧的取值对真实大棚场景足够对答辩演示也稳定。3.3 定时调度循环、线程还是APScheduler采集只有一个循环时不需要调度器如果系统要同时做“每30分钟生成统计桶”“每天8点发日报”“每秒探测一次心跳”建议直接引APScheduler。方式任务间隔粒度代码量适用场景while time.sleep基本固定间隔最少单一采集任务threading.Timer线程级并行中采集之外还要跑独立告警APSchedulercron/interval/date三种触发器多但易维护统计、报表与告警共存间隔触发场景推荐用BackgroundScheduler而不阻塞采集主线程from apscheduler.schedulers.background import BackgroundScheduler def summary_job(): print(生成最近10分钟平均温度) sched BackgroundScheduler() sched.add_job(summary_job, interval, minutes10, idsummary) sched.start()id参数建议必填后期对同一任务做替换或取消时按id定位会可靠得多。BackgroundScheduler会把任务放进线程池采集主循环继续正常读串口。3.4 高频写入时的重复数据处理方法2秒一个样本的原始数据直接画成曲线会非常密而且温度传感器的瞬时抖动会被当成真实波动。常见的稳定做法是另建一张分钟聚合表CREATE TABLE sensor_readings_min ( ts_min DATETIME PRIMARY KEY, avg_temp REAL, avg_humi REAL, max_lux INTEGER, sample_count INTEGER );聚合任务每隔60秒执行一次用strftime(%Y-%m-%d %H:%M, ts)做时间窗口分组同步计算平均值和最大值。页面默认读聚合表原始表留下来做校验和回放。这个“一采一聚”的结构在论文里能单独写一小节设计说明评阅老师看到你认为自己对数据量级有概念而不是无脑把所有点塞进图表。4. 阈值告警与Flask可视化把监控页面做成能讲解的完整闭环4.1 阈值表与回滞参数避免告警抖动告警的初版逻辑往往是“超过阈值就推送”实测在温室环境下温度在阈值附近来回波动时告警会在几十秒内反复触发和解除。我给每项参数加了一个recover回滞值让触发值和恢复值错开。THRESHOLDS { temp: {lower: 10.0, upper: 35.0, recover: 2.0}, humi: {lower: 40.0, upper: 85.0, recover: 5.0}, }温度高于35℃才报警降到33℃upper减去recover以下才恢复。湿度低于40%报警升到45%以上才算解除。对整套大棚控制逻辑来说这个设计能减少大量无效告警也是一个答辩时容易讲清楚的小细节。4.2 Flask读取SQLite按时间范围取数的接口页面后端用Flask两个路由就够首页渲染模板/api/latest返回最近N条时间戳数据。from flask import Flask, jsonify, render_template import sqlite3 app Flask(__name__) DB_PATH greenhouse.db def query_recent(limit120): conn sqlite3.connect(DB_PATH) rows conn.execute( SELECT ts, temp, humi, soil, lux FROM sensor_readings ORDER BY id DESC LIMIT ?, (limit,) ).fetchall() conn.close() return list(reversed(rows)) # 翻回时间正序 app.route(/) def index(): return render_template(dashboard.html) app.route(/api/latest) def latest(): rows query_recent(120) return jsonify([ {ts: r[0], temp: r[1], humi: r[2], soil: r[3], lux: r[4]} for r in rows ])用ORDER BY id DESC LIMIT n取尾部数据再反转比直接ORDER BY id ASC带上限扫描更省内存。SQLite连接采用短开短关避免Flask多线程下共用连接对象时报错这个细节能减少开发模式里很多干扰信息。4.3 前端用ECharts做5秒轮询前端图表库选ECharts折线图只保留最近120个点轮询间隔5秒async function refresh() { const resp await fetch(/api/latest); const data await resp.json(); chart.setOption({ xAxis: { data: data.map(d d.ts) }, series: [{ name: 温度, data: data.map(d d.temp) }] }); } setInterval(refresh, 5000);首次调用放在setInterval之前页面一加载就有图5秒的间隔对演示友好轮询过短只会让ECharts动画频繁重排。前端不直连数据库坚持只走HTTP接口后端换存储结构时前端不用跟着改。4.4 告警通道对比SMTP稳定可靠群机器人直观通道部署成本演示效果备注日志文件最低需要现场翻文件只适合调试阶段SMTP邮件低手机邮箱收信直观需要邮箱开启SMTP授权码群机器人中最直观但依赖外网服务演示前提前配置好我一般用SMTP邮件来保证稳定触发示例如下import smtplib from email.message import EmailMessage def send_alert(subject: str, body: str): msg EmailMessage() msg[Subject] f[大棚告警] {subject} msg[From] senderexample.com msg[To] [recipientexample.com] msg.set_content(body) with smtplib.SMTP_SSL(smtp.example.com, 465, timeout10) as server: server.login(senderexample.com, SMTP授权码) server.send_message(msg)465端口对应SSL加密连接还有不少邮件服务用587端口加STARTTLS换成smtplib.SMTP后再启动TLS即可。注意邮箱的授权码与登录密码是两个东西不要直接把账号密码写进代码。注意不同邮箱服务商的SMTP端口和授权码名称有差异以对应服务商帮助文档为准。5. 打包与验证把r.ar交付物做成能拆也能跑的毕业设计评阅老师拿到的“python项目大棚监测系统毕业设计.r.ar”解压后至少应该有三样东西源代码、requirements.txt、README。README里写清“运行前提”“创建虚拟环境”“启动命令”三句话能省掉答辩现场一大半的回家折腾。5.1 锁依赖与目录组织python -m venv .venv .venv\Scripts\activate # Windows 环境 pip install pyserial flask apscheduler requests pip freeze requirements.txt用pip freeze而不是手写包名能保证交出去的版本清单和实测环境完全一致。数据库文件greenhouse.db可以附一份带数据的副本评阅老师解压后不用等传感器采集打开页面就能看到趋势图。5.2 演示前必查的三个位置检查项故障表现现场处理服务端口是否被占用Flask启动报Address already in use换端口或结束占用进程环境变量与路径SQLite报no such table代码统一用绝对路径拼接数据库文件依赖是否缺失ModuleNotFoundError现场执行pip install -r requirements.txt做完三项检查再走一遍“启动采集、打开页面、拔掉串口、插回串口”四步。拔插串口的恢复演示比任何静态截图都有说服力因为评委看的是程序行为不是页面外观。5.3 无硬件回放十分钟的持续演示如果现场没有真实传感器可以用生成器模拟数据帧接在采集循环入口就行def mock_source(rows): for row in rows: yield json.dumps(row).encode(utf-8) time.sleep(2)把原先从port.readline()取数据的地方换成从mock_source取采集、入库、页面、告警四层链路都真实运行只有数据源被替换。这个技巧的成本不到十行代码但它让整个系统在没有硬件时依然可以完整演示“数据采集、入库、展示”的核心闭环还能顺带验证4.2节的接口和4.3节的图表刷新是否正常工作。本文还有配套的精品资源点击获取