跳至主要内容

自動植物澆水

本課程的概述手繪筆記

手繪筆記由 Nitya Narasimhan 提供。點擊圖片查看大圖。

本課程是 IoT 01 for Beginners Project 2 - Digital Agriculture series 的一部分,由 Microsoft Reactor 提供。

物聯網驅動的自動植物澆水

課前測驗

課前測驗

介紹

在上一課中,你學會了如何監測土壤濕度。在本課中,你將學習如何構建自動澆水系統的核心組件,該系統能夠根據土壤濕度進行反應。你還將學習有關時間的知識——傳感器可能需要一段時間才能對變化做出反應,而執行器可能需要時間來改變傳感器測量的屬性。

在本課中,我們將涵蓋:

從低功率物聯網設備控制高功率設備

物聯網設備使用低電壓。雖然這對於傳感器和低功率執行器(如 LED)來說已經足夠,但對於控制較大的硬件(如用於灌溉的水泵)來說,這個電壓太低。即使是你可以用於室內植物的小型泵也會消耗過多的電流,會燒壞物聯網開發套件。

🎓 電流,以安培(A)為單位,是通過電路的電量。電壓提供推動力,電流是被推動的量。你可以在 維基百科的電流頁面 上閱讀更多關於電流的內容。

解決方案是將泵連接到外部電源,並使用執行器來打開泵,就像你打開燈一樣。用你的手指翻轉開關只需要很少的能量(來自你身體的能量),這樣就可以將燈連接到 110v/240v 的市電。

一個開關打開燈的電源

🎓 市電 是指通過國家基礎設施向家庭和企業提供的電力。

✅ 物聯網設備通常可以提供 3.3V 或 5V,電流小於 1 安培(1A)。與此相比,市電通常為 230V(北美為 120V,日本為 100V),可以為消耗 30A 電流的設備提供電力。

有許多執行器可以做到這一點,包括可以附加到現有開關上的機械裝置,模仿手指打開它們。最受歡迎的是繼電器。

繼電器

繼電器是一種電機開關,它將電信號轉換為機械運動,從而打開開關。繼電器的核心是一個電磁鐵。

🎓 電磁鐵 是通過電線圈通電而產生的磁鐵。當電流打開時,線圈被磁化。當電流關閉時,線圈失去磁性。

當打開時,電磁鐵產生磁場,打開輸出電路的開關

在繼電器中,控制電路為電磁鐵供電。當電磁鐵打開時,它拉動一個杠杆,移動開關,閉合一對觸點,完成輸出電路。

當關閉時,電磁鐵不產生磁場,關閉輸出電路的開關

當控制電路關閉時,電磁鐵關閉,釋放杠杆並打開觸點,關閉輸出電路。繼電器是數字執行器——高信號打開繼電器,低信號關閉繼電器。

輸出電路可以用來為額外的硬件供電,如灌溉系統。物聯網設備可以打開繼電器,完成為灌溉系統供電的輸出電路,植物得到澆水。然後物聯網設備可以關閉繼電器,切斷灌溉系統的電源,關閉水。

繼電器打開,打開泵,將水送到植物

在上面的视频中,繼電器被打開。繼電器上的 LED 亮起,表示它已打開(某些繼電器板上有 LED 指示繼電器是打開還是關閉),電源被送到泵,打開泵並將水泵入植物。

💁 繼電器還可以用來在兩個輸出電路之間切換,而不是打開和關閉一個輸出電路。當杠杆移動時,它將開關從完成一個輸出電路移動到完成另一個輸出電路,通常共享一個公共電源連接或公共接地連接。

✅ 做一些研究:有多種類型的繼電器,其差異包括控制電路在通電時打開或關閉繼電器,或多個輸出電路。了解這些不同類型的繼電器。

當杠杆移動時,你通常可以聽到它與電磁鐵接觸時發出的明確的咔嗒聲。

💁 繼電器可以接線,使得連接實際上會斷開繼電器的電源,關閉繼電器,然後再次向繼電器供電,如此反復。這意味著繼電器會非常快速地點擊,發出嗡嗡聲。這是一些早期電鈴中使用的蜂鳴器的工作原理。

繼電器電源

電磁鐵不需要大量電力來激活和拉動杠杆,它可以使用物聯網開發套件的 3.3V 或 5V 輸出來控制。輸出電路可以承載更多的電力,取決於繼電器,包括市電電壓甚至更高的工業用電力。這樣,物聯網開發套件可以控制灌溉系統,從單個植物的小泵到整個商業農場的大型工業系統。

一個標有控制電路、輸出電路和繼電器的 Grove 繼電器

上圖顯示了一個 Grove 繼電器。控制電路連接到物聯網設備,使用 3.3V 或 5V 打開或關閉繼電器。輸出電路有兩個端子,任何一個都可以是電源或接地。輸出電路可以處理高達 250V、10A 的電壓,足以應對一系列市電設備。你可以獲得可以處理更高功率水平的繼電器。

通過繼電器連接的泵

在上圖中,電源通過繼電器供應給泵。有一根紅色電線將 USB 電源的 +5V 端子連接到繼電器的輸出電路的一個端子,另一根紅色電線將輸出電路的另一個端子連接到泵。一根黑色電線將泵連接到 USB 電源的接地端子。當繼電器打開時,它完成電路,將 5V 送到泵,打開泵。

控制繼電器

你可以從你的物聯網開發套件控制繼電器。

任務 - 控制繼電器

通過相關指南,使用你的物聯網設備控制繼電器:

通過 MQTT 控制你的植物

到目前為止,你的繼電器是由物聯網設備直接根據單個土壤濕度讀數控制的。在商業灌溉系統中,控制邏輯將集中化,允許它使用多個傳感器的數據來做出澆水決策,並允許在一個地方更改任何配置。為了模擬這一點,你可以通過 MQTT 控制繼電器。

任務 - 通過 MQTT 控制繼電器

  1. 添加相關的 MQTT 庫/pip 包和代碼到你的 soil-moisture-sensor 項目中以連接到 MQTT。將客戶端 ID 命名為 soilmoisturesensor_client,並在前面加上你的 ID。

    ⚠️ 你可以參考 項目 1,第 4 課中連接到 MQTT 的說明

  2. 添加相關的設備代碼以發送帶有土壤濕度設置的遙測數據。對於遙測消息,將屬性命名為 soil_moisture

    ⚠️ 你可以參考 項目 1,第 4 課中發送遙測數據到 MQTT 的說明

  3. 創建一些本地伺服器代碼來訂閱遙測數據並在名為 soil-moisture-sensor-server 的文件夾中發送控制繼電器的命令。將命令消息中的屬性命名為 relay_on,並將客戶端 ID 命名為 soilmoisturesensor_server,並在前面加上你的 ID。保持與你在項目 1,第 4 課中編寫的伺服器代碼相同的結構,因為你將在本課中添加到此代碼中。

    ⚠️ 你可以參考 項目 1,第 4 課中發送遙測數據到 MQTT 的說明通過 MQTT 發送命令 的說明。

  4. 添加相關的設備代碼以從接收到的命令控制繼電器,使用消息中的 relay_on 屬性。如果 soil_moisture 大於 450,則發送 true 給 relay_on,否則發送 false,與你之前為物聯網設備添加的邏輯相同。

    ⚠️ 你可以參考 項目 1,第 4 課中響應來自 MQTT 的命令的說明

💁 你可以在 code-mqtt 文件夾中找到此代碼。

確保代碼在你的設備和本地伺服器上運行,並通過更改土壤濕度水平來測試它,無論是通過更改虛擬傳感器發送的值,還是通過添加水或從土壤中移除傳感器來更改土壤的濕度水平。

傳感器和執行器的時間

在第 3 課中,你構建了一個夜燈——當光傳感器檢測到低光水平時,LED 會立即打開。光傳感器立即檢測到光水平的變化,設備能夠快速響應,僅受 loop 函數或 while True: 循環中延遲的限制。作為物聯網開發者,你不能總是依賴這樣的快速反饋循環。

土壤濕度的時間

如果你在上一課中使用了物理傳感器進行土壤濕度測量,你會注意到在澆水後,土壤濕度讀數需要幾秒鐘才能下降。這不是因為傳感器慢,而是因為水需要時間滲透到土壤中。

💁 如果你在傳感器附近澆水,你可能會看到讀數迅速下降,然後回升——這是因為傳感器附近的水分散到土壤的其他部分,減少了傳感器附近的土壤濕度。

在澆水期間,土壤濕度讀數為 658,不會改變,只有在澆水後,當水滲透到土壤中時,讀數才會下降到 320

在上圖中,土壤濕度讀數顯示為 658。植物被澆水,但這個讀數不會立即改變,因為水還沒有到達傳感器。澆水甚至可能在水到達傳感器之前結束,讀數才會下降以反映新的濕度水平。

如果你正在編寫代碼來根據土壤濕度水平通過繼電器控制灌溉系統,你需要考慮這個延遲並在你的物聯網設備中構建更智能的時間控制。

✅ 花點時間思考你可能會怎麼做。

控制傳感器和執行器的時間

想像一下,你被要求為一個農場構建一個灌溉系統。根據土壤類型,已經發現植物生長的理想土壤濕度水平與 400-450 的模擬電壓讀數相匹配。

你可以像夜燈一樣編程設備——當傳感器讀數高於 450 時,打開繼電器以打開泵。問題是水需要一段時間才能從泵通過土壤到達傳感器。傳感器會在檢測到 450 的水平時停止供水,但水位會繼續下降,因為泵送的水會繼續滲透到土壤中。最終結果是浪費水,並且有根部損壞的風險。

✅ 記住——過多的水對植物的危害與過少的水一樣,並且浪費寶貴的資源。

更好的解決方案是理解執行器打開和傳感器讀取的屬性改變之間存在延遲。這意味著傳感器不僅應該等待一段時間再測量值,執行器還需要在下一次傳感器測量之前關閉一段時間。

每次繼電器應該打開多長時間?最好謹慎行事,只打開繼電器一小段時間,然後等待水滲透,然後重新檢查濕度水平。畢竟,你總是可以再次打開它來添加更多的水,但你不能從土壤中移除水。

💁 這種時間控制非常特定於你正在構建的物聯網設備、你正在測量的屬性以及使用的傳感器和執行器。

一個草莓植物通過泵連接到水,泵通過繼電器連接。繼電器和植物中的土壤濕度傳感器都連接到 Raspberry Pi

例如,我有一個草莓植物,帶有土壤濕度傳感器和由繼電器控制的泵。我觀察到當我添加水時,土壤濕度讀數需要大約 20 秒才能穩定下來。這意味著我需要關閉繼電器並等待 20 秒再檢查濕度水平。我寧願水少一點也不願水多——我可以隨時再次打開泵,但我不能從植物中取出水。

步驟 1,測量。步驟 2,添加水。步驟 3,等待水滲透到土壤中。步驟 4,重新測量

這意味著最佳過程將是類似於以下的澆水循環:

  • 打開泵 5 秒
  • 等待 20 秒
  • 檢查土壤濕度
  • 如果水平仍然高於我需要的,重複上述步驟

5 秒對於泵來說可能太長了,特別是如果濕度水平僅略高於所需水平。知道應該使用什麼時間的最佳方法是嘗試,然後在有傳感器數據時進行調整,保持不斷的反饋循環。這甚至可以導致更細粒度的時間控制,例如每 100 高於所需土壤濕度時打開泵 1 秒,而不是固定的 5 秒。

✅ 做一些研究:還有其他時間考慮因素嗎?當土壤濕度過低時,植物可以隨時澆水,還是有特定的時間適合和不適合澆水?

💁 當控制戶外種植的自動澆水系統時,還可以考慮天氣預報。如果預計會下雨,那麼澆水可以推遲到雨後。此時土壤可能已經足夠濕潤,不需要澆水,比在下雨前浪費水更有效。

為你的植物控制伺服器添加時間

可以修改伺服器代碼以添加有關澆水循環時間控制的邏輯,並等待土壤濕度水平的變化。控制繼電器時間的伺服器邏輯如下:

  1. 接收到遙測消息
  2. 檢查土壤濕度水平
  3. 如果它是正常的,什麼都不做。如果讀數太高(意味著土壤濕度太低),則:
    1. 發送命令打開繼電器
    2. 等待 5 秒
    3. 發送命令關閉繼電器
    4. 等待 20 秒讓土壤濕度水平穩定

澆水循環,即從接收到遙測消息到準備再次處理土壤濕度水平的過程,大約需要 25 秒。我們每 10 秒發送一次土壤濕度水平,因此在伺服器等待土壤濕度水平穩定時會有重疊,這可能會開始另一個澆水循環。

有兩個選擇來解決這個問題:

  • 更改物聯網設備代碼,使其每分鐘只發送一次遙測數據,這樣澆水循環將在下一條消息發送之前完成
  • 在澆水循環期間取消訂閱遙測數據

第一個選擇並不總是大型農場的好解決方案。農民可能希望在澆水期間捕獲土壤濕度水平,以便以後進行分析,例如了解農場不同區域的水流情況,以指導更有針對性的澆水。第二個選擇更好——代碼只是忽略它不能使用的遙測數據,但遙測數據仍然存在於其他可能訂閱它的服務中。

💁 物聯網數據不是僅從一個設備發送到一個服務,而是許多設備可以將數據發送到代理,許多服務可以從代理中收聽數據。例如,一個服務可以收聽土壤濕度數據並將其存儲在數據庫中以便以後進行分析。另一個服務也可以收聽相同的遙測數據來控制灌溉系統。

任務 - 為你的植物控制伺服器添加時間

更新你的伺服器代碼,使其運行繼電器 5 秒,然後等待 20 秒。

  1. 如果尚未打開,請在 VS Code 中打開 soil-moisture-sensor-server 文件夾。確保虛擬環境已激活。

  2. 打開 app.py 文件

  3. 在現有導入語句下方添加以下代碼到 app.py 文件中:

    import threading

    此語句從 Python 庫中導入 threading,threading 允許 python 在等待時執行其他代碼。

  4. handle_telemetry 函數之前添加以下代碼:

    water_time = 5
    wait_time = 20

    這定義了運行繼電器的時間(water_time)和之後等待的時間(wait_time)。

  5. 在此代碼下方添加以下代碼:

    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 的函數,用於通過 MQTT 發送控制繼電器的命令。遙測數據被創建為字典,然後轉換為 JSON 字符串。傳遞給 state 的值決定繼電器應該打開還是關閉。

  6. 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,然後發送命令關閉繼電器。最後,它等待 wait_time 秒讓土壤濕度水平穩定。然後它重新訂閱遙測數據。

  7. 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 函數。此函數在單獨的線程上運行,在後台運行。

  8. 確保你的物聯網設備正在運行,然後運行此代碼。更改土壤濕度水平並觀察繼電器的變化——它應該打開 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 終端電源。確保泵的電源或泵的輸出通過繼電器連接。


🚀 挑戰

你能想到其他任何物聯網或其他電氣設備,它們有類似的問題,即執行器的結果需要一段時間才能到達傳感器。你家裡或學校裡可能有幾個這樣的設備。

  • 它們測量什麼屬性?
  • 在使用執行器後,屬性需要多長時間才能改變?
  • 屬性超過所需值可以嗎?
  • 如果需要,如何將其恢復到所需值?

課後測驗

課後測驗

回顧與自學

作業

構建更高效的澆水循環