1. 项目概述你是不是也和我一样养过几盆绿植但总是因为忘记浇水或者浇水过多而让它们“英年早逝”作为一个喜欢折腾硬件的开发者我总觉得应该用技术来解决这个问题。传统的土壤湿度计需要你凑近了看而我想的是能不能在办公室的电脑前甚至是在地铁上就能随时知道家里那盆琴叶榕是不是渴了这就是物联网IoT的魅力所在——把物理世界的数据搬到数字世界里来。这个项目的核心就是搭建一个“植物保姆”系统。它由三部分组成一个放在花盆里的“眼睛和手”PyPortal开发板和土壤传感器一个负责思考和展示的“大脑”Microsoft Azure IoT Central云平台以及连接它们的“神经网络”Wi-Fi和代码。我们使用CircuitPython来编写设备端的逻辑因为它对硬件新手极其友好无需复杂的编译环境像写Python脚本一样简单。Azure IoT Central则扮演了云端的枢纽角色它负责接收数据、存储数据并提供一个漂亮的仪表盘让你一目了然。整个过程就是从土壤里的一点点水分变化到屏幕上清晰图表的数据之旅。无论你是想学习物联网的入门实践还是想为你的智能家居添砖加瓦这个项目都是一个绝佳的起点。它涵盖了硬件连接、嵌入式编程、云服务配置和数据可视化等多个环节但每一步我都将拆解得足够细致。你不需要是电子或编程专家只要跟着步骤走就能亲手让一个物理设备与云端“对话”。接下来我们就从零开始一步步把这个“植物监测系统”搭建起来。2. 核心硬件与原理深度解析2.1 PyPortal你的物联网设备核心PyPortal并不是一个简单的单片机你可以把它理解为一个高度集成、开箱即用的物联网终端。它基于ATSAMD51微控制器并板载了ESP32 WiFi协处理器、3.5英寸触摸屏、光线传感器、温度传感器等多个模块。这种设计哲学非常明确降低物联网项目的硬件集成门槛。你不需要再单独购买屏幕、Wi-Fi模块然后费劲地焊接连线Adafruit已经帮你把最常用的部件都集成在了一块板子上。这里有一个关键点需要理解主控与网络协处理器的分工。PyPortal上的ATSAMD51我们常说的主MCU负责运行我们的主要程序CircuitPython代码、驱动屏幕、读取I2C传感器等。而ESP32则专门负责处理网络连接它通过SPI总线与主MCU通信。这种架构的优势在于网络通信的复杂协议栈和信号处理由专门的芯片ESP32负责不会占用主MCU过多的计算资源保证了设备响应的流畅性。在我们的项目中所有与Azure云端的通信实际上都是由ESP32这个“通信专家”来完成的。2.2 STEMMA土壤传感器为什么是电容式选择正确的传感器是项目成功的一半。市面上常见的土壤湿度传感器大多是电阻式的。它的原理是通过两个金属探针测量土壤的导电性水分越多电阻越小读数越高。但这种方法有几个致命缺点电极腐蚀直流电长期通过金属探针和土壤中的电解质会发生电解反应导致探针快速腐蚀、生锈寿命很短。测量误差土壤中的肥料离子会极大影响导电性导致读数不准确你可能测到的是“肥力”而不是“湿度”。对植物有潜在影响微弱的电流可能影响植物根系的生长环境。而我们使用的Adafruit STEMMA土壤传感器采用的是电容式测量原理。它内部只有一个探针通常被包裹在防水的环氧树脂中另一个“电极”是传感器本身的电路板。它测量的是土壤作为电介质与探针之间形成的电容的容量。水的介电常数远高于空气和干燥土壤因此土壤湿度增加会导致电容值显著上升。这种方法的优点非常突出无电极腐蚀因为测量的是电容没有直流电流长期流过土壤和探针极大延长了传感器寿命。测量更准确受土壤离子浓度影响较小更能真实反映体积含水量。对植物友好无电流干扰。传感器通过I2C接口输出数据除了湿度它还集成了一个温度传感器可以同时监测土壤的 ambient temperature环境温度虽然精度不高±2°C但对于植物监测来说已经足够。2.3 硬件连接为什么是I2CPyPortal和土壤传感器通过一根4线的STEMMA QT / Qwiic JST-PH连接线对接。这种连接器防反插即插即用无需焊接。连接的四根线分别是VIN (5V) 和 GND为传感器提供电源和地线。SDA 和 SCL这是I2C通信的数据线和时钟线。为什么选择I2C协议I2C是一种多主、多从的串行通信总线。在物联网项目中它有几个不可替代的优势节省引脚只需要两根线SDA, SCL就可以连接多个传感器每个设备有唯一地址。PyPortal的I2C端口可以挂载土壤传感器、光照传感器等多个设备而不会占用太多宝贵的GPIO引脚。协议成熟CircuitPython对I2C有非常好的库支持读写操作非常简单。传输可靠相对于单线的模拟读取I2C是数字信号抗干扰能力更强传输距离也更远在板载范围内足够稳定。注意在连接时务必确保传感器白色部分电路板不要埋入土中只需将金属探针部分插入土壤。可以将传感器放在花盆边缘便于布线和查看。3. 软件环境搭建与核心配置3.1 CircuitPython固件与库管理构建设备“操作系统”首先你需要为PyPortal刷入CircuitPython固件。你可以把它想象成给手机安装安卓或iOS系统。去CircuitPython官网找到PyPortal对应的.uf2文件用USB线连接PyPortal和电脑将其置于引导加载模式通常快速双击复位按钮会出现一个名为PYPORTALBOOT的U盘把.uf2文件拖进去设备会自动重启之后就会出现一个名为CIRCUITPY的U盘这就是设备的“系统盘”。接下来是库文件。CircuitPython的强大之处在于其丰富的“库”生态系统。库就是别人写好的、实现特定功能的代码包。我们的项目需要多个库协同工作adafruit_esp32spi这是与ESP32 WiFi协处理器通信的底层驱动是所有网络功能的基石。adafruit_requests一个类似于Python标准库requests的HTTP客户端库让我们能用非常Pythonic的方式向云端发送HTTP请求如POST数据。adafruit_pyportal/adafruit_portalbase高级封装库简化了在PyPortal屏幕上显示图形、文字和网络交互的流程。adafruit_bus_device提供I2C和SPI总线的基础支持。传感器驱动库例如adafruit_seesawSTEMMA土壤传感器基于seesaw协处理器用于从传感器读取数据。安装方法很简单下载最新的Adafruit CircuitPython库包Library Bundle解压后将lib文件夹内本项目所需的库文件复制到CIRCUITPY盘符下的lib文件夹中即可。一个常见的坑是库版本不匹配。务必确保你下载的库包版本与你的CircuitPython固件版本大致对应。如果遇到ImportError首先检查库文件是否齐全其次考虑更换为更旧或更新的库版本试试。3.2settings.toml安全存储敏感信息的艺术在物联网项目中Wi-Fi密码、云服务API密钥等都是敏感信息。早期我们习惯把它们直接写在code.py里但这带来了安全问题代码分享时会泄露密码和不变性问题换个网络就得改代码。从CircuitPython 8开始官方推荐使用settings.toml文件来管理配置。这是一个存储在CIRCUITPY根目录下的纯文本文件采用TOML格式。它的核心思想是将配置与代码分离。你需要创建一个名为settings.toml的文件内容如下# WiFi配置 CIRCUITPY_WIFI_SSID 你的Wi-Fi名称 CIRCUITPY_WIFI_PASSWORD 你的Wi-Fi密码 # Azure IoT Central设备连接信息 (示例具体值需在Azure中创建后获得) AZURE_IOT_CENTRAL_SCOPE_ID 0ne12345678 AZURE_IOT_CENTRAL_DEVICE_ID my-plant-monitor-01 AZURE_IOT_CENTRAL_DEVICE_KEY yourPrimaryOrSecondaryKeyHere在code.py中你可以通过os.getenv()函数来读取这些值import os ssid os.getenv(CIRCUITPY_WIFI_SSID) password os.getenv(CIRCUITPY_WIFI_PASSWORD) scope_id os.getenv(AZURE_IOT_CENTRAL_SCOPE_ID)这样做的好处安全你可以放心地将code.py分享到GitHub而不会暴露你的密码。灵活更换网络或设备凭证时只需修改settings.toml文件无需触碰核心代码。统一所有配置集中管理一目了然。实操心得务必确保settings.toml文件以UTF-8编码无BOM保存。在Windows上用记事本编辑时另存为可以选择编码。错误的编码可能导致CircuitPython无法正确解析中文字符或特殊符号。3.3 网络连接测试确保通信链路畅通在对接复杂的云服务之前必须确保PyPortal能成功连接互联网。Adafruit提供了一个经典的网络测试脚本。将其保存为code.py并运行你将在串行终端如Mu编辑器、Thonny或VS Code的串行监视器中看到输出。这个测试脚本做了以下几件事初始化ESP32通过SPI引脚与ESP32协处理器建立通信。扫描网络列出周围可用的Wi-Fi网络及其信号强度RSSI。连接AP使用settings.toml中的凭据连接指定网络。基础网络测试获取本地IP解析域名如adafruit.com并尝试Ping一个外网地址。HTTP请求测试分别获取一个文本网页和一个JSON接口的内容验证HTTP协议栈工作正常。常见问题与排查问题终端卡在“Connecting to AP...”或提示密码错误。排查首先检查settings.toml中的SSID和密码是否正确注意大小写和特殊字符。其次检查路由器是否设置了MAC地址过滤或将PyPortal的MAC地址加入白名单。问题能连接AP但无法Ping通或获取网页。排查检查路由器是否正常连接外网。尝试将TEXT_URL和JSON_URL替换为更常见的地址如http://example.com进行测试。有时企业或校园网有额外的认证门户Captive Portal需要手动网页登录。问题ESP32固件版本过旧。排查测试脚本会打印ESP32的固件版本。如果版本很旧如早于1.7可能会导致不稳定。可以考虑通过Arduino IDE等工具为ESP32更新AT固件但这需要一些额外步骤。通过这个测试我们就为设备上云铺平了道路。接下来我们要在云端建立一个“指挥中心”。4. Azure IoT Central云端平台配置详解4.1 创建应用程序定义你的项目蓝图Azure IoT Central不是一个虚拟机或容器它是一个平台即服务PaaS。这意味着微软已经帮你管理好了底层的基础设施、安全和缩放逻辑你只需要通过网页界面来定义你的设备模型、规则和仪表盘。首先访问Azure IoT Central官网并用你的Microsoft账户登录。如果你有Azure订阅建议使用该订阅关联的账户以便享受免费额度和管理资源。如果没有也可以使用微软账户直接创建试用应用有7天或设备数量限制。点击“创建应用程序”这里我强烈建议使用“自定义应用”模板而不是完全从头开始。但对于我们这个具体项目Adafruit提供了一个预配置的模板链接能极大简化初始设置。这个模板已经预定义了一个“植物监测设备”的模型包含了湿度、温度等遥测数据。使用模板后你需要填写应用详情给应用起个名字如My-Plant-Monitoring。URL会自动生成这是你访问仪表盘的地址。选择定价计划对于个人项目和小型试验选择“免费”计划。它允许最多2台设备数据保留7天完全足够我们学习和原型开发。创建点击创建等待几分钟你的专属IoT应用就部署好了。4.2 创建设备模板与真实设备在IoT Central中设备模板是蓝图设备是实体。模板定义了这类设备能做什么发送什么数据接受什么命令而设备是这个模板的一个具体实例。理解设备模板使用模板创建的应用已经自带了一个设备模板。你可以进入“设备模板”页面查看它。你会看到一个名为“Plant Monitor”的模板里面定义了“湿度”humidity和“温度”temperature两个遥测Telemetry字段。这就是我们PyPortal将要上报的数据格式。创建设备进入“设备”页面点击“ 新建”。选择刚才的“Plant Monitor”模板并输入一个设备ID例如pyportal-plant-01。设备名称可以更友好些如客厅-琴叶榕监测器。点击创建。获取设备连接凭证这是最关键的一步点击你刚创建的真实设备进入设备详情页。找到“连接”选项通常在页面顶部或设置中。这里你会看到三样至关重要的信息ID范围Scope ID整个IoT Central应用的范围ID所有设备共享。设备IDDevice ID你刚才为这个实体设备设置的ID。主密钥Primary Key或SAS令牌用于设备认证的密钥。请立即将这三项信息更新到你的PyPortal的settings.toml文件中对应我们之前预留的AZURE_IOT_CENTRAL_*变量。重要安全提示主密钥Primary Key就像设备的根密码拥有它就可以以该设备的身份连接云端。务必妥善保管不要泄露。在生产环境中可以考虑使用派生出的、有效期更短的SAS令牌。4.3 设计仪表盘让数据会说话数据上传后我们需要一个直观的方式查看。IoT Central的仪表盘功能非常强大且易于拖拽。进入你设备的仪表盘或创建一个新的你可以添加各种磁贴折线图/曲线图磁贴最常用。选择“湿度”遥测设置时间范围如过去1小时你就可以看到土壤湿度随时间变化的曲线。再添加一个温度曲线。最新值磁贴显示传感器当前的最新读数数字大而醒目。事件历史磁贴如果未来你设置了规则如“湿度低于20%时报警”可以在这里看到触发的警报。KPI磁贴显示关键指标如过去24小时的平均湿度。你可以自由拖放、调整大小组织一个直观的监控面板。例如顶部放最新值中间放曲线图底部放设备状态。配置好后点击发布这个仪表盘就生效了。至此云端的“指挥部”已经搭建完毕它正等待着我们的硬件设备前来报到并发送数据。5. CircuitPython代码实现与深度解析5.1 项目代码结构与核心逻辑完整的项目代码较长但结构清晰。我将核心逻辑拆解并附上详细注释。你需要将以下代码保存为CIRCUITPY盘符下的code.py。import time import board import busio from digitalio import DigitalInOut import adafruit_esp32spi.adafruit_esp32spi_socket as socket from adafruit_esp32spi import adafruit_esp32spi import adafruit_requests as requests import displayio import terminalio from adafruit_display_text import label from adafruit_seesaw.seesaw import Seesaw import adafruit_azureiot # --- 1. 读取配置 --- import os # 从settings.toml读取WiFi和Azure配置 WIFI_SSID os.getenv(CIRCUITPY_WIFI_SSID) WIFI_PASSWORD os.getenv(CIRCUITPY_WIFI_PASSWORD) SCOPE_ID os.getenv(AZURE_IOT_CENTRAL_SCOPE_ID) DEVICE_ID os.getenv(AZURE_IOT_CENTRAL_DEVICE_ID) DEVICE_KEY os.getenv(AZURE_IOT_CENTRAL_DEVICE_KEY) # --- 2. 初始化硬件 --- # 2.1 初始化ESP32 WiFi协处理器 esp32_cs DigitalInOut(board.ESP_CS) esp32_ready DigitalInOut(board.ESP_BUSY) esp32_reset DigitalInOut(board.ESP_RESET) spi busio.SPI(board.SCK, board.MOSI, board.MISO) esp adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) # 2.2 初始化I2C总线并连接土壤传感器 i2c_bus busio.I2C(board.SCL, board.SDA) # Seesaw是STEMMA土壤传感器使用的芯片 ss Seesaw(i2c_bus, addr0x36) # 默认I2C地址为0x36 # 2.3 初始化显示组PyPortal屏幕 splash displayio.Group() board.DISPLAY.show(splash) # 创建文本标签用于显示本地数据 text_area label.Label(terminalio.FONT, textInitializing..., color0xFFFFFF) text_area.x 10 text_area.y 60 splash.append(text_area) # --- 3. 连接WiFi --- print(Connecting to WiFi...) while not esp.is_connected: try: esp.connect_AP(WIFI_SSID, WIFI_PASSWORD) except RuntimeError as e: print(Could not connect to AP, retrying:, e) continue print(Connected to:, str(esp.ap_info.ssid, utf-8), RSSI:, esp.ap_info.rssi) print(My IP address is, esp.pretty_ip(esp.ipv4_address)) # --- 4. 初始化Azure IoT Central连接 --- # 为requests库设置socket池和SSL上下文 import adafruit_connection_manager pool adafruit_connection_manager.get_radio_socketpool(esp) ssl_context adafruit_connection_manager.get_radio_ssl_context(esp) requests.set_socket(socket, esp) # 创建IoT Central设备客户端 # 注意此处使用了一个假设的辅助库adafruit_azureiot实际可能需要根据Azure SDK调整 # 核心是使用DPS设备预配服务和SAS令牌进行认证 device_client adafruit_azureiot.IoTCentralDevice( requests, pool, ssl_context, scope_idSCOPE_ID, device_idDEVICE_ID, device_keyDEVICE_KEY, ) print(Connecting to Azure IoT Central...) device_client.connect() print(Connected to Azure!) # --- 5. 主循环读取传感器数据并上报 --- while True: try: # 读取传感器数据 # 触摸读数用于电容湿度测量 touch ss.moisture_read() # 温度读数来自传感器板载温度传感器 temp ss.get_temp() # 将原始数据转换为更易读的单位示例转换需根据传感器校准 # 电容读数范围通常约200非常干到2000非常湿 moisture_percentage min(max((touch - 200) / (2000 - 200) * 100, 0), 100) # 在本地屏幕显示 display_text Moisture: {:.1f}%\nTemp: {:.1f}C.format(moisture_percentage, temp) text_area.text display_text # 准备上传到云端的数据负载JSON格式 telemetry_data { humidity: moisture_percentage, temperature: temp } print(Sending:, telemetry_data) # 发送遥测数据到Azure IoT Central device_client.send_telemetry(telemetry_data) except (RuntimeError, OSError) as e: # 处理任何读写或网络错误 print(Error occurred:, e) text_area.text Error:\n str(e) # 尝试重新连接网络和Azure try: if not esp.is_connected: esp.connect_AP(WIFI_SSID, WIFI_PASSWORD) device_client.reconnect() except Exception as reconnect_e: print(Reconnect failed:, reconnect_e) # 每10秒发送一次数据避免过于频繁节省电力和网络资源 time.sleep(10)5.2 代码关键环节深度剖析4. Azure IoT连接初始化这是代码中最核心也最容易出错的部分。Azure IoT设备连接通常采用DPS设备预配服务和SAS共享访问签名令牌认证流程。DPS设备首先向全局的DPS端点发起请求提供SCOPE_ID、DEVICE_ID和DEVICE_KEY。DPS验证后会告诉设备它应该连接到哪个具体的IoT Central实例分配一个主机名。SAS令牌设备使用DEVICE_KEY和当前时间等信息生成一个有时效性的加密签名SAS Token作为后续MQTT或HTTP请求的密码。MQTT协议设备与IoT Central之间最常用的通信协议是MQTT这是一种轻量级的发布/订阅消息协议非常适合物联网场景。代码中的adafruit_azureiot库或类似的实现内部封装了生成SAS Token和通过MQTT连接、发布消息的复杂细节。5. 主循环的设计哲学错误处理物联网设备运行环境不可靠网络可能中断。try...except块捕获所有可能异常传感器读取失败、网络发送失败并在屏幕上显示错误信息。同时在异常处理中尝试重新连接网络和Azure增强了设备的鲁棒性。数据发送频率time.sleep(10)意味着每10秒上报一次数据。这个间隔需要权衡太短会增加设备功耗和云端负载太长则监控不够实时。对于植物浇水10-30秒的间隔是合理的。你可以根据电池供电还是USB供电来调整这个值。数据格式我们发送的是一个简单的JSON对象键名humidity,temperature必须与在Azure IoT Central设备模板中定义的遥测字段名称完全一致否则云端无法正确解析和显示。5.3 传感器数据校准与优化代码中的湿度百分比转换(touch - 200) / (2000 - 200) * 100是一个线性映射的示例。但电容式传感器的读数并非完全线性且受土壤类型、压实程度影响极大。因此这个公式只能给出一个粗略的参考。如何进行校准获取基准值将传感器完全置于空气中干燥状态记录此时的touch读数此为dry_value可能接近200。获取饱和值将传感器探针完全浸入清水中注意电路部分不要沾水记录读数此为wet_value可能接近2000。修改公式将代码中的200和2000替换为你实测的dry_value和wet_value。土壤特异性校准进阶对于更精确的测量你需要在你实际使用的土壤中进行校准。取一份完全干燥的土壤测一个值再加水至你认为“湿润”的状态测一个值用这两个值作为基准。这能获得对该种土壤最准确的百分比。温度读数传感器板载的温度传感器测量的是传感器电路板附近的空气温度而非土壤温度。对于植物监测环境温度同样重要。你可以考虑增加一个DS18B20这类防水温度传感器将其探针插入土壤深处来获取更准确的根区土壤温度。6. 系统集成、测试与问题排查实录6.1 全链路测试流程当硬件连接好、代码上传完毕、云端配置完成后就可以进行端到端测试了。硬件上电用USB线为PyPortal供电。观察屏幕应该会显示“Initializing...”然后变为“Connecting to WiFi...”。监视串行输出打开串行终端波特率115200。这是最重要的调试窗口。你应该依次看到WiFi连接成功的信息SSID和IP地址。“Connecting to Azure IoT Central...” 和 “Connected to Azure!”。循环打印的 “Sending: {humidity: xx.x, temperature: xx.x}”。观察本地屏幕成功连接并发送数据后屏幕会更新为当前的湿度和温度值。验证云端数据在Azure IoT Central的设备详情页点击“原始数据”标签页。你应该能看到近乎实时有少量延迟刷新的、从设备发来的遥测数据流。如果这里没有数据说明设备到云端的链路有问题。检查仪表盘回到设备仪表盘你添加的“最新值”和“曲线图”磁贴应该开始显示数据并随时间更新。6.2 常见问题排查速查表以下是我在多次搭建和教学中遇到的典型问题及解决方法问题现象可能原因排查步骤与解决方案串口无输出或输出乱码1. 串口监视器波特率设置错误。2. USB线仅供电无数据线。3. 板子处于非CircuitPython模式。1. 确认波特率为115200。2. 换用一条已知良好的数据线。3. 尝试双击PyPortal复位按钮看是否出现CIRCUITPY盘符。卡在“Connecting to WiFi...”1.settings.toml中SSID/密码错误。2. WiFi信号太弱。3. 路由器设置了MAC过滤或特殊认证。1. 仔细核对SSID和密码注意隐藏空格。2. 将设备移近路由器。3. 检查路由器后台暂时关闭MAC过滤如果是公共网络尝试用手机/电脑先完成网页认证。提示“Azure连接失败”或认证错误1.settings.toml中Azure连接三要素错误。2. SAS令牌过期如果使用动态生成。3. 设备在IoT Central中被禁用。1. 逐字核对SCOPE_ID,DEVICE_ID,DEVICE_KEY确保从设备详情页“连接”信息中复制完整。2. 检查代码中SAS令牌生成逻辑的时间戳是否同步。3. 登录Azure IoT Central确认设备状态为“已就绪”而非“已禁用”。云端收到数据但仪表盘不显示1. 设备模板中遥测字段名称与代码中JSON键名不匹配。2. 数据格式不正确如字符串而非数字。3. 仪表盘磁贴未关联正确设备或遥测。1. 对比设备模板定义和代码telemetry_data字典的键名必须完全一致包括大小写。2. 确保发送的是整数或浮点数不是带引号的字符串。3. 编辑仪表盘磁贴检查其配置的数据源是否选择了当前设备及正确的遥测字段。设备运行一段时间后离线1. WiFi不稳定。2. 代码中未处理断线重连。3. Azure侧连接空闲超时。1. 增强代码的异常处理如我们代码中的try...except块在捕获到网络错误后执行重连逻辑。2. 考虑使用WiFiManager类Adafruit提供它能提供更稳定的连接管理。3. MQTT有保活机制确保代码中实现了心跳或定期发送数据以维持连接。湿度读数始终为0或异常1. I2C连接松动或线序错误。2. 传感器损坏或未完全插入土壤。3. 代码中传感器I2C地址错误。1. 检查STEMMA连接线是否插紧。确认PyPortal的I2C端口不是其他标有SDA/SCL的引脚。2. 将传感器拔出用手指触摸金属探针观察读数是否变化。不变则可能传感器故障。3. 确认代码中Seesaw的地址参数是0x36这是该传感器的默认地址。6.3 项目优化与扩展思路当基础系统跑通后你可以考虑以下方向进行深化和扩展低功耗优化目前设备通过USB持续供电。若想电池供电需大幅降低功耗。深度睡眠让PyPortal在主循环每次发送数据后进入深度睡眠time.sleep()不是真睡眠仅留ESP32定时唤醒。这需要更复杂的电源管理和可能的外部RTC。减少屏幕更新屏幕是耗电大户。可以设置为仅在有数据更新或按键触摸时才点亮屏幕。增加执行器闭环控制从“监测”升级到“控制”。自动浇水添加一个小水泵和继电器模块。在Azure IoT Central中创建一个“命令”Command当你在仪表盘点击“浇水”按钮或设置一条规则“当湿度低于20%时”云端向设备发送命令设备控制继电器打开水泵一段时间。数据深度利用数据导出在Azure IoT Central中配置“数据导出”将遥测数据持续流式传输到Azure Blob Storage廉价存储或Azure Time Series Insights时序数据分析服务。设置警报规则在IoT Central中创建规则当温度超过35°C或湿度低于15%时向你的邮箱或Teams发送通知。机器学习将历史数据导入Azure Machine Learning训练一个模型来预测未来几小时的湿度变化实现预测性浇水。美化本地界面利用PyPortal的显示能力。使用displayio加载植物图片作为背景。用不同颜色的文字或进度条来表示湿度状态例如绿色表示良好红色表示需要浇水。添加一个触摸按钮本地手动触发一次数据读取或屏幕刷新。这个项目就像一颗种子你已经完成了播种和培育的第一步。它不仅仅是一个植物监测器更是一个完整的、可复用的物联网设备原型框架。你可以更换不同的传感器光照、空气质量、噪音应用到不同的场景仓库环境监控、宠物喂食器、信箱提醒器。希望你在动手实现的过程中不仅收获了绿意盎然更体会到了连接物理与数字世界的乐趣与力量。