Analyzing Plant Health: Arduino-Based Smart Plant Monitoring With Real Time Data Analysis Using Python

 

Smart Plant Monitoring System


1.  Abstract:

This project introduces a Smart Plant Monitoring System that uses current soil moisture levels to automate plant watering. The Arduino Uno microcontroller, soil moisture sensor, 16x2 LCD display with I2C module, 5V relay module, and 5V water pump are used in the construction of the system. The Arduino receives data from the soil sensor, which continually checks the moisture content. The Arduino decides if the soil is dry, medium, or wet based on pre-established thresholds. The mechanism automatically turns on the pump through the relay to water the plant if the soil is dry.


1.    The LCD display makes user monitoring simple by displaying real-time soil condition and pump operation. A 3.7V Li-ion battery that has been increased to 5V powers the complete arrangement, making it portable and energy-efficient. This initiative promotes smart gardening by providing an affordable, dependable, and automated watering system.

Authors:

o   Shubham Das (Bioscience Student, Class-XII)

o   Rupam Das (M.Sc. Electronics, Guest Lecturer)




Date: 8th July, 2025

Place: Barrackpore, Kolkata


2.    Introduction

             I.          Plants require regular care and watering to stay healthy, but manual irrigation is time-consuming and inefficient, especially for people with busy schedules or in large-scale farming.
           II.    Smart gardening and automated irrigation systems can solve this problem by monitoring soil conditions and watering plants only when necessary.
        III.           This project focuses on building a Smart Plant Monitoring System using Arduino Uno, which automatically detects soil moisture and controls a water pump accordingly.
        IV.           The system uses a soil moisture sensor to measure the water content in the soil. Based on the moisture level, the Arduino controls a relay module to turn the water pump ON or OFF.
          V.          A 16x2 LCD display with an I2C module is used to display the real-time status of the soil (Dry, Medium, or Wet) and the pump (ON/OFF).
        VI.           The setup is powered by a 3.7V Li-ion battery boosted to 5V, making it portable and energy-efficient.

     VII.          The project aims to promote smart and sustainable farming practices, reduce water waste, and minimize the need for manual intervention.


3.  Required Components:

·       Arduino Uno

·       Soil Moisture Sensor

·       LCD Display

·       I2C Sensor

·       5volt Relay Module

·       Breadboard

·       5volt water pump

·       Jumper Wire
Note: For knowing the details of the components of this project visit the component section in our website

·      Soil Moisture Sensor

  

                                

The Soil Moisture Sensor is a simple and reliable tool used to detect the moisture level in the soil. It is widely used in smart irrigation systems, automatic plant watering projects, and DIY gardening setups. This sensor helps determine whether the soil is dry, moist, or wet by measuring the resistance between two metal probes.

It provides both analog output (for real-time moisture values) and digital output (with an adjustable threshold). The analog pin reads varying moisture levels, while the digital pin sends a HIGH or LOW signal based on soil conditions.

This sensor is compatible with Arduino, ESP32, NodeMCU, and other microcontrollers, making it ideal for home automation and IoT-based plant care systems.


Parameter

Value

 

Operating Voltage

3.3V – 5V DC

 

Output Type

Analog & Digital

 

Analog Output Range

0 – 1023 (10-bit ADC)

 

Digital Output Level

HIGH (wet), LOW (dry)

 

Probe Material

Nickel-plated / Copper

 

Dimensions

60mm x 20mm (sensor part)

 

Interface

3 Pins (VCC, GND, A0/D0)

 

 




4.   Circuit diagram

This system involves two representations of the electronic layout: the simplified block diagram and the detailed original circuit diagram. Both serve different purposes in understanding and implementing the system.

A.   Block Diagram Overview

                 

·        The block diagram is a high-level representation that shows how each component connects logically and functionally.

·        It includes the major parts: Arduino Uno, Soil Moisture Sensor, Relay Module, Water Pump, LCD Display, and Battery.

·        Arrows represent the flow of data (sensor readings), control signals (relay switching), and power.

·        This diagram is useful for conceptual understanding, presentations, and planning.

Key Blocks:

·        Soil Moisture Sensor → Arduino Uno → Relay Module → Water Pump

·        Arduino Uno → LCD Display

·        Battery → Powers all modules

B.   Original Circuit Design

    

·   The actual circuit diagram includes specific electrical connections, pin numbers, and wiring routes on a breadboard or PCB.

·        It shows how each component is physically wired to the Arduino and to each other.

·        The soil sensor’s analog output connects to pin A0 of Arduino.

·        The LCD (with I2C) connects to SDA (A4) and SCL (A5).

·        The relay IN pin is connected to digital pin D7.

·        The water pump connects to the normally open (NO) terminal of the relay and to the battery through the relay's switch.

·        All VCC and GND lines are properly distributed via the breadboard using the 5V supply (boosted from 3.7V Li-ion).

Highlights of the Circuit:

·        Analog signal → Digital decision → Electromechanical actuation

·        Uses I2C for efficient LCD connection

·        Relay isolates Arduino from pump’s higher current

      Summary of circuitry:

·        The block diagram is abstract and used for logic representation.

·        The original circuit is detailed and used for physical implementation.

·        Both are necessary to move from planning to building a functional project.


 

5.    Working Principle

The Smart Plant Monitoring System functions by continuously monitoring the soil moisture level and controlling the water pump based on real-time data. It uses a combination of sensor input, microcontroller logic, and actuator control, all powered by a compact portable power source. The working is based on the principles of electrical conductivity, signal processing, and electromechanical switching.

 

 

A.   Key Functional Components

 

 

1.    Soil Moisture Sensor

o   Working Principle: The sensor measures the volumetric water content of the soil by determining its electrical conductivity. Wet soil conducts electricity better than dry soil due to the presence of water and dissolved salts.

                                           

o   Output: An analog voltage signal (typically 0–1023) sent to the Arduino’s analog pin (A0).

o   Physics Concept: Ohm’s Law and resistivity (R = ρL/A). As moisture increases, resistance decreases, and current flow improves, resulting in a lower analog value (for resistive sensors).

2.    Arduino Uno

o   Role: Acts as the brain of the system. It reads the analog signal from the soil sensor, processes the value using pre-set thresholds, and sends control signals to other components.

                               

o   Internal Mechanism: Converts analog voltage from the sensor to a digital value using a 10-bit ADC (Analog to Digital Converter).

o   Thresholds:

§  950 → Dry soil → Turn pump ON

§  400–950 → Medium moisture → Pump OFF

§  <400 → Wet soil → Pump OFF

3.    LCD Display with I2C Module

o   Displays real-time feedback such as soil status (Dry/Medium/Wet) and Pump status (ON/OFF).

           

o   I2C reduces the number of pins needed (uses only SDA and SCL).

o   Based on liquid crystal polarization controlled by electric current.

4.    5V Relay Module

o   A relay is an electrically operated switch that isolates the Arduino from the higher current required by the water pump.

                                       

o   When the Arduino sends a HIGH signal (5V) to the relay, it activates an internal electromagnetic coil.

o   This coil generates a magnetic field, attracting a switch and closing the circuit between the pump and power supply.

5.    5V Water Pump

o   A small DC pump used for irrigation.

o   Activated via the relay, it pulls water from a reservoir to the plant when the soil is dry.

                                        

o   Based on Bernoulli’s principle and fluid dynamics: pressure created by the rotating impeller pushes water through the outlet.

6.    3.7V Li-ion Battery (Boosted to 5V)

o   Supplies power to the entire circuit via a boost converter.

                                             

o   Physics: Chemical energy stored in lithium ions is converted into electrical energy during discharge.

o   The boost converter steps up voltage using inductive switching

(V = L di/dt).

 

 B. Overall System Process

1.    The soil sensor continuously measures moisture levels and sends analog signals to the Arduino.

2.    Arduino converts and compares the input to thresholds to determine the soil’s state.

3.    The system decides whether to activate the water pump through a relay module.

4.    The LCD displays the moisture level category (Dry/Medium/Wet) and the pump’s state (ON/OFF).

5.    The pump irrigates the soil when dry, powered by the Li-ion battery.

6.    The process repeats at fixed intervals (can be improved with time delays or sleep mode for power efficiency).

 Summary of Physics & Electronics Concepts Used

  • Electrical conductivity & resistance (moisture sensing)
  • Analog to digital conversion (Arduino ADC)
  • Electromagnetism (relay activation)
  • Liquid crystal optics (LCD display)
  • Fluid dynamics (pump operation)
  • Energy conversion (Li-ion battery)

 

 


6.    How the Smart Plant Monitoring System Works:

 

1.  Soil Moisture Detection
 - The soil moisture sensor is placed in the soil near the plant.
 - It detects how much water is present in the soil using electrical conductivity.
 - The drier the soil, the higher the sensor reading (closer to 1023); the wetter the soil, the lower the reading (closer to 300).

2.  Sensor Sends Data to Arduino
 - The sensor sends an analog signal to the Arduino Uno on pin A0.
 - The Arduino reads the sensor value (between 0–1023) and processes it.

3.  Arduino Makes a Decision
 Based on the sensor value:
 - If the value > 950 → Soil is dry → Turn ON pump
 - If 400 ≤ value ≤ 950 → Soil is medium → Keep pump OFF
 - If value < 400 → Soil is wet → Keep pump OFF

4.  Display the Status
 - The 16x2 LCD (with I2C module) shows the soil condition (Dry / Medium / Wet)
 - It also displays the status of the pump (ON / OFF)

5.  Control the Pump Using Relay
 - If the soil is dry, the Arduino sends a signal to the 5V relay module (connected to pin D7).
 - The relay activates and allows current to flow to the 5V water pump.
 - The pump starts and waters the plant.

6.  Power Supply
 - The entire system is powered by a 3.7V Li-ion battery.
 - A boost converter increases this voltage to 5V to power the Arduino, relay, and pump.

7.  Continuous Monitoring
 - The system runs continuously, checking the soil at regular intervals (e.g., every few seconds or minutes).
 - As soon as the soil becomes wet enough, the Arduino turns off the pump.

 

🛠 Optional Enhancements:

·        Add a delay so the pump doesn’t turn on/off too quickly.

·        Add Wi-Fi or Bluetooth for remote monitoring.

·        Log data for analysis (CSV or cloud)


7.    Arduino Code (With Comments)

Below is a compact and functional version of the Arduino code used in the project:

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 16, 2);  // I2C address 0x27, 16 columns, 2 rows

const int soilSensorPin = A0; // Soil moisture sensor input pin
const int relayPin = 7; // Relay control pin

voidsetup()

{
lcd.begin();
lcd.backlight();
pinMode(soilSensorPin, INPUT);
pinMode(relayPin, OUTPUT);
digitalWrite(relayPin, LOW); //Initially turn OFF pump
}

void loop()

{
int moistureValue = analogRead(soilSensorPin);
lcd.setCursor(0, 0);
lcd.print("Moisture: ");
lcd.print(moistureValue);

if (moistureValue > 950) {
lcd.setCursor(0, 1);
lcd.print("Soil: DRY PUMP ON ");
digitalWrite(relayPin, HIGH);
}
else if (moistureValue >= 400 && moistureValue <= 950) {
lcd.setCursor(0, 1);
lcd.print("Soil: MED PUMP OFF");
digitalWrite(relayPin, LOW);
}
else {
lcd.setCursor(0, 1);
lcd.print("Soil: WET PUMP OFF");
digitalWrite(relayPin, LOW);
}

delay(2000); // Delay to allow LCD update
}

Explanation:

  • The soil moisture sensor provides an analog reading from 0 to 1023.
  • The code determines whether soil is Dry (>950), Medium (400–950), or Wet (<400).
  • The LCD displays both moisture reading and pump status.
  • The relay is triggered only when the soil is dry.

8.   Result and Output:

           After uploading the code and assembling the circuit, the system behaves as follows:

A. System Behaviour:

  • When soil is dry (sensor value > 950):
    • LCD shows “Soil: DRY PUMP ON”
    • Relay activates the pump, watering the plant.
  • When soil is medium moist (400–950):
    • LCD shows “Soil: MED PUMP OFF”
    • Pump remains off.
  • When soil is sufficiently wet (< 400):
    • LCD shows “Soil: WET PUMP OFF”
    • Pump stays off to avoid overwatering.

 

B. Observed Output (Examples):

Time

 Moisture Value

 Soil Status

 Pump Status

10:00 AM

    987

  Dry

  ON

11:30 AM

    875

  Medium

  OFF

12:45 PM

    345

  Wet

  OFF

 

 

C. LCD Display Example:

Line 1: Moisture: 987
Line 2: Soil: DRY PUMP ON

 

D. Performance:

  • The system reliably maintains correct pump control.
  • LCD provides clear real-time feedback.
  • Battery lasts well under optimized duty cycles.

 


 

9.   Advantage:

·       Automated Irrigation: The system waters the plant automatically based on real-time soil moisture data, reducing manual effort.

·       Water Conservation: Prevents overwatering by activating the pump only when the soil is dry.

·       Energy Efficient: Uses a low-power Arduino and battery-based supply, making it suitable for remote areas.

·       Real-Time Monitoring: Displays moisture levels and pump status live on the LCD.

·       Low Cost: Built with inexpensive and widely available components.

·       Easy to Build and Expand: Beginner-friendly and modular design allows for upgrades.

·       Promotes Smart Agriculture: Encourages adoption of technology in small-scale farming and home gardening.

·       Portable Setup: The Li-ion battery makes it suitable for use in areas without constant power.

·       Customizable Thresholds: Soil moisture thresholds can be tuned to different plant needs.





10.        Future Scope:


·        IoT Integration: Add Wi-Fi (ESP8266/ESP32) or GSM modules for remote control and mobile app connectivity.

·        Cloud Data Logging: Store moisture data online (e.g., Google Sheets, Firebase) for analysis and alerts.

·        Solar Charging: Use solar panels to recharge the battery and make the system fully self-sustaining.

·        Additional Sensors: Include temperature, humidity, and light sensors for comprehensive environmental monitoring.

·        Smart App Interface: Develop a companion mobile app to control thresholds and view real-time data.

·        AI-Based Irrigation: Implement machine learning to optimize watering schedules based on weather predictions and plant type.

·        Multi-Zone Monitoring: Extend the system to monitor and control irrigation for multiple plants or zones.

 


 

11.        Conclusion

The Smart Plant Monitoring System using Arduino provides a practical solution for automatic plant irrigation based on soil moisture levels. It is a cost-effective, energy-efficient, and easily deployable system for home gardening, small-scale agriculture, and educational purposes. The system successfully monitors soil moisture and activates a water pump when the soil is dry, displaying live data through an LCD interface. Although the current version is basic, it offers vast potential for expansion into a fully automated, connected, and intelligent plant care platform. This project lays a strong foundation for future smart farming innovations.



 

12.   Data Analysis 


#IMPORTING NECESSARY LIBRARIES
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression

df=pd.read_csv("smart_plant_monitoring_data.csv")

#IMPORTING NECESSARY LIBRARIES
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression

df.head() #returns first 5 entries

         Timestamp         Soil_Moisture    Soil_Status    Pump_Status  Battery_Voltage
0  2025-06-23 00:00:00            774        Medium         OFF                3.98
1  2025-06-23 01:00:00            679        Medium         OFF                3.92
2  2025-06-23 02:00:00            797        Medium         OFF                3.91
3  2025-06-23 03:00:00            928        Medium         OFF                3.92
4  2025-06-23 04:00:00            664        Medium         OFF                3.99

df.tail() #returns first 5 entries

               Timestamp     Soil_Moisture    Soil_Status    Pump_Status  Battery_Voltage
163  2025-06-29 19:00:00            576      Medium         OFF  \                 3.91
164  2025-06-29 20:00:00            844      Medium         OFF                    4.01
165  2025-06-29 21:00:00            761      Medium         OFF                    3.93
166  2025-06-29 22:00:00            823      Medium         OFF                    4.10
167  2025-06-29 23:00:00            984         Dry              ON                     3.99

df.shape

(168, 5)

df.isnull().sum()

Timestamp          0
Soil_Moisture      0
Soil_Status        0
Pump_Status        0
Battery_Voltage    0
dtype: int64

df.dtypes

Timestamp           object
Soil_Moisture        int64
Soil_Status         object
Pump_Status         object
Battery_Voltage    float64
dtype: object

df.info()

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 168 entries, 0 to 167
Data columns (total 5 columns):
 #   Column           Non-Null Count  Dtype 
---  ------           --------------  ----- 
 0   Timestamp        168 non-null    object
 1   Soil_Moisture    168 non-null    int64 
 2   Soil_Status      168 non-null    object
 3   Pump_Status      168 non-null    object
 4   Battery_Voltage  168 non-null    float64
dtypes: float64(1), int64(1), object(3)
memory usage: 6.7+ KB

data=df.groupby('Soil_Status')

df.head()

             Timestamp  Soil_Moisture Soil_Status Pump_Status  Battery_Voltage
0  2025-06-23 00:00:00            774      Medium         OFF             3.98
1  2025-06-23 01:00:00            679      Medium         OFF             3.92
2  2025-06-23 02:00:00            797      Medium         OFF             3.91
3  2025-06-23 03:00:00            928      Medium         OFF             3.92
4  2025-06-23 04:00:00            664      Medium         OFF             3.99

df.head()

             Timestamp  Soil_Moisture Soil_Status Pump_Status  Battery_Voltage
0  2025-06-23 00:00:00            774      Medium         OFF             3.98
1  2025-06-23 01:00:00            679      Medium         OFF             3.92
2  2025-06-23 02:00:00            797      Medium         OFF             3.91
3  2025-06-23 03:00:00            928      Medium         OFF             3.92
4  2025-06-23 04:00:00            664      Medium         OFF             3.99

df['Timestamp'] = pd.to_datetime(df['Timestamp'])

print("Dataset Summary:")
print(df.describe())

Dataset Summary:
                 Timestamp  Soil_Moisture  Battery_Voltage
count                  168     168.000000       168.000000
mean   2025-06-26 11:30:00     693.333333         4.007798
min    2025-06-23 00:00:00     307.000000         3.680000
25%    2025-06-24 17:45:00     597.750000         3.930000
50%    2025-06-26 11:30:00     698.500000         4.010000
75%    2025-06-28 05:15:00     778.750000         4.070000
max    2025-06-29 23:00:00    1023.000000         4.390000
std                    NaN     140.841809         0.098385

soil_counts = df['Soil_Status'].value_counts()
print("\nSoil Status Counts:")
print(soil_counts)


Soil Status Counts:
Soil_Status
Medium    161
Dry         6
Wet         1
Name: count, dtype: int64

plt.figure(figsize=(10, 5))
sns.histplot(df['Soil_Moisture'])
plt.title("Soil Moisture Distribution")
plt.xlabel("Soil Moisture")
plt.ylabel("Frequency")
plt.grid(True)
plt.tight_layout()
plt.show()

plt.boxplot(df['Soil_Moisture'])

{'whiskers': [<matplotlib.lines.Line2D at 0x2d5de68ab20>,
  <matplotlib.lines.Line2D at 0x2d5de68aeb0>],
 'caps': [<matplotlib.lines.Line2D at 0x2d5de69b280>,
  <matplotlib.lines.Line2D at 0x2d5de69b610>],
 'boxes': [<matplotlib.lines.Line2D at 0x2d5de68a760>],
 'medians': [<matplotlib.lines.Line2D at 0x2d5de69b9a0>],
 'fliers': [<matplotlib.lines.Line2D at 0x2d5de69bd30>],
 'means': []}

df['Soil_Moisture'].hist()

<AxesSubplot:>

df['Battery_Voltage'].hist()

<AxesSubplot:>

plt.figure(figsize=(10, 6))
plt.scatter(df['Soil_Moisture'], df['Battery_Voltage'], alpha=0.5, color='blue')
plt.title('Battery Voltage vs Soil Moisture')
plt.xlabel('Soil Moisture (Sensor Value)')
plt.ylabel('Battery Voltage (V)')
plt.grid(True)
plt.tight_layout()
plt.show()

sns.pairplot(df, hue='Soil_Moisture')

<seaborn.axisgrid.PairGrid at 0x2d5dc838d60>

sns.pairplot(df, hue='Battery_Voltage')

<seaborn.axisgrid.PairGrid at 0x2d5dc85a3d0>

plt.figure(figsize=(8, 6))
sns.boxplot(x='Pump_Status', y='Battery_Voltage', data=df, palette='Set2')
plt.title('Battery Voltage vs Pump Status')
plt.xlabel('Pump Status')
plt.ylabel('Battery Voltage (V)')
plt.grid(True)
plt.tight_layout()
plt.show()

plt.figure(figsize=(8, 6))
sns.boxplot(x='Soil_Status', y='Soil_Moisture', data=df, palette='Set3')
plt.title('Soil Moisture vs Soil Status')
plt.xlabel('Soil Status')
plt.ylabel('Soil Moisture (Sensor Value)')
plt.grid(True)
plt.tight_layout()
plt.show()

sns.violinplot(x='Soil_Status', y='Soil_Moisture', data=df, palette='Set2')

<AxesSubplot:xlabel='Soil_Status', ylabel='Soil_Moisture'>

plt.figure(figsize=(10, 6))
sns.stripplot(x='Soil_Status', y='Soil_Moisture', hue='Pump_Status', data=df, jitter=True, palette='coolwarm')
plt.title('Soil Moisture vs Soil Status and Pump Status')
plt.legend(title='Pump Status')
plt.grid(True)
plt.show()

sns.violinplot(x='Soil_Status', y='Soil_Moisture', hue='Pump_Status', data=df, split=True, palette='muted')
plt.title('Soil Moisture Distribution by Soil Status and Pump Status')
plt.grid(True)
plt.show()

import pandas as pd
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from sklearn.preprocessing import LabelEncoder

le_soil = LabelEncoder()
le_pump = LabelEncoder()
df['Soil_Status_Code'] = le_soil.fit_transform(df['Soil_Status'])
df['Pump_Status_Code'] = le_pump.fit_transform(df['Pump_Status'])

fig = plt.figure(figsize=(10, 7))
ax = fig.add_subplot(111, projection='3d')

ax.scatter(df['Soil_Moisture'],
df['Soil_Status_Code'],
df['Pump_Status_Code'],
c=df['Pump_Status_Code'], cmap='coolwarm', alpha=0.6)

ax.set_xlabel('Soil Moisture')
ax.set_ylabel('Soil Status')
ax.set_zlabel('Pump Status')
ax.set_title('3D Plot: Soil Moisture vs Soil Status vs Pump Status')

Text(0.5, 0.92, '3D Plot: Soil Moisture vs Soil Status vs Pump Status')

ax.set_yticks([0, 1, 2])
ax.set_yticklabels(le_soil.inverse_transform([0, 1, 2]))
ax.set_zticks([0, 1])
ax.set_zticklabels(le_pump.inverse_transform([0, 1]))

plt.tight_layout()
plt.show()

<Figure size 640x480 with 0 Axes>

pd.crosstab(df['Soil_Status'], df['Pump_Status'])

Pump_Status    0  1
Soil_Status       
Dry            0  6
Medium       161  0
Wet            1  0

 

 

 

 

 

 

 

 

Post a Comment

0 Comments