Matteo_TassiDaniele_Andrea
Published © GPL3+

Smart Irrigation | Capacitive soil moisture sensor @VALLAURI

Here, we learn how to make a Smart Irrigation System in which wemos can sense the moisture of the plant soil and watering it accordingly.

IntermediateWork in progress2 hours805
Smart Irrigation | Capacitive soil moisture sensor @VALLAURI

Things used in this project

Hardware components

Wemos D1 mini Shields
×1
Wemos SD shield
×1
Wemos Relays shield
×1
Jumper wires (generic)
Jumper wires (generic)
×1
Capactive soil moisture sensor
×1
Wemos Triple base
×1
Transformer
×1
Seaflow350 pump
×1
PVC pipes
×1
USB-A to Mini-USB Cable
USB-A to Mini-USB Cable
×1

Software apps and online services

Autodesk AutoCAD
Cura
Solidworks
Tinkercad
Autodesk Tinkercad
Lasercut
Makercase
Arduino IDE
Arduino IDE

Hand tools and fabrication machines

Laser cutter (generic)
Laser cutter (generic)
3D Printer (generic)
3D Printer (generic)

Story

Read more

Custom parts and enclosures

AutoCAD for the sensor

AutoCAD for wemos

SOLIDWORKS for custom pieces of the pump

SOLIDWORKS for watering nozzle

Schematics

Grafcet

Grafcet 2

Code

Smart irrigation

C/C++
Change the Bot token, the WiFi password and SSID
#include <ESP8266WiFi.h> //library for ESP8266 WIFI
#include <WiFiClientSecure.h>//library used to make the BOT private
#include <UniversalTelegramBot.h> //library for telegram bot
#include <SPI.h> //library for SD shield
#include <SD.h> //library for SD shield
#include <WiFiUdp.h> //library for time  used on the SD shield
#include <NTPClient.h> //library for time used on the SD shield

// Wifi network station credentials
#define WIFI_SSID "************" //include the WiFi name
#define WIFI_PASSWORD "*************************" //include the WiFi password
#define BOT_TOKEN "********************************************"// Telegram BOT Token (Get from Botfather)

X509List cert(TELEGRAM_CERTIFICATE_ROOT);
WiFiClientSecure secured_client;
UniversalTelegramBot bot(BOT_TOKEN, secured_client);

unsigned long bot_lasttime; // last time messages' scan has been done
const unsigned long BOT_MTBS = 1000; // mean time between scan messages
const int ledPin = D1; //Relè shield
const int chipSelect = D4; //SD shield
int ledStatus = 0; //used to control the pump
int dato_sensore1 = 0; //humidity value
int mem = 0; //used to control the pump


//SECTION OF THE LISTING USED FOR HANDLE NEW MESSAGES (TELEGRAM BOT)
void handleNewMessages(int numNewMessages){
int dato_sensore1 = analogRead(A0); //read the value from the humidity sensor
dato_sensore1 = map(dato_sensore1, 300, 1000, 100, 0); //map this value to "%" (0% - 100%)

  Serial.print("handleNewMessages ");
  Serial.println(numNewMessages);

for (int i = 0; i < numNewMessages; i++){
    String chat_id = bot.messages[i].chat_id;
    String text = bot.messages[i].text;
    String from_name = bot.messages[i].from_name;
    if (from_name == "")
        from_name = "Guest";

    if (text == "/SWITCHON"){
       ledStatus = 1;
       digitalWrite(ledPin, HIGH); // turn the pump ON (HIGH is the voltage level)
       bot.sendMessage(chat_id, "PUMP IS ON BUT SHE SWITCH OFF AFTER 5 SECONDS", ""); //the program takes 5 seconds to return a value.
       }

    if (text == "/SWITCHOFF"){
       ledStatus = 0;
       digitalWrite(ledPin, LOW); // turn the pump OFF (LOW is the voltage level)
       bot.sendMessage(chat_id, "PUMP IS OFF", "");
       }

    if (text == "/HUMIDITY") {
       String data = (String(dato_sensore1));
       bot.sendMessage(chat_id, data , ""); //specifies the Humidity value
       }

    if (text == "/STATUS"){ //specifies the current status of the pump (ON or OFF)
      
       if (mem == 1){
          bot.sendMessage(chat_id, "PUMP IS ON", "");
       }
       else{
          bot.sendMessage(chat_id, "PUMP IS OFF", "");
       }
    }

    if (text == "/start"){ //specifies the function of each command 
    
      String welcome = "Welcome to Universal Telegram Bot " + from_name + ".\n";
      welcome += "This is ANNAFFIATORINO Bot example.\n\n";
      welcome += "/SWITCHON : to switch the pump ON\n";
      welcome += "/SWITCHOFF : to switch the pump OFF\n";
      welcome += "/STATUS : Returns current pump status\n";
      welcome += "/HUMIDITY : Returns current % soil humidity \n";
      bot.sendMessage(chat_id, welcome, "Markdown");
    }
  }
}

//time for SD card
const long utcOffsetInSeconds =3600;
String weekDays[7] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
String months[12] = {"January", "February", "March", "April", "May", "June", "July", "August", "Semptember", "October", "November", "December"};
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, ".pool.ntp.org.");

void setup(){
Serial.begin(115200); //initialize the serial monitor
Serial.println();
pinMode(mem, OUTPUT); // initialize mem as an output.
pinMode(ledPin, OUTPUT); // initialize ledPin as an output.
digitalWrite(ledPin, LOW); // initialize pin as off (active LOW)

// attempt to connect to Wifi network:
configTime(0, 0, "pool.ntp.org");      // get UTC time via NTP
secured_client.setTrustAnchors(&cert); // Add root certificate for api.telegram.org
Serial.print("Connecting to Wifi SSID ");
Serial.print(WIFI_SSID);
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
while (WiFi.status() != WL_CONNECTED){
       Serial.print(".");
       delay(500);
       }
timeClient.begin();
    
    
//SECTION OF THE LISTING FOR THE SD CARD
Serial.print("Initializing SD card...");
// see if the card is present and can be initialized:
    if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
// don't do anything more:
    return;
    }
Serial.println("card initialized.");
timeClient.begin(); //set offset time in seconds to adjust for your timezone
timeClient.setTimeOffset(3600); //in Italy, there is a GMT offset of +1 hour

//SECTION OF THE LISTING FOT THE TELEGRAM BOT
Serial.print("\nWiFi connected. IP address: ");//print in the serial monitor when wemos is connected to the WiFi 
Serial.println(WiFi.localIP());
}

void loop() {
int dato_sensore1 = analogRead(A0); //read the value from the humidity sensor
dato_sensore1 = map(dato_sensore1, 300, 1000, 100, 0); //map this value to "%" (0% - 100%)

//SECTION OF THE LISTING FOT THE TELEGRAM BOT
    if (millis() - bot_lasttime > BOT_MTBS){
        int numNewMessages = bot.getUpdates(bot.last_message_received + 1);
    while (numNewMessages){
      Serial.println("got response");//print in the serial monitor when telegram respons at the message
      handleNewMessages(numNewMessages);
      numNewMessages = bot.getUpdates(bot.last_message_received + 1); //increase the number of recived messages
      }
    bot_lasttime = millis();
   }
  
//SECTION OF THE LISTING FOR THE PUMP CONTROL

    if ((dato_sensore1 <=25) || (mem == 1)) {
       mem = 1; //set the mem value to 1
    
    if (dato_sensore1 <70){ 
       digitalWrite(ledPin, HIGH); //pump ON
    }
 }
    if (dato_sensore1 >70) {
       digitalWrite(ledPin, LOW); //pump OFF
       mem = 0; //set the mem value to 1
   }
   
//print values on the serial monitor
Serial.print("Humidity : ");
Serial.print(dato_sensore1);
Serial.print("%");
Serial.print("     ");
Serial.print("Mem : ");
Serial.println(mem);

//SECTION OF THE LISTING FOR THE SD shield

// make a string for assembling the data to log:
String dataString = "";
dataString = String(dato_sensore1); //write on the string the humidity sensore value
File dataFile = SD.open("Dati-sensore.CSV", FILE_WRITE); //write the value on the string of the file " "
  
if (dataFile) { //create an if to control the presence of the SD card  
     dataFile.print (weekDays[timeClient.getDay()]);
     dataFile.print (" | ");
     dataFile.print (timeClient. getFormattedTime ());
     dataFile.print (" | ");
     dataFile.print (timeClient. getEpochTime());
     dataFile.print (" | ");
     dataFile.println (dataString);
     dataFile.close(); //stop writing in the string create before
     Serial.print (weekDays[timeClient.getDay()]);
     Serial.print (" | ");
     Serial.println (timeClient. getFormattedTime ());
}
else{ //used to report the absence of the SD card
     Serial. println ( "error while opening Dati-sensore.CSV" );
}
delay(3000);
}

Credits

Matteo_Tassi

Matteo_Tassi

1 project • 1 follower
Daniele_Andrea

Daniele_Andrea

1 project • 2 followers

Comments