☰
智能养花系统:从ESP32到微信小程序的物联网闭环实战
2026/10/22 4:07:10 网站建设 项目流程

简介:一份面向计算机类毕业设计与课程作业的智能养花系统源码包,基于微信小程序搭建,覆盖环境监测、设备控制、数据分析与用户交互等环节,适合需要完整项目参考、进行二次开发或学习人工智能落地的本科生。压缩包共33个文件,约962KB,以json配置、js逻辑、wxss样式、wxml页面及png/jpg图像为主,另含md说明文档,可清晰还原小程序从页面结构到交互逻辑的实现路径。已有102人学习下载,具备一定的参考价值。借助这份源码,可快速掌握前后端数据交互、硬件接口模拟、物联网通信以及图表展示等关键模块,同时通过目录与注释梳理毕业设计文档撰写和系统构建思路,为课程作业或毕设答辩提供扎实支撑。

1. 智能养花系统:课程作业里的人工智能与物联网闭环

做毕设或课程设计时,最怕的不是没想法,而是想法太大、落地太散。“智能养花系统”听起来像 AI 算法项目,放到压缩包里看,其实是一个典型的物联网工程:传感器采集环境数据,后端做判断,微信小程序做展示和控制,再把指令回传给执行设备。把这条链路走通,答辩时就有完整的端到端演示。这个资源包里带了微信小程序工程、project.config.json 和整套源码,适合两类人:一类是正在为毕设选题发愁的学生,另一类是已经做完基础功能、想看看别人怎么组织“感知—决策—执行”三层的开发者。

2. 系统分层与硬件选型:感知、决策、执行三条链路怎么串

打开这个包,第一眼看到的是微信小程序代码,但小程序只是整个系统的冰山一角。我在拆这套代码的时候,习惯先把系统拆成三条链路:感知链路负责采集温湿度、土壤湿度和光照,决策链路跑在后端服务里,执行链路控制水泵和补光灯。三条链路串起来,才算是一个完整的智能养花系统。

2.1 分层设计:三类端点各管一段

感知端最常见的主控是 ESP8266 或 ESP32。这个级别的毕设项目通常用 MicroPython 写设备端,改动起来快,串口调试也直接。传感器方面,温度和湿度用 DHT11 或 DHT22,土壤湿度用两针的电容式探头,光照用光敏电阻模块或者 BH1750 数字光照传感器。DHT11 便宜但误差大一点,DHT22 贵一些,精度能到正负 0.5 度,课程演示的话 DHT11 够用。

决策端是后端服务。我一般会用一个 Flask 轻量服务来接收数据、跑判断逻辑、下发控制指令。选 Flask 而不是 Spring Boot,原因很简单:这个场景的并发量极低,不需要重型框架,Flask 路由写起来快,模型和逻辑都在一个文件里就能看明白。应用端就是微信小程序,负责展示实时数据、历史曲线,以及手动开关水泵和补光灯。

2.2 通信选型:为什么优先走 HTTP 长轮询而不是 MQTT

很多同学一上来就选 MQTT,觉得物联网项目不用消息协议不够高级。但实际上 MQTT 需要自己搭建 Broker,微信小程序端又不原生支持 MQTT over WebSocket,调试成本会明显上升。我的建议是走 HTTP 轮询:设备端每 5 秒 POST 一次环境数据到后端,小程序端每次进入页面或下拉刷新时拉取最新数据,控制指令也通过 HTTP 下发。

这个方案在教务演示场景里足够稳定,而且把数据链路简化为“设备上报 + 服务端存储 + 小程序拉取”,哪一段出问题都好排查。我在实际项目里见过因为强行上 MQTT 导致课程作业翻车的情况——Broker 崩了,整个演示只能干等。毕设评分看的是完整闭环,不是协议栈的深度。

2.3 设备端初始化:传感器校准与数据上报格式

设备端代码里最容易忽略的不是采集逻辑,而是数据格式的统一。这个包里的前后端字段要能对上,就必须在一开始就把上报结构定死。下面这段是 MicroPython 风格的采集上报逻辑,和包内设备端代码的思路一致:

import json import time from machine import Pin, ADC soil = ADC(Pin(34)) dht_pin = Pin(4) def read_soil(): value = soil.read() percent = (1 - value / 4095) * 100 return max(0, min(100, round(percent, 1))) def report(): payload = { "device_id": "flower_01", "temperature": 24.5, "humidity": 60.2, "soil_moisture": read_soil(), "light": 320, "timestamp": int(time.time()) } # POST 到后端 /api/device/report # requests.post("http://192.168.1.100:5000/api/device/report", json=payload)

read_soil 里的换算逻辑值得展开说一下:ADC 在 ESP32 上读到的原始值范围是 0 到 4095,土壤越湿,探头之间的电阻越小,读到的数值越大。用1 - value / 4095做一个反向映射,再把结果限制在 0 到 100 之间,就得到了一个直观的湿度百分比。这里的 4095 是 12 位 ADC 的最大值,如果换到 ESP8266 这类 10 位 ADC 的芯片,就要改成 1023。

上报的 JSON 字段名要和后端数据库字段一一对应,尽量不要在服务端再做一次字段映射。timestamp用整型时间戳,不要传字符串日期,否则后面做历史曲线排序和聚合时会有时区问题。这个包的小程序端能直接解析这份 JSON,说明字段命名是保持一致的,这也是我拆包时比较看重的一点:前后端字段对齐的项目,二次开发成本低很多。

3. 智能决策逻辑:阈值控制、滞回保护与定时补偿的实现

“人工智能”这个标签容易让人误以为系统跑着神经网络模型,实际上这个包里的智能决策是规则引擎:根据传感器数据决定要不要浇水、要不要补光。这正是大部分智能养花毕设的真实水平——不是不需要 AI,而是规则控制在演示场景里最可控、最好解释。

3.1 浇水决策:湿度阈值加滞回区间

浇水逻辑看起来简单,但直接写“湿度低于 30 就开泵”会在临界点翻车。土壤湿度在阈值附近轻微波动时,继电器可能几十秒内反复吸合断开,水泵电机受不了,继电器触点也会打火老化。正确做法是加滞回区间,也就是把开启阈值和关闭阈值分开:

def decide_watering(soil_moisture, last_action_time, config): min_moisture = config.get("soil_min", 30) max_moisture = config.get("soil_max", 45) cooldown = config.get("min_interval", 300) now = time.time() if now - last_action_time < cooldown: return "hold" if soil_moisture < min_moisture: return "on" if soil_moisture >= max_moisture: return "off" return "hold"

这段逻辑的核心在于:湿度低于 30% 才启动浇水,湿度升到 45% 以上才停止,中间区间什么都不做。于是系统不会因为传感器读数在 29% 和 31% 之间抖动而频繁切换状态,这是工业控制里典型的滞回控制思路,放在养花系统里一样适用。

参数怎么调取决于植物类型:多肉植物喜欢偏干的环境,soil_min可以调到 20,soil_max调到 35;迷你玫瑰这类需要保湿的植物,soil_min调到 40,soil_max调到 55。min_interval是冷却时间,防止一次浇水还没渗入土壤就被重复触发,我一般设成 300 秒,也就是至少五分钟才允许一次新的开关动作。config 里的参数建议放到数据库配置表里,这样小程序端可以直接调,不用每次改代码。

3.2 光照调节:亮度分级与补光控制

光照控制和浇水不太一样:浇水有很长的执行时间,补光灯却是可以瞬时响应的设备。我建议把光照强度分成三个区间:低于 200 lx 开补光灯,200 到 600 lx 保持现状,高于 600 lx 关灯。分三档而不是两档,是为了避免补光灯在阴天和晴天交替时频繁启停,也给人工干预留出空间。

这里有一个很容易踩的坑:光敏传感器如果安装在补光灯附近,补光灯亮起时传感器立刻读到高亮度,系统会误以为自然光充足而关灯,形成正反馈振荡。解决方法是把光敏探头放在补光灯照射范围之外,或者朝窗户方向安装,让传感器主要读取自然光。

3.3 控制指令下发:设备端怎么跟小程序握手

后端决定动作之后,不会直接调用设备,而是先把指令写进命令表,设备端下一次轮询来取。这样设计的好处是解耦:后端只负责生成指令,设备端只负责执行指令,即使设备临时离线,指令也不会丢失,重新上线后能补执行。

指令格式一般是这样的 JSON:

{ "action": "water", "duration": 8, "cmd_id": 1680000001 }

cmd_id是命令唯一标识,设备端执行完成后要把这个 ID 回传给后端,标记为已执行。这个字段在简单系统里容易被忽略,但我强烈建议保留——网络重传的时候,设备端可能收到同一条指令两次,没有 cmd_id 就无法去重,水泵就会被重复开启。做课程演示时看不出问题,连续运行一两天后,这种重复指令的隐患会逐渐显现。

4. 数据链路与小程序端:建表、接口调用与图表渲染

数据链路是这套系统里工作量最大的部分,也是答辩时最值得讲的部分。环境数据要能存下来、能按时间查、能画成曲线,才算把物联网和软件工程结合到一起。

4.1 数据表设计:环境数据、控制日志、用户配置

我在拆这个包时发现它的表结构很克制,没有过度设计。核心就是两张表:环境数据表和控制命令表。环境数据表只做插入和查询,不需要频繁更新;控制命令表则要记录指令状态,方便排查问题。

CREATE TABLE environment_data ( id INT AUTO_INCREMENT PRIMARY KEY, device_id VARCHAR(32) NOT NULL, temperature DECIMAL(5,2), humidity DECIMAL(5,2), soil_moisture DECIMAL(5,2), light INT, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, INDEX idx_device_time (device_id, created_at) ); CREATE TABLE device_command ( id INT AUTO_INCREMENT PRIMARY KEY, device_id VARCHAR(32) NOT NULL, action VARCHAR(16) NOT NULL, duration INT DEFAULT 0, status TINYINT DEFAULT 0, created_at DATETIME DEFAULT CURRENT_TIMESTAMP );

environment_data表加了一个组合索引(device_id, created_at),这是因为小程序端画历史曲线时,查询条件基本固定为“某个设备最近 24 小时的数据”,这个索引能直接命中查询。数据量到了几万条以后,没有这个索引的查询会明显变慢,这在课程演示时用户量不大可能感受不到,但答辩老师如果要看数据库设计,组合索引是一个加分点。

device_command表的status字段用来标记指令状态:0 表示待执行,1 表示已执行,2 表示执行失败。设备端轮询时只取status = 0的记录,执行完更新状态。手动控制的水泵指令也会写到这张表里,这样设备和后端的每次交互都有记录,出了问题能回溯。

4.2 小程序端接口对接:wx.request 的用法与参数

微信小程序端和后端的交互全部走wx.request,这块代码在压缩包里可以直接看到。它的基本用法和浏览器里的 fetch 类似,但有几个参数是需要特别注意的:

wx.request({ url: 'https://your-domain.com/api/environment/recent', data: { deviceId: 'flower_01', hours: 24 }, method: 'GET', success(res) { const list = res.data.list; this.setData({ chartData: list }); }, fail(err) { wx.showToast({ title: '请求失败', icon: 'none' }); } });

url这个字段是第一个坑:正式环境中必须在小程序后台配置 request 合法域名,而且域名不能带路径、不能是 IP。开发阶段可以在开发者工具里勾选“不校验合法域名”,但真机上这个选项不生效。如果是局域网内调试,需要把后端服务的地址写成http://192.168.x.x:5000,同时保证手机和电脑在同一网段。fail回调里至少要有一个 toast 提示,否则断网时页面会无声无息地白屏。

4.3 图表展示:把历史曲线画出来

小程序端的图表我推荐直接用 echarts-for-weixin 插件包,这个包里的图表页面大概率也是这样实现的。图表数据不要直接喂原始记录,建议做 5 分钟聚合:每 5 分钟取一组均值,既能压住传感器抖动,又能让曲线看起来平滑。聚合可以在后端完成,也可以在小程序端用 JavaScript 处理,前者的好处是不用传太多数据到前端。

图上一般要展示三个指标:温度、空气湿度、土壤湿度。土壤湿度曲线的价值最大,因为它直接反映了浇水决策是否正确——如果土壤湿度曲线稳定在 30% 到 45% 之间,说明滞回控制生效了;如果曲线像锯齿一样频繁起伏,说明阈值设置不合理,回到底层去调参数比换算法更实际。

5. 避坑指南:从传感器抖动到小程序真机预览的五条记录

这个包在我手上跑过一遍,也见过同学复现时翻车,有些坑属于“看着代码没问题,跑起来全不对”的玄学。下面这五条是我觉得最值得提前知道的。

5.1 湿度读数跳变:滤波和接线哪个先查

现象:土壤湿度传感器显示 40%,几秒后跳到 90%,再过几秒又掉回 35%,数据曲线像心电图。

原因:传感器探头插入土壤过浅,或者 GPIO 引脚接触不良,ADC 采样值不稳定。采样间隔太短也会放大波动,尤其是供电电压不稳定时。

解决:先检查物理接线,探头插到土壤深度三分之二左右,引脚上加一个 100nF 滤波电容。软件层面做采样均值滤波,连续读五次取平均值再上报。把采样间隔从 1 秒加大到 5 秒,抖动就会明显收敛。

5.2 水泵频繁启停:继电器抖动的根源是滞回缺失

现象:水泵每隔十几秒启动一次,每次只转几秒就停,继电器发出连续的哒哒声。

原因:代码里只用了一个阈值判断,湿度在 30% 附近反复跨越,导致开关状态跟着来回翻转。

解决:按第三章的方式加滞回区间,低于 30% 开、高于 45% 关,中间保持原状态。再设置最少 5 分钟的冷却时间。我实测过一组数据,加了滞回之后,水泵每天动作次数从几十次降到了个位数。

5.3 小程序模拟器正常、真机白屏

现象:开发者工具里预览一切正常,一放到真机上就白屏,或者数据加载不出来。

原因:开发者工具默认勾选了“不校验合法域名”,局域网 HTTP 接口能直接访问;真机上 wx.request 会校验域名合法性,HTTP 局域网地址直接被拦掉。

解决:临时演示时,在手机微信里打开小程序的调试模式,就能绕过域名校验。正式部署则必须申请 HTTPS 域名并在后台配置 request 合法域名。注意模拟器的缓存也要定期清,改完代码后有时候显示的还是旧页面。

5.4 project.config.json 里的 appid 与路径残留

现象:用微信开发者工具导入这个包时,提示 appid 无效,或者编译时项目文件路径对不上。

原因:project.config.json 里的 appid 默认是测试号 touristappid,而且这个包是别人修改过第二版的项目,工程里可能残留了上一台电脑的绝对路径配置。

解决:导入后在开发者工具里重新选择自己的小程序测试号 appid,清空编译缓存,再执行一次“重新编译”。如果项目路径报错,直接删掉 project.config.json 中关于 miniprogramRoot 的绝对路径配置,让它自动识别。

5.5 数据曲线时间错位:本地时间与 UTC 混用

现象:历史曲线的横轴和真实时间对不上,数据点整体偏了几个小时。

原因:设备端上报的是 UTC 时间戳,后端转储到 MySQL 时用了本地时区,小程序端拿到时间戳又按东八区渲染,来回转换导致偏移。

解决:全链路统一用整型 UNIX 时间戳存储和传输,只在展示层做一次格式化。MySQL 的 created_at 字段可以保持 DATETIME 类型,但写入前要在后端代码里显式转换时区,不要依赖数据库默认时区。

6. 进阶实践:用模拟数据源先把软件链路跑通

硬件调试是最消耗时间的部分,而业务逻辑的验证其实不需要真实硬件。我拿到这个包之后做的一件事,就是写一个 Python 脚本模拟传感器上报,先把“设备端 → 后端 → 小程序”这条链路跑通,再考虑接板子。这样能把硬件问题隔离出去,软件稳了再接设备,排查范围会小很多。

import json import random import time import requests def fake_sensor(): return { "device_id": "flower_01", "temperature": round(24 + random.uniform(-2, 2), 1), "humidity": round(55 + random.uniform(-8, 8), 1), "soil_moisture": round(38 + random.uniform(-10, 10), 1), "light": int(320 + random.uniform(-30, 30)), "timestamp": int(time.time()) } while True: payload = fake_sensor() requests.post("http://127.0.0.1:5000/api/device/report", json=payload) time.sleep(5)

这个脚本会每 5 秒向后端上报一条接近真实分布的数据。验证时先让土壤湿度在一个区间内波动,观察小程序端的曲线是否正常显示;然后手动把soil_moisture的随机范围改到 20 以下,再观察后端是否生成了浇水指令,设备命令表里状态有没有变化。这就是完整的回归验证。

从实践角度看,我拿到任何一套带设备端和小程序的代码包,都会先写这样一段模拟脚本走一遍闭环,再动硬件。硬件玄学问题一大堆,连线、供电、烧录、串口,哪个环节都可能干扰判断;先用软件验证逻辑,再接实物,磨合时间会少一个量级。希望你拆这个包的时候,也能从这个流程里省下几个调试的夜晚。

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

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

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

立即咨询