NodeMCU ESP8266 板可監控植物的土壤水分,并在需要澆水時通過 Telegram 通知您!
為什么要做這個項目?
我可能是萬千個一直忘記給植物澆水的人其中的一份子,有多少植物因為你忘記了你甚至在家里有它們而枯萎?
我就是其中之一,因此我決定創建一個項目,讓我知道我什么時候沒有給我的鱷梨植物澆水。
目標
起初的目標只是需要知道我什么時候需要給植物澆水。但既然我正在開發這個工具,為什么不添加一些額外的選項,比如能夠按需檢查鱷梨的表現。
我使用了一個 Arduino 兼容板“WeMos D1 NodeMcu Lua V3 CH340G ESP8266”,可以在 eBay 上購買。
還選擇了“ESP8266板”,因為內置wifi功能和便宜的價格。我們不需要太多的電力,所以沒有必要使用 ESP-32 板。
要知道鱷梨是否需要澆水,我使用了土壤濕度傳感器 YL-69(或 YL-39)。通過它的電極,我們可以確定植物土壤的干燥程度。該傳感器也可在 eBay 上購買。
傳感器有一個電位器,可以校準返回的值。
該板將使用 VIN 和 GND 引腳由 9V 電池供電。
注意:根據您使用的電路板,輸入電壓可能會有所不同。在某些情況下,允許的輸入會寫在板上。
軟件
Arduino IDE 用于該項目。
第一步是創建一個 Telegram 機器人。由于網上已經有很多關于如何做到這一點的教程,這一步我就不做過多解釋。請參閱下面的鏈接以開始使用。
如果您不想使用 Telegram 機器人,可以使用IFTTT 。
為了與機器人通信,我使用了 Giancarlo Bacchio 開發的“ ESP8266-TelegramBot ”庫,該庫可在此找到。
為了能夠在我需要給植物澆水時收到通知,我設置了一個 Telegram 機器人來向我發送通知。每隔 24 小時,系統會檢查狀態并在達到關鍵限制時通知我。
由于 Telegram 機器人為我們提供了相當大的自由度,因此我實現了一個額外的命令來隨時讀取傳感器值。
根據土壤的不同,從傳感器讀取的值可能與我的示例不同。以下是電位器完全逆時針旋轉(最小值)時返回的值。
澆水后: 460
24 小時后:420
48 小時后:380
我通常每 2 天給鱷梨澆一次水,所以我決定使用400作為臨界值。一旦讀取的值低于此值,我將收到通知。
警告
為避免損壞傳感器,我們僅在讀取土壤濕度時才將其通電。因此,它不是直接連接到 3.3V 引腳,而是連接到數字引腳之一。
未來的拓展
這個項目的一個改進是添加一些視覺效果,也許是一個 LED,它可以通過將顏色從綠色變為黃色再變為紅色來為您提供狀態。
另一種選擇是通過使用運行在 3.3V/8MHz 的 Arduino Pro Mini 和 ESP-01 來延長電池壽命。
如果您想更在此基礎上更進一步,您還可以使用水泵構建一個自動澆水系統!
Avocado Watering Monitor:
/*
? ?Avocado Watering Monitor
? ?Board used: WeMos D1 NodeMcu Lua V3 ESP8266
? ?Sensor: YL-69 / YL-39 Soil Moisture Sensor
? ?By g4x - 01/2018
*/
#include
#include
#include
// YL-69 sensor
#define moistureCriticalLevel 400
byte pinMoistureSensor = A0;
byte pinMoistureVCC = 4; // D2
int ?moistureValue;
// protothreading
int ?moistureReadingInterval = 86400; ? // interval in seconds between sensor reading (every 24h)
long moistureLastRead = 0; ? ? ? ? ? ? ?// last time the moisture was read
int ?botScanInterval = 1; ? ? ? ? ? ? ? // interval time between scan messages (seconds)
long botLastScan; ? ? ? ? ? ? ? ? ? ? ? // last time messages' scan has been done
long nowMillis;
// WiFi connection
const char* ssid ? ? = "Mr.Robot"; ? ? ?// wifi name
const char* password = "********"; ? ? ?// wifi password
// Telegram bot
#define botMyChatID "********" ? ? ? ? ?// reference to my phone's chat
#define botToken "********"
#define botName "********";
#define botUsername "********"
TelegramBOT bot(botToken, botName, botUsername);
String botCommand;
String botResponse;
void setup() {
? Serial.begin(9600);
? delay(1000);
? // init the moisture sensor
? pinMode(pinMoistureSensor, INPUT);
? pinMode(pinMoistureVCC, OUTPUT);
? digitalWrite(pinMoistureVCC, LOW); ? ?// by default, we do not power the sensor
? // connect to wifi
? Serial.print("Connecting to "");
? Serial.print(ssid);
? Serial.println(""");
? WiFi.begin(ssid, password);
? while (WiFi.status() != WL_CONNECTED) {
? ? delay(500);
? ? Serial.print(".");
? }
? Serial.println("");
? Serial.print("WiFi connected (");
? Serial.print(WiFi.localIP());
? Serial.println(")");
? Serial.println("");
? // start bot
? bot.begin();
}
void loop() {
? checkSoilMoisture();
? handleBotMessages();
}
void checkSoilMoisture() {
? nowMillis = millis();
? if ((nowMillis > moistureLastRead + (moistureReadingInterval * 1000)) or moistureLastRead == 0) {
? ? moistureLastRead = nowMillis;
? ? moistureValue = readMoisture();
? ? if (moistureValue < moistureCriticalLevel) {
? ? ? // send value to Telegram chat
? ? ? botResponse = "Avocado: Water me! (Humidity Level [0-1023]: ";
? ? ? botResponse.concat(moistureValue);
? ? ? botResponse.concat(")");
? ? ? bot.sendMessage(botMyChatID, botResponse, ""); ? ?// send notification to my phone
? ? }
? ? Serial.print("*************** Humidity Level (0-1023): ");
? ? Serial.println(moistureValue);
? ? Serial.println("");
? }
}
int readMoisture() {
? digitalWrite(pinMoistureVCC, HIGH); // power up sensor
? delay(500);
? int value = analogRead(pinMoistureSensor);
? digitalWrite(pinMoistureVCC, LOW); // power down sensor
? return 1023 - value;
}
/* Check if the bot received any message */
void handleBotMessages() {
? nowMillis = millis();
? if (nowMillis > botLastScan + (botScanInterval * 1000)) {
? ? botLastScan = millis();
? ? bot.getUpdates(bot.message[0][1]); ? // launch API GetUpdates up to xxx message
? ? // loop at messages received
? ? for (int i = 1; i < bot.message[0][0].toInt() + 1; i++) ? ? ?{
? ? ? handleBotCommands(i);
? ? }
? ? bot.message[0][0] = ""; ? // All messages have been replied - reset new messages
? }
}
/* Execute command sent to the bot */
void handleBotCommands(int line) {
? botCommand = bot.message[line][5]; // message reiceived
? botCommand.toUpperCase(); ?// not case sensitive anymore
? if (botCommand.equals("/READ")) {
? ? // read data
? ? moistureValue = readMoisture();
? ? //botResponse = "Sensor value: ";
? ? botResponse = "Humidity Level (0-1023): ";
? ? botResponse.concat(moistureValue);
? ? if (moistureValue < moistureCriticalLevel) {
? ? ? botResponse.concat(" (critical)");
? ? }
? } else if (botCommand.equals("/HELP")) {
? ? botResponse = "Allowed commands are:";
? ? bot.sendMessage(bot.message[line][4], botResponse, "");
? ? botResponse = "/read - Read soil moisture";
? ? bot.sendMessage(bot.message[line][4], botResponse, "");
? ? botResponse = "/ip - Get local IP address";
? } else if (botCommand.equals("HI") or botCommand.equals("HELLO") or botCommand.equals("COUCOU") or botCommand.equals("SALUT")) {
? ? botResponse = "Hello " + bot.message[line][2] + " !"; ?// user's name
? ??
? } else if (botCommand.equals("/IP")) {
? ??
? ? botResponse = "Local IP address: ";
? ? botResponse.concat(WiFi.localIP().toString());
? ??
? } else {
? ? botResponse = "Unknown command, use /help for command list.";
? }
? bot.sendMessage(bot.message[line][4], botResponse, ""); ? ?// bot.message[line][4] is chat ID
}
評論
查看更多