NodeMCU ESP8266 板可監(jiān)控植物的土壤水分,并在需要澆水時(shí)通過(guò) Telegram 通知您!
為什么要做這個(gè)項(xiàng)目?
我可能是萬(wàn)千個(gè)一直忘記給植物澆水的人其中的一份子,有多少植物因?yàn)槟阃浟四闵踔猎诩依镉兴鼈兌菸?/p>
我就是其中之一,因此我決定創(chuàng)建一個(gè)項(xiàng)目,讓我知道我什么時(shí)候沒(méi)有給我的鱷梨植物澆水。
目標(biāo)
起初的目標(biāo)只是需要知道我什么時(shí)候需要給植物澆水。但既然我正在開(kāi)發(fā)這個(gè)工具,為什么不添加一些額外的選項(xiàng),比如能夠按需檢查鱷梨的表現(xiàn)。
我使用了一個(gè) Arduino 兼容板“WeMos D1 NodeMcu Lua V3 CH340G ESP8266”,可以在 eBay 上購(gòu)買(mǎi)。
還選擇了“ESP8266板”,因?yàn)閮?nèi)置wifi功能和便宜的價(jià)格。我們不需要太多的電力,所以沒(méi)有必要使用 ESP-32 板。
要知道鱷梨是否需要澆水,我使用了土壤濕度傳感器 YL-69(或 YL-39)。通過(guò)它的電極,我們可以確定植物土壤的干燥程度。該傳感器也可在 eBay 上購(gòu)買(mǎi)。
傳感器有一個(gè)電位器,可以校準(zhǔn)返回的值。
該板將使用 VIN 和 GND 引腳由 9V 電池供電。
注意:根據(jù)您使用的電路板,輸入電壓可能會(huì)有所不同。在某些情況下,允許的輸入會(huì)寫(xiě)在板上。
軟件
Arduino IDE 用于該項(xiàng)目。
第一步是創(chuàng)建一個(gè) Telegram 機(jī)器人。由于網(wǎng)上已經(jīng)有很多關(guān)于如何做到這一點(diǎn)的教程,這一步我就不做過(guò)多解釋。請(qǐng)參閱下面的鏈接以開(kāi)始使用。
如果您不想使用 Telegram 機(jī)器人,可以使用IFTTT 。
為了與機(jī)器人通信,我使用了 Giancarlo Bacchio 開(kāi)發(fā)的“ ESP8266-TelegramBot ”庫(kù),該庫(kù)可在此找到。
為了能夠在我需要給植物澆水時(shí)收到通知,我設(shè)置了一個(gè) Telegram 機(jī)器人來(lái)向我發(fā)送通知。每隔 24 小時(shí),系統(tǒng)會(huì)檢查狀態(tài)并在達(dá)到關(guān)鍵限制時(shí)通知我。
由于 Telegram 機(jī)器人為我們提供了相當(dāng)大的自由度,因此我實(shí)現(xiàn)了一個(gè)額外的命令來(lái)隨時(shí)讀取傳感器值。
根據(jù)土壤的不同,從傳感器讀取的值可能與我的示例不同。以下是電位器完全逆時(shí)針旋轉(zhuǎn)(最小值)時(shí)返回的值。
澆水后: 460
24 小時(shí)后:420
48 小時(shí)后:380
我通常每 2 天給鱷梨澆一次水,所以我決定使用400作為臨界值。一旦讀取的值低于此值,我將收到通知。
警告
為避免損壞傳感器,我們僅在讀取土壤濕度時(shí)才將其通電。因此,它不是直接連接到 3.3V 引腳,而是連接到數(shù)字引腳之一。
未來(lái)的拓展
這個(gè)項(xiàng)目的一個(gè)改進(jìn)是添加一些視覺(jué)效果,也許是一個(gè) LED,它可以通過(guò)將顏色從綠色變?yōu)辄S色再變?yōu)榧t色來(lái)為您提供狀態(tài)。
另一種選擇是通過(guò)使用運(yùn)行在 3.3V/8MHz 的 Arduino Pro Mini 和 ESP-01 來(lái)延長(zhǎng)電池壽命。
如果您想更在此基礎(chǔ)上更進(jìn)一步,您還可以使用水泵構(gòu)建一個(gè)自動(dòng)澆水系統(tǒng)!
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
}
評(píng)論
查看更多