自动化植物浇水 本课概述草图 草图由 Nitya Narasimhan 绘制。点击图片查看大图。 本课程作为 物联网初学者项目 2 - 数字农业系列 的一部分,由 Microsoft Reactor 讲授。 物联网驱动的自动化植物浇水 课前测验 课前测验 引言 在上一课中,你学习了如何监测土壤湿度。在这节课中,你将学习如何构建一个基于土壤湿度自动浇水系统的组成部分。你还将了解定时——传感器响应变化需要多长时间,以及执行器改变测量属性需要多长时间。 本节课我们将涵盖以下内容: 从低功耗物联网设备控制高功率设备 控制继电器 通过MQTT控制植物 传感器和执行器的定时 向植物控制系统添加定时 从低功耗物联网设备控制高功率设备 物联网设备使用低压电源。

草图由 Nitya Narasimhan 绘制。点击图片查看大图。
本课程作为 物联网初学者项目 2 - 数字农业系列 的一部分,由 Microsoft Reactor 讲授。
在上一课中,你学习了如何监测土壤湿度。在这节课中,你将学习如何构建一个基于土壤湿度自动浇水系统的组成部分。你还将了解定时——传感器响应变化需要多长时间,以及执行器改变测量属性需要多长时间。
本节课我们将涵盖以下内容:
物联网设备使用低压电源。虽然这对传感器和低功率执行器(如LED)来说已经足够,但对用于灌溉的大功率水泵来说,这种电压太低,无法控制。即使是用于室内植物的小型水泵,也会消耗过多电流,烧坏开发板上的电路。
电流以安培(A)为单位测量,是通过电路流动的电量。电压提供推力,电流是被推动的量。你可以在维基百科的 电流页面 上阅读更多关于电流的内容。
解决这个问题的方法是将水泵连接到外部电源,并使用执行器来切换水泵,就像用手指拨动开关一样。只需一点点能量(你身体里的能量),你的手指就可以翻转开关,从而将灯连接到110V/240V的主电源。

主电源 是指许多国家通过国家基础设施送到家庭和企业的电力。
✅ 物联网设备通常可以提供3.3V或5V电压,电流小于1安培(1A)。与主电源相比,主电源通常是230V(北美为120V,日本为100V),并且可以为消耗30A电流的设备供电。
有许多执行器可以做到这一点,包括可以连接到现有开关上的机械装置,模仿手指拨动开关的动作。最流行的是继电器。
继电器是一种电磁开关,它将电信号转换成机械动作,从而打开或关闭开关。继电器的核心是一个电磁铁。
电磁铁 是通过电线缠绕形成的磁铁,当电流通过时,线圈会磁化。当电流停止时,线圈会失去磁性。

在继电器中,控制电路为电磁铁供电。当电磁铁接通时,它拉动一个杠杆,使开关移动,闭合一对触点,完成输出电路。

当控制电路断开时,电磁铁关闭,释放杠杆,打开触点,关闭输出电路。继电器是数字执行器——高信号使继电器接通,低信号使继电器断开。
输出电路可以用来为其他硬件供电,例如灌溉系统。物联网设备可以打开继电器,完成输出电路,为灌溉系统供电,植物得到水。然后,物联网设备可以关闭继电器,切断灌溉系统的电源,停止供水。

在上面的视频中,继电器接通。继电器上的LED亮起,表示它已接通(一些继电器板上有LED指示继电器是否接通或断开),然后为泵供电,使其接通并开始向植物泵水。
继电器也可以用于在两个输出电路之间切换,而不是接通或断开一个电路。当杠杆移动时,它会将开关从完成一个输出电路切换到完成另一个输出电路,通常共享一个公共电源连接或公共接地连接。
✅ 做一些研究:有多种类型的继电器,它们之间的区别包括控制电路在通电时是接通还是断开继电器,或者多个输出电路。找出这些不同类型的继电器。
当杠杆移动时,你通常可以听到它与电磁铁接触时发出的清晰的咔嗒声。
继电器可以接线,使得实际连接会断开继电器的电源,从而关闭继电器,然后重新为继电器供电,再次打开继电器,如此循环。这意味着继电器会非常快速地咔嗒作响,发出嗡嗡声。这是早期电铃中使用的一些方式。
电磁铁只需要少量电力就能激活并拉动杠杆,可以通过物联网开发套件的3.3V或5V输出进行控制。输出电路可以承载更多的电力,这取决于继电器,包括主电压甚至更高的工业级电力。这样,物联网开发套件可以控制灌溉系统,从小型水泵供单个植物用水,到大型商业农场的整个灌溉系统。

上述图像显示了一个Grove继电器。控制电路连接到物联网设备,使用3.3V或5V来接通或断开继电器。输出电路有两个端子,任何一个都可以作为电源或接地。输出电路能够处理高达250V、10A的电力,足以满足一系列主电源设备。你可以获得能够处理更高功率的继电器。

在上述图像中,通过继电器为泵供电。一条红色导线将USB电源供应的+5V终端连接到继电器输出电路的一个终端,另一条红色导线将继电器输出电路的另一个终端连接到泵。一条黑色导线将泵连接到USB电源供应的接地。当继电器接通时,它会完成电路,将5V发送到泵,启动泵。
你可以从你的物联网开发套件控制一个继电器。
按照相关指南操作,使用你的物联网设备控制继电器:
到目前为止,你的继电器是由物联网设备直接根据单一土壤湿度读数控制的。在一个商业灌溉系统中,控制逻辑是集中的,允许它基于来自多个传感器的数据做出浇水决策,并且可以在一个地方更改任何配置。为了模拟这一点,你可以通过MQTT控制继电器。
向你的soil-moisture-sensor项目添加相关的MQTT库/pip包和代码,以便连接到MQTT。将客户端ID命名为soilmoisturesensor_client,并在其前加上你的ID。
⚠️ 如果需要,可以参考 项目1第4课连接到MQTT的说明。
添加相关的设备代码,发送包含土壤湿度设置的遥测数据。对于遥测消息,将属性命名为soil_moisture。
⚠️ 如果需要,可以参考 项目1第4课将遥测数据发送到MQTT的说明。
在名为soil-moisture-sensor-server的文件夹中创建一些本地服务器代码,订阅遥测数据并发送控制继电器的命令。将命令消息中的属性命名为relay_on,并将客户端ID命名为soilmoisturesensor_server,在其前加上你的ID。保留你在项目1第4课编写的服务器代码结构,稍后你将在本课中继续添加代码。
⚠️ 如果需要,可以参考 项目1第4课编写服务器代码 和 通过MQTT发送命令 的说明。
添加相关的设备代码,从接收到的消息中控制继电器,使用消息中的relay_on属性。如果soil_moisture大于450,则发送true,否则发送false,与你之前为物联网设备添加的逻辑相同。
⚠️ 如果需要,可以参考 项目1第4课响应MQTT命令的说明。
你可以在 code-mqtt 文件夹中找到这些代码。
确保你的设备和本地服务器上的代码正在运行,并通过改变土壤湿度水平来测试它,无论是通过改变虚拟传感器发送的值,还是通过加水或取出传感器来改变土壤湿度水平。
回到第3课,你构建了一个夜灯——一个在光线传感器检测到低光照水平时立即接通的LED。光线传感器瞬间检测到光水平的变化,设备能够快速响应,仅受loop函数或while True:循环中的延迟限制。作为一个物联网开发者,你不能总是依赖这样的快速反馈回路。
如果你在上一课中使用物理传感器监测土壤湿度,你会发现浇水后几秒钟土壤湿度读数才会下降。这不是因为传感器慢,而是因为水需要时间渗透到土壤中。
如果你浇水的位置离传感器太近,你可能会看到读数迅速下降,然后又上升——这是因为靠近传感器的水分扩散到土壤的其他部分,减少了传感器处的土壤湿度。

在上述图表中,土壤湿度读数显示为658。给植物浇水时,读数不会立即改变,因为水还没有到达传感器。甚至在水完全渗透土壤之前,浇水过程就已经结束,读数值反映新的湿度水平。
如果你正在编写基于土壤湿度控制灌溉系统的代码,你需要考虑到这种延迟,并在你的物联网设备中加入更智能的定时功能。
✅ 想一想你可能怎么做。
假设你被委派为农场建造一个灌溉系统。根据土壤类型,种植的植物理想的土壤湿度水平已确定为400-450的模拟电压读数。
你可以像夜灯那样编程——只要传感器读数高于450,就接通继电器启动水泵。问题在于水从水泵通过土壤到达传感器需要一段时间。传感器会在读数达到450时停止供水,但随着泵入的水继续渗透土壤,土壤湿度水平将继续下降。最终结果是浪费水,并且有根部受损的风险。
✅ 记住——太多水对植物和太少水一样有害,还会浪费宝贵的资源。
更好的解决方案是理解在执行器接通和传感器读取的属性发生变化之间存在延迟。这意味着不仅传感器需要等待一段时间后再测量值,执行器也需要在下一次传感器测量前关闭一段时间。
每次继电器应该接通多久?最好谨慎行事,只接通继电器一小段时间,然后等待水渗透,然后再检查湿度水平。毕竟,你可以随时再次接通继电器以添加更多水分,而不能从土壤中移除水分。
这种定时控制非常具体于你正在构建的物联网设备、测量的属性以及使用的传感器和执行器。
例如,我有一棵草莓植物,上面有一个土壤湿度传感器和一个由继电器控制的水泵。我发现当我加水时,大约需要20秒土壤湿度读数才能稳定下来。这意味着在检查湿度之前,我需要关闭继电器并等待20秒。我宁愿土壤湿度过低也不愿过高——如果湿度过高,我可以随时再次启动水泵,但无法从植物中取出多余的水分。

这意味着最佳流程应该是一个浇水周期,类似于:
对于泵来说,5秒钟可能太长了,特别是当湿度仅略高于所需水平时。了解使用什么时间的最佳方法是尝试一下,然后根据传感器数据进行调整,并持续反馈循环。这甚至可以细化到每高出100个湿度单位就打开泵1秒,而不是固定5秒。
✅ 进行一些研究:还有哪些其他时间考虑因素?植物是否可以在土壤湿度过低时随时浇水,或者是否有特定的时间段是浇水的好时机或坏时机?
在控制户外种植的自动灌溉系统时,也可以将天气预报纳入考虑。如果预计会有雨,那么可以暂停浇水直到雨停。这时土壤可能已经足够湿润,不需要再浇水,这样比在下雨前浇水更高效。
服务器代码可以修改为围绕浇水周期的定时控制以及等待土壤湿度变化。控制继电器时间的服务器逻辑如下:
浇水周期,即从收到遥测消息到再次处理土壤湿度水平的过程大约需要25秒。我们每10秒发送一次土壤湿度水平,因此在服务器等待土壤湿度水平稳定时,可能会有另一条消息被接收,从而开始另一个浇水周期。
有两种方法来解决这个问题:
第一个选项对于大型农场并不总是好的解决方案。农民可能希望在浇水过程中捕获土壤湿度水平以供日后分析,例如为了了解农场不同区域的水流情况,从而指导更精确的浇水。第二种方案更好——代码只是忽略无法使用的遥测消息,但遥测消息仍然存在,可供其他订阅这些消息的服务使用。
物联网数据不是只从一个设备发送到一个服务,而是许多设备可以将数据发送到代理,许多服务可以从代理中监听数据。例如,一个服务可以监听土壤湿度数据并将其存储在数据库中,以便日后分析。另一个服务也可以监听相同的遥测数据来控制灌溉系统。
更新您的服务器代码,使其运行继电器5秒,然后等待20秒。
如果尚未打开,请在VS Code中打开soil-moisture-sensor-server文件夹。确保激活了虚拟环境。
打开app.py文件
在app.py文件中现有导入语句下方添加以下代码:
import threading
这段代码导入了用于处理服务器接收到的遥测消息的threading from Python libraries, threading allows python to execute other code while waiting.
Add the following code before the handle_telemetry函数:
water_time = 5 wait_time = 20
这定义了运行继电器的时间(water_time), and how long to wait afterwards to check the soil moisture (wait_time)。
在这段代码下方添加以下内容:
def send_relay_command(client, state): command = { 'relay_on' : state } print("Sending message:", command) client.publish(server_command_topic, json.dumps(command))
这段代码定义了一个名为send_relay_command that sends a command over MQTT to control the relay. The telemetry is created as a dictionary, then converted to a JSON string. The value passed into state determines if the relay should be on or off.
After the send_relay_code函数,添加以下代码:
def control_relay(client): print("Unsubscribing from telemetry") mqtt_client.unsubscribe(client_telemetry_topic) send_relay_command(client, True) time.sleep(water_time) send_relay_command(client, False) time.sleep(wait_time) print("Subscribing to telemetry") mqtt_client.subscribe(client_telemetry_topic)
这段代码定义了一个根据所需时间控制继电器的函数。它首先取消订阅遥测消息,以防止在浇水期间处理土壤湿度消息。接下来,它发送一个命令以打开继电器。然后等待water_time before sending a command to turn the relay off. Finally it waits for the soil moisture levels to stabilize for wait_time seconds. It then re-subscribes to telemetry.
Change the handle_telemetry函数添加以下代码:
def handle_telemetry(client, userdata, message): payload = json.loads(message.payload.decode()) print("Message received:", payload) if payload['soil_moisture'] > 450: threading.Thread(target=control_relay, args=(client,)).start()
这段代码检查土壤湿度水平。如果大于450,说明土壤需要浇水,因此调用control_relay函数。这个函数在一个单独的线程上运行,后台执行。
确保您的IoT设备正在运行,然后运行此代码。改变土壤湿度水平并观察继电器的变化——它应该打开5秒,然后至少关闭20秒,只有在土壤湿度水平不足时才会再次打开。
(.venv) ➜ soil-moisture-sensor-server ✗ python app.py Message received: {'soil_moisture': 457} Unsubscribing from telemetry Sending message: {'relay_on': True} Sending message: {'relay_on': False} Subscribing to telemetry Message received: {'soil_moisture': 302}
在模拟灌溉系统中测试这一点的一个好方法是使用干燥的土壤,然后在继电器打开时手动倒入水,当继电器关闭时停止倒水。
您可以在code-timing文件夹中找到此代码。
如果您想使用泵建立一个实际的灌溉系统,可以使用一个6V微型水泵,并配一个USB终端电源供应。确保泵的电源通过继电器连接。
您能否想到其他具有类似问题的物联网或其他电气设备,其中执行器的结果需要一段时间才能达到传感器?
声明:
本文件灏天文库团队进行了翻译。尽管我们力求准确,但请注意,翻译可能包含错误或不准确之处。原文档以其原始语言为准。我们不对因使用此翻译而产生的任何误解或误译负责。