基于行空板边缘AI的桌面微环境与植物健康看护站
一、项目简介
桌面盆栽经常出现养死的情况,市面上普通的植物监测设备只能读取土壤湿度、温湿度等环境数据,无法观察植株本身的叶片状态。
本项目使用行空板,融合多类环境传感器 + 本地AI视觉识别,同时采集环境参数与植株叶片状态,双维度综合推理植物健康状况。
当植物出现黄叶、土壤过干/过湿、光照不适等问题时,屏幕显示状态,并语音播报对应的养护建议;同时自动保存植株照片,记录植物生长变化,实现桌面盆栽的智能看护。
二、硬件清单
1. 行空板 m10
2. DHT11温湿度传感器
3. 土壤湿度传感器
5. 面包板、杜邦线若干
三、设计思路
1. 环境感知层:通过DHT11读取空气温湿度;土壤湿度传感器读取盆土干湿;光敏传感器采集环境光照强度。
2. AI视觉感知层:行空板摄像头定时拍摄盆栽画面,通过颜色阈值识别叶片发黄枯萎区域,判断植株叶片健康情况。
3. 综合推理逻辑:把传感器环境数据和叶片视觉结果结合,生成养护建议。
4. 输出反馈层:行空板屏幕展示全部实时数据、植物状态;异常时语音播报养护提示;定时保存植株照片,留存生长记录。
四、工作原理
1. 程序循环读取各类传感器数值;
2. 调用摄像头获取画面,做HSV颜色空间处理,统计画面中黄色像素占比,判断是否存在黄叶;
3. 将土壤湿度、温湿度、光照、叶片状态四个信息综合判断,输出养护提示;
4. 屏幕刷新全部信息,异常触发语音提醒;
5. 每隔一段时间保存一张植株照片,用于后续对比植物生长变化。
五、核心代码
导入库与硬件初始化
from unihiker import GUI
import time
import os
from pinpong.board import Board, Pin, DHT11
import cv2
import numpy as np
Board().begin()
gui = GUI()
dht11 = DHT11(Pin(Pin.P16))
soil_pin = Pin(Pin.P27, Pin.ANALOG)
save_dir = "/sdcard/plant_photo"
if not os.path.exists(save_dir):
os.mkdir(save_dir)编写黄叶识别核心函数
def detect_yellow_leaf(img):
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
lower_yellow = np.array([20, 80, 80])
upper_yellow = np.array([35, 255, 255])
mask = cv2.inRange(hsv, lower_yellow, upper_yellow)
yellow_pixel = np.sum(mask > 0)
total_pixel = img.shape[0] * img.shape[1]
yellow_ratio = yellow_pixel / total_pixel
return yellow_ratio > 0.12设计界面,绘制固定静态UI
TITLE_COLOR = "#00AA00"
TEXT_COLOR = "#ffffff"
WARN_COLOR = "#ff4444"
OK_COLOR = "#00ff00"
LINE_COLOR = "#444444"
gui.draw_text(text="🌿 AI植物看护站", x=20, y=8, font_size=22, color=TITLE_COLOR)
gui.draw_line(x0=5, y0=38, x1=235, y1=38, color=LINE_COLOR, width=2)
photo_count = 0循环采集传感器数据、获取摄像头图像并自动拍照
while True:
temp = dht11.temp_c()
hum = dht11.humidity()
soil_val = soil_pin.read_analog()
light_val = gui.get_light()
if temp is None or hum is None or np.isnan(temp) or np.isnan(hum):
temp = "---"
hum = "---"
frame = gui.get_camera_frame()
has_yellow = detect_yellow_leaf(frame)
if photo_count % 10 == 0:
save_path = f"{save_dir}/plant_{photo_count}.jpg"
cv2.imwrite(save_path, frame)
photo_count += 1状态判断、屏幕刷新与语音预警
gui.fill_rect(x=0, y=45, w=240, h=275, color="#000000")
gui.draw_text(text=f"🌡温度: {temp} ℃", x=12, y=55, font_size=15, color=TEXT_COLOR)
gui.draw_text(text=f"💨空气湿度: {hum} %", x=12, y=85, font_size=15, color=TEXT_COLOR)
gui.draw_text(text=f"☀光照强度: {light_val}", x=12, y=115, font_size=15, color=TEXT_COLOR)
gui.draw_text(text=f"🪴土壤湿度: {soil_val}", x=12, y=145, font_size=15, color=TEXT_COLOR)
gui.draw_line(x0=5, y0=170, x1=235, y1=170, color=LINE_COLOR, width=1)
tip_text = ""
tip_color = OK_COLOR
if has_yellow:
tip_text = "⚠检测黄叶!少浇水、加强通风"
tip_color = WARN_COLOR
elif soil_val < 300:
tip_text = "💧土壤偏干,请及时浇水"
tip_color = WARN_COLOR
elif soil_val > 820:
tip_text = "⚠土壤过湿,请暂停浇水"
tip_color = WARN_COLOR
elif light_val < 200:
tip_text = "☀光照不足,请移至明亮处"
tip_color = WARN_COLOR
else:
tip_text = "✅植物各项状态良好"
tip_color = OK_COLOR
gui.draw_text(text=tip_text, x=10, y=185, font_size=14, color=tip_color)
gui.draw_text(text=f"照片计数:{photo_count}", x=10, y=220, font_size=12, color="#aaaaaa")
if "⚠" in tip_text or "💧" in tip_text:
gui.speak(tip_text)
time.sleep(3)完整可移植代码
from unihiker import GUI
import time
import os
from pinpong.board import Board, Pin, DHT11
import cv2
import numpy as np
Board().begin()
gui = GUI()
dht11 = DHT11(Pin(Pin.P16))
soil_pin = Pin(Pin.P27, Pin.ANALOG)
save_dir = "/sdcard/plant_photo"
if not os.path.exists(save_dir):
os.mkdir(save_dir)
TITLE_COLOR = "#00AA00"
TEXT_COLOR = "#ffffff"
WARN_COLOR = "#ff4444"
OK_COLOR = "#00ff00"
LINE_COLOR = "#444444"
gui.draw_text(text="🌿 AI植物看护站", x=20, y=8, font_size=22, color=TITLE_COLOR)
gui.draw_line(x0=5, y0=38, x1=235, y1=38, color=LINE_COLOR, width=2)
def detect_yellow_leaf(img):
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
lower_yellow = np.array([20, 80, 80])
upper_yellow = np.array([35, 255, 255])
mask = cv2.inRange(hsv, lower_yellow, upper_yellow)
yellow_pixel = np.sum(mask > 0)
total_pixel = img.shape[0] * img.shape[1]
yellow_ratio = yellow_pixel / total_pixel
return yellow_ratio > 0.12
photo_count = 0
while True:
temp = dht11.temp_c()
hum = dht11.humidity()
soil_val = soil_pin.read_analog()
light_val = gui.get_light()
if temp is None or hum is None or np.isnan(temp) or np.isnan(hum):
temp = "---"
hum = "---"
frame = gui.get_camera_frame()
has_yellow = detect_yellow_leaf(frame)
if photo_count % 10 == 0:
save_path = f"{save_dir}/plant_{photo_count}.jpg"
cv2.imwrite(save_path, frame)
photo_count += 1
gui.fill_rect(x=0, y=45, w=240, h=275, color="#000000")
gui.draw_text(text=f"🌡温度: {temp} ℃", x=12, y=55, font_size=15, color=TEXT_COLOR)
gui.draw_text(text=f"💨空气湿度: {hum} %", x=12, y=85, font_size=15, color=TEXT_COLOR)
gui.draw_text(text=f"☀光照强度: {light_val}", x=12, y=115, font_size=15, color=TEXT_COLOR)
gui.draw_text(text=f"🪴土壤湿度: {soil_val}", x=12, y=145, font_size=15, color=TEXT_COLOR)
gui.draw_line(x0=5, y0=170, x1=235, y1=170, color=LINE_COLOR, width=1)
tip_text = ""
tip_color = OK_COLOR
if has_yellow:
tip_text = "⚠检测黄叶!少浇水、加强通风"
tip_color = WARN_COLOR
elif soil_val < 300:
tip_text = "💧土壤偏干,请及时浇水"
tip_color = WARN_COLOR
elif soil_val > 820:
tip_text = "⚠土壤过湿,请暂停浇水"
tip_color = WARN_COLOR
elif light_val < 200:
tip_text = "☀光照不足,请移至明亮处"
tip_color = WARN_COLOR
else:
tip_text = "✅植物各项状态良好"
tip_color = OK_COLOR
gui.draw_text(text=tip_text, x=10, y=185, font_size=14, color=tip_color)
gui.draw_text(text=f"照片计数:{photo_count}", x=10, y=220, font_size=12, color="#aaaaaa")
if "⚠" in tip_text or "💧" in tip_text:
gui.speak(tip_text)
time.sleep(3)这里的模型大家可以在mind+V2中自己训练需要的检测植物。
由于我的行空板有问题,为大家做了模拟处理,但放心,行空板预览效果和下图大差不差。

六、调试踩坑记录(这里为大家列出来防止大家重蹈覆辙)
1. 光照干扰问题:强光环境下,叶片反光会造成黄叶误识别。
解决:调整摄像头角度,避开直射阳光,适当调低黄色识别阈值。
2. 土壤湿度读数漂移:土壤传感器容易接触不良。
解决:传感器探针插入土壤深度保持一致,每次上电重新读取校准。
3. 摄像头画面卡顿:循环间隔设置为3秒,不要频繁拍照,避免行空板性能占用过高。
八、未来改进方向(为大家提供以下方向参考)
1. 增加微型水泵,实现自动浇水;
2. 训练专用植物识别AI模型,提升叶片病害识别准确度;
3. 实现WiFi上传,在电脑端查看植物生长历史记录;
4. 生成植物延时生长视频。





