Arduino Soil Erosion Detection Project

Introduction

Soil erosion might seem like a slow and harmless process, but it’s one of the silent destroyers of our environment. When rain or wind carries away the topsoil, the nutrients that plants depend on disappear with it. That’s where technology and creativity meet — to build something smart and preventive.

Arduino Soil Erosion Detection Project

This Arduino Soil Erosion Detection Project is a simple yet powerful system that uses laser–LDR pairs to monitor soil displacement in real-time. It detects different erosion levels and can even send the readings to an IoT platform like Blynk for remote monitoring.

In this guide, you’ll learn everything about how the project works, how to build it, and how it can be extended for smart farming or environmental monitoring.

What is Soil Erosion and Why Should We Care?

Soil erosion is the gradual removal of the top layer of soil due to wind, water, or human activity. It reduces soil fertility, clogs water channels, and leads to environmental degradation.

what is soil erosion

In agriculture, soil erosion directly impacts crop yield and sustainability. If left unchecked, it can turn fertile land into barren ground.

That’s why detecting soil erosion early is so important — and using simple electronics like Arduino, lasers, and LDRs, we can simulate this detection in an educational and practical way.

Project Overview: Arduino Soil Erosion Detection

soil erosion effects on agriculture

This project models a transparent soil container that represents a mini farmland. Three laser beams are positioned at different vertical levels to represent soil height. Opposite each laser beam is a Light Dependent Resistor (LDR) sensor.

You may also like to read: Best Solar-Powered Gadgets for Home and Outdoor Use

the lazers to detect erosion

As erosion occurs (or when soil is removed), the laser beam becomes visible to the LDR. Each detection level corresponds to a specific erosion percentage.

The system then displays or sends these readings, which can later be connected to IoT platforms like Blynk for real-time monitoring on a smartphone.

How It Works — The Basic Concept

Let’s break it down step by step:

  1. Setup: Three lasers are aligned at different heights along one side of a transparent soil container.
  2. Sensing: Three LDRs are positioned directly opposite the lasers to receive light.
  3. Soil Simulation: As soil erodes or is removed, light from each laser begins to reach its corresponding LDR.
  4. Detection Logic:
    • Top LDR = minor erosion (≈ 28%)
    • Middle LDR = moderate erosion (≈ 57%)
    • Bottom LDR = severe erosion (≈ 90%)
  5. Output: The Arduino reads voltage changes from each LDR circuit and displays erosion levels via serial monitor or LED indicators.
  6. Optional IoT: Data can be sent to Blynk or other IoT dashboards for remote tracking.

It’s a clean, low-cost approach to visualize how erosion affects soil levels in real time.

You May also like to read: Easy-to-Use Smartwatches for Seniors health

Components Required

1. Arduino Nano (optionally, you can use an Uno board)

arduino nano board

Acts as the main controller. It reads signals from the LDR sensors and processes them according to your programmed logic.

Laser Light Modules (x3)

brass line laser dot diode

Provide precise, visible light beams that help detect soil level changes.

Light Dependent Resistors (LDRs) (x3)

light dependent resistors (LDRs)

Serve as the eyes of the system. When light from the laser hits an LDR, its resistance decreases — indicating that level of soil erosion.

Fixed Resistors (10kΩ each)

10k fixed resistor 5 bands

Used with the LDRs to form voltage divider circuits. This helps convert light intensity into readable voltage signals for the Arduino.

Breadboard or Veroboard

breadboard from Adafruit

For prototyping or permanent soldering of the circuit connections.

Connecting Wires and JST Connectors

Used to connect the laser and LDR modules neatly.

Transparent Plastic or Acrylic Box

Simulates the soil container. It allows light beams to pass through and visually demonstrates erosion levels.

5V Power Supply

Powers both the Arduino and the laser modules.

Hardware Design and Connection

The Schematic Diagram

circuit diagram soil erosion

Each LDR is connected in series with a 10kΩ resistor to form a voltage divider. The junction of each divider goes to an analog input pin of the Arduino. Each laser module is powered through a 5V pin.
The Arduino continuously reads voltage from the LDR dividers. See the circuit diagram above and below.

When an LDR detects a laser beam, its resistance drops, changing the voltage value. The program then interprets this as an erosion event.

schematic diagram of the soil erosion detection using Arduino Uno

The system design basically can also work with HIGH and LOW on the Arduino logic programming. For the LDRs, they were positioned in a way that the LDRs won’t see the illumination of the day’s brightness as a result of the sun rays where they are positioned.

In the project that this technique was used, the LDRs were embedded into a hole on a wooden surface and since Laser rays travel in a straight line. It was easier for the sun rays not to have a significant drop on the LDR’s resistance as a result of the natural illuminance. But when the Laser’s red light cuts through as a result of the soil level washing out due to erosion, this laser ray shoots directly on the LDR’s surface. Showing clearly the level of soil erosion.

Arduino Code for Soil Erosion Detection

You can use Arduino IDE to program the logic for detecting erosion levels and printing messages to the serial monitor or lighting up LEDs.

//define user safe zone
int minSafeZone = 30;
int maxSafeZone = 80;
//create a variable to keep track of state
int laserStatus;

void setup() {
  // Start the Serial Monitor and temp sensor
  Serial.begin(115200);
//declare where the inputs are connected
  pinMode(ldrOne, INPUT);
  pinMode(ldrTwo, INPUT);
  pinMode(ldrThree, INPUT);
 
}

int erosionSensor(){
  //read the input ldr
  int readLDROne = digitalRead(ldrOne);
  int readLDRTwo = digitalRead(ldrTwo);
  int readLDRThree = digitalRead(ldrThree);
    //use conditional statement    
    if ((readLDROne == 0) && (readLDRTwo == 0) && (readLDRThree == 0)) {
      laserStatus = 0;     //return one
      Serial.println("No Soil exposes. NO EROSION");  
      }  
        //check if only 1 laser can pass through
    if ((readLDROne == 1) && (readLDRTwo == 0) && (readLDRThree == 0)) {
      laserStatus = 1;     //return one
      Serial.println("Minimum Soil exposes. Min EROSION");
      }
     //check if only 2 lasers can pass through
    if ((readLDROne == 1) && (readLDRTwo == 1) && (readLDRThree == 0)) {
      laserStatus = 2;     //return two
      Serial.println("Moderate Soil exposes. MODERATE EROSION");
      }
    //check if all lasers can pass through
    if ((readLDROne == 1) && (readLDRTwo == 1) && (readLDRThree == 1)) {
      laserStatus = 3;
      Serial.println("All Soil exposes. MAX EROSION");
            }
      Serial.println(String("LDR 1: ") + readLDROne + String(" LDR 2: ")+ readLDRTwo + String(" LDR 3: ") + readLDRThree + String(" laser status: ") + laserStatus);
       //Serial.println(laserStatus);
       return laserStatus;     //return the variable used to keep track     
 }

void loop() {
erosionSensor();
}

Explanation of Arduino Code

image of the Arduino code snippet

In the custom function erosionSensor() created to read and measure the soil erosion level. The provided Arduino code establishes a system to monitor soil erosion using light-dependent resistors (LDRs) as sensors. It defines a safe zone for soil exposure with specific minimum (30) and maximum (80) threshold values, although these limits are not utilized in the checking logic. The core function, erosionSensor(), reads values from three LDRs connected to specific pins. Based on the input states—whether an LDR detects light or not—the code assesses the degree of soil exposure and categorizes it into four erosion levels: no erosion, minimal erosion, moderate erosion, and maximum erosion. Depending on the readings from the sensors, it updates the laserStatus variable and prints messages to the serial monitor detailing the current state of erosion and the readings from each sensor.

In the setup() function, the code initializes the serial communication and sets the pins for each LDR as inputs. The main loop repeatedly calls erosionSensor(), allowing the system to continuously monitor and report on the erosion level. This approach provides a real-time feedback mechanism, which can be crucial for applications such as agricultural monitoring or environmental assessments. The use of conditional statements allows the program to differentiate between various soil exposure scenarios effectively. Overall, the code lays a foundational framework for a soil erosion monitoring system using basic components and logic.

Visualizing Soil Erosion Levels

You can display the results in multiple ways:

  • Serial Monitor: Shows the exact erosion level in percentage. This is already included in the code above.
  • LED Indicators: Three LEDs can be connected to indicate low, medium, or high erosion. This is an optional method
  • LCD Display (Optional): To show a real-time text display of erosion percentage.

This helps make the project more interactive and understandable, especially for educational demonstrations.

Calibration of the LDR-Laser System

Each laser–LDR pair must be carefully aligned. Even a small misalignment can cause inaccurate readings.

Here are a few calibration tips:

  • Mount lasers firmly at equal distances.
  • Use black tape or tubing around LDRs to reduce ambient light interference. We used a wooden framework for our as shown in the image above.
  • Record baseline readings (no light, partial light, full light) to determine thresholds.
  • Adjust the resistor values if your LDRs are too sensitive or not sensitive enough.

Proper calibration ensures accuracy and stability of the readings.

Optional IoT Integration (Blynk or Thingspeak)

If you want to make this project IoT-enabled, you can connect an ESP8266 or ESP32 board and send data to a cloud dashboard such as Blynk or Thingspeak. This is shown in the YouTube video below.

The Arduino can either:

  • Send serial data to the ESP8266 (acting as a WiFi module).
  • Or you can replace the Arduino with NodeMCU for a fully integrated setup.

Once connected, you can visualize the erosion levels, trigger alerts, and even log long-term data for analysis. Here is the Arduino code for such a design.

#define BLYNK_TEMPLATE_ID "TMPL254hf7xAQ"
#define BLYNK_TEMPLATE_NAME "IoT Soil Moisture Monitoring"
#define BLYNK_AUTH_TOKEN "LR52s6CJD8hLxLOlhOcWZERp7bJEW7AJ"
//include the dht11 lib
#include "DHT.h"

/* Comment this out to disable prints and save space */
#define BLYNK_PRINT Serial

#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
// Digital pin connected to the DHT sensor
#define DHTPIN D3  
// Uncomment whatever type you're using!
#define DHTTYPE DHT11   // DHT 11
//#define DHTTYPE DHT22   // DHT 22  (AM2302), AM2321
//#define DHTTYPE DHT21   // DHT 21 (AM2301)
DHT dht(DHTPIN, DHTTYPE);

// Your WiFi credentials.
// Set password to "" for open networks.
char ssid[] = "Galaxy A51 917E";
char pass[] = "tosin@345";

BlynkTimer timer;     

#include <OneWire.h>
#include <DallasTemperature.h>

// GPIO where the DS18B20 is connected to
const int pumpPin = D4;
const int oneWireBus = D5;  
const int ldrOne = D6; 
const int ldrTwo = D7; 
const int ldrThree = D8;   

//define user safe zone
int minSafeZone = 30;
int maxSafeZone = 80;
//create a variable to keep track of state
int laserStatus;

// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(oneWireBus);

// Pass our oneWire reference to Dallas Temperature sensor 
DallasTemperature sensors(&oneWire);

float tempCelsius(){
//calculate for temperature
  sensors.requestTemperatures(); 
  float temperatureC = sensors.getTempCByIndex(0);
  float temperatureF = sensors.getTempFByIndex(0);
  Serial.print("Temp in Degree Celsius: ");
  Serial.print(temperatureC);
  Serial.print("ºC ");
   Serial.print(" Temp in Degree Fahreneit: ");
  Serial.print(temperatureF);
  Serial.println("ºF");
  return temperatureC;
}

int soilMoisture(){
  int soilWater = analogRead (A0);
  soilWater = map(soilWater, 1024, 400, 0, 1000);
  soilWater = constrain(soilWater, 0, 1000);
  //use conditional statements to automatically control soil irrigation
    if(soilWater <= 100){
      digitalWrite(pumpPin, HIGH);
      Serial.println("Pump Irrigating model now!!!");
    }
    else if(soilWater >= 890){
      digitalWrite(pumpPin, LOW);
      Serial.println("Pump Irrigation Turned off!!!");
    }

    else{
      Serial.println("User can control pump now!!!");
    }
  //print out the soil moisture level
  Serial.print("Soil Moisture: ");
  Serial.print(soilWater);
  Serial.println("L/m3");
  return soilWater;
}

int erosionSensor(){
  //read the input ldr
  int readLDROne = digitalRead(ldrOne);
  int readLDRTwo = digitalRead(ldrTwo);
  int readLDRThree = digitalRead(ldrThree);
    //use conditional statement    
    if ((readLDROne == 0) && (readLDRTwo == 0) && (readLDRThree == 0)) {
      laserStatus = 0;     //return one
      Serial.println("No Soil exposes. NO EROSION");  
      }  
        //check if only 1 laser can pass through
    if ((readLDROne == 1) && (readLDRTwo == 0) && (readLDRThree == 0)) {
      laserStatus = 1;     //return one
      Serial.println("Minimum Soil exposes. Min EROSION");
      }
     //check if only 2 lasers can pass through
    if ((readLDROne == 1) && (readLDRTwo == 1) && (readLDRThree == 0)) {
      laserStatus = 2;     //return two
      Serial.println("Moderate Soil exposes. MODERATE EROSION");
      }
    //check if all lasers can pass through
    if ((readLDROne == 1) && (readLDRTwo == 1) && (readLDRThree == 1)) {
      laserStatus = 3;
      Serial.println("All Soil exposes. MAX EROSION");
            }
      Serial.println(String("LDR 1: ") + readLDROne + String(" LDR 2: ")+ readLDRTwo + String(" LDR 3: ") + readLDRThree + String(" laser status: ") + laserStatus);
       //Serial.println(laserStatus);
       return laserStatus;     //return the variable used to keep track     
 }

float humiditySensor(){
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  float h = dht.readHumidity();
  // Read temperature as Celsius (the default)
  float t = dht.readTemperature();
  // Read temperature as Fahrenheit (isFahrenheit = true)
  float f = dht.readTemperature(true);

  // Check if any reads failed and exit early (to try again).
  if (isnan(h) || isnan(t) || isnan(f)) {
    Serial.println(F("Failed to read from DHT sensor!"));
    return 0.00;
  }

  // Compute heat index in Fahrenheit (the default)
  float hif = dht.computeHeatIndex(f, h);
  // Compute heat index in Celsius (isFahreheit = false)
  float hic = dht.computeHeatIndex(t, h, false);

  Serial.print(F("Humidity: "));
  Serial.print(h);
  Serial.print(F("%  "));
   Serial.print(F(" Heat index: "));
  Serial.print(hic);
  Serial.print(F("°C "));
  Serial.print(hif);
  Serial.println(F("°F"));
  
  return h;
}

//use this fxn to turn on or off the DC pump from the IoT dashboard
BLYNK_WRITE(V3) {
  soilMoisture();
int buttonWidget = param.asInt();
 Serial.print("Dashboard button: ");
  Serial.println(buttonWidget);
  //use conditional statement
  if((soilMoisture() >= 101 ) && (soilMoisture() <= 850)){
       if(buttonWidget == 1 ){
          digitalWrite(pumpPin, HIGH);
          Serial.println("DC pumps ON");
            }

      else{
        digitalWrite(pumpPin, LOW);
        Serial.println("DC pumps OFF");
        }
  }
 }


void myTimerEvent(){
     // You can send any value at any time.
  // Please don't send more that 10 values per second.
  Blynk.virtualWrite(V0, tempCelsius());
  Blynk.virtualWrite(V1, soilMoisture());
  Blynk.virtualWrite(V2, erosionSensor());
  Blynk.virtualWrite(V4, humiditySensor());
   //laserStatus = 0;
  }

void setup() {
  // Start the Serial Monitor and temp sensor
  Serial.begin(115200);
  sensors.begin();    //begin the ds18b20 temp sensor
  dht.begin();    //begin the dht11 sensor
//declare where the inputs are connected
  pinMode(ldrOne, INPUT);
  pinMode(ldrTwo, INPUT);
  pinMode(ldrThree, INPUT);
  pinMode(pumpPin, OUTPUT);
 
   Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass);
  // Setup a function to be called every second
  timer.setInterval(2000L, myTimerEvent);
}

void loop() {
  Blynk.run();
  timer.run(); // Initiates BlynkTimer
}

Real-World Application and Benefits

🌱 Agricultural Monitoring

Farmers can use such systems to detect early soil degradation and take timely preventive measures, like planting cover crops or adjusting irrigation.

🧪 Environmental Research

Researchers can monitor erosion in controlled experiments, studying how rainfall, slope, or vegetation affect soil stability.

🧭 Educational Demonstrations

It’s a great classroom project to explain soil erosion, physics of light, and sensor interfacing concepts.

🛰️ IoT and Automation

When paired with IoT, this system can provide valuable real-time data for precision agriculture or smart environmental management.

Advantages of Arduino-Based Soil Erosion Detection

  • ✅ Low-cost and easy to build
  • ✅ Accurate detection of soil level changes
  • ✅ Expandable for IoT integration
  • ✅ Great for school and college projects
  • ✅ Minimal power consumption

Limitations of the Current Model

  • Works best for transparent enclosures; not suitable for real outdoor soil unless adapted.
  • Ambient sunlight may affect LDR sensitivity if not shielded.
  • Requires careful alignment between laser and LDR sensors.
  • Detects relative erosion (levels), not exact soil volume loss.

Improvements for Future Versions

  1. Replace LDRs with photodiodes or IR sensors for better accuracy.
  2. Add soil moisture and rainfall sensors to correlate erosion with weather conditions.
  3. Use AI or data logging to predict future erosion trends.
  4. Solar power integration for field deployment.

Troubleshooting Common Issues

ProblemPossible CauseSolution
LDR not detecting lightMisaligned laserAdjust position or secure with glue
False readingsAmbient light interferenceUse black casing around LDR
No serial dataWrong analog pin or code issueCheck wiring and re-upload code
Fluctuating readingsUnstable power supplyUse a regulated 5V source

Cost Estimate (Approximate)

ComponentQuantityEstimated Price
Arduino Nano1₦3,000
Laser modules3₦1,200
LDR sensors3₦600
10kΩ resistors3₦150
Jumper wires₦500
Breadboard/veroboard1₦1,000
Transparent container1₦1,200
Total₦7,500 – ₦8,000

Conclusion

This Arduino Soil Erosion Detection Project beautifully combines electronics, environmental science, and creativity. By simulating soil erosion using laser and LDR sensors, it teaches important concepts in sensor interfacing, automation, and sustainability.

And with just a few modifications — like adding WiFi connectivity — this system can evolve into a full-fledged IoT soil monitoring solution.

Whether you’re a student, a maker, or an environmental researcher, this project proves how simple tools can make a big impact on understanding and preserving our planet.

FAQs

1. What is the purpose of this project?
To detect different soil erosion levels using Arduino, lasers, and LDR sensors as part of a soil monitoring system.

2. Can it work outdoors?
Not directly. It’s a model project but can be adapted for outdoor use with stronger sensors and weatherproof casing.

3. How accurate is it?
It can detect relative soil level changes accurately if properly aligned and calibrated.

4. Can I connect this project to the Internet?
Yes! You can use ESP8266 or NodeMCU to send data to IoT platforms like Blynk or Thingspeak.

5. What’s the best way to reduce light interference?
Use dark tubes or covers around the LDRs so only the laser light reaches them.

Leave a Comment

Follow by Email
Pinterest
Pinterest
fb-share-icon
Instagram
Telegram
WhatsApp