OC
OceanRemote
Low-code IoT platform
← Back to Course

Complete Soil Monitoring Station

Complete Soil Monitoring Station

🛠️ Complete Soil Monitoring Station - Smart Soil Health System

🌱 What You'll Learn in This Lesson:

  • 🌡️ Monitor soil moisture, temperature, NPK nutrients, and pH
  • 📊 Build a complete soil health monitoring station
  • 💰 Understand ROI - pays for itself in 1-2 seasons
  • 🔋 Make your station solar-powered for remote operation
  • 📡 Send soil data to OceanRemote cloud dashboard

🛒 Complete Bill of Materials

||DSML||
Component Model/Type Purpose Cost
Soil Moisture Capacitive (v2.0) Measures water content 0-100% $8-12
Soil Temperature DS18B20 Waterproof -55°C to +125°C at root depth $5-8
NPK Sensor JXCT RS485 Nitrogen, Phosphorus, Potassium levels $50-70
pH Meter Analog pH Sensor (SEN0161) Soil acidity/alkalinity (3-9 pH) $12-18
Microcontroller ESP32 (30-pin) Data processing + WiFi $6-10
Solar Power 6V 2W Solar + TP4056 + 18650 Off-grid power for remote fields $12-18
Enclosure IP65 Weatherproof Box Protects electronics from rain/dust $8-12
Total Investment - Complete soil monitoring station $100-140
🌟 Return on Investment (ROI) Calculation:
  • 💧 Water savings: 30-40% reduction → saves $30-50 per season
  • 🌱 Fertilizer savings: Apply only when needed → saves $40-60 per season
  • 📈 Yield increase: 20-30% higher production → $100-200 additional revenue
  • 💰 Total annual savings: $170-310 per hectare
  • Payback period: 1-2 growing seasons!

🔌 Complete Wiring Diagram

═══════════════════════════════════════════════════════════════════════════════
                    COMPLETE SOIL MONITORING STATION WIRING
═══════════════════════════════════════════════════════════════════════════════

    ESP32 PIN MAPPING:
    ┌─────────────────────────────────────────────────────────────────────────┐
    │                                                                         │
    │  Soil Moisture Sensor (Capacitive)                                     │
    │  VCC  → 3.3V                                                           │
    │  GND  → GND                                                            │
    │  OUT  → GPIO32 (Analog)                                                │
    │                                                                         │
    │  DS18B20 (Soil Temperature)                                            │
    │  Red     → 3.3V                                                        │
    │  Black   → GND                                                         │
    │  Yellow  → GPIO4 (OneWire) + 4.7kΩ pull-up to 3.3V                    │
    │                                                                         │
    │  NPK Sensor (RS485) - requires MAX485 module                           │
    │  MAX485          ────────── ESP32                                      │
    │  VCC             → 5V                                                  │
    │  GND             → GND                                                 │
    │  RO (Receiver Out) → GPIO16 (RX2)                                      │
    │  DI (Driver In)   → GPIO17 (TX2)                                       │
    │  RE/DE            → GPIO18 (Control)                                   │
    │                                                                         │
    │  pH Sensor (Analog)                                                    │
    │  VCC  → 3.3V                                                           │
    │  GND  → GND                                                            │
    │  OUT  → GPIO33 (Analog)                                                │
    │                                                                         │
    └─────────────────────────────────────────────────────────────────────────┘

    SOLAR POWER CONNECTION:
    ┌─────────────────────────────────────────────────────────────────────────┐
    │  6V Solar Panel ──► TP4056 Charger (IN+ / IN-)                        │
    │  18650 Battery   ──► TP4056 (BAT+ / BAT-)                             │
    │  TP4056 (OUT+)    ──► MT3608 Boost Converter (IN+)                     │
    │  TP4056 (OUT-)    ──► MT3608 (IN-) + ESP32 GND                        │
    │  MT3608 (OUT+)    ──► ESP32 VIN (5V)                                   │
    │                                                                         │
    │  This provides stable 5V for ESP32 and sensors for 3-5 days without sun│
    └─────────────────────────────────────────────────────────────────────────┘

═══════════════════════════════════════════════════════════════════════════════

💻 Complete Soil Monitoring Code

/*
 * Complete Soil Monitoring Station
 * Measures: Moisture, Temperature, NPK, pH
 * 
 * Components:
 * - Capacitive soil moisture sensor
 * - DS18B20 soil temperature sensor
 * - JXCT NPK sensor (RS485)
 * - Analog pH sensor
 * - ESP32 with WiFi
 */

#include 
#include 
#include 
#include 
#include 

// ========== WIFI CONFIGURATION ==========
const char* ssid = "YOUR_WIFI";
const char* password = "YOUR_PASSWORD";
const char* oceanRemoteToken = "YOUR_TOKEN";

// ========== PIN DEFINITIONS ==========
#define SOIL_MOISTURE_PIN 32
#define PH_PIN 33
#define ONE_WIRE_BUS 4
#define RS485_RX 16
#define RS485_TX 17
#define RS485_RE_DE 18

// ========== SENSOR CALIBRATION ==========
const int SOIL_DRY = 3800;
const int SOIL_WET = 1500;

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature soilTemp(&oneWire);

ModbusMaster npkSensor;

// ========== READ SOIL MOISTURE ==========
int readSoilMoisture() {
    int raw = analogRead(SOIL_MOISTURE_PIN);
    int percentage = map(raw, SOIL_DRY, SOIL_WET, 0, 100);
    percentage = constrain(percentage, 0, 100);
    return percentage;
}

// ========== READ SOIL TEMPERATURE ==========
float readSoilTemperature() {
    soilTemp.requestTemperatures();
    float temp = soilTemp.getTempCByIndex(0);
    if (temp == -127.0) return 0;
    return temp;
}

// ========== READ NPK VALUES (RS485) ==========
void readNPK(float &nitrogen, float &phosphorus, float &potassium) {
    uint8_t result;
    uint16_t data[6];
    
    // Read NPK sensor using Modbus protocol
    result = npkSensor.readHoldingRegisters(0x001E, 3);
    if (result == npkSensor.ku8MBSuccess) {
        data[0] = npkSensor.getResponseBuffer(0);
        data[1] = npkSensor.getResponseBuffer(1);
        data[2] = npkSensor.getResponseBuffer(2);
        
        nitrogen = data[0] / 10.0;
        phosphorus = data[1] / 10.0;
        potassium = data[2] / 10.0;
    } else {
        nitrogen = 0;
        phosphorus = 0;
        potassium = 0;
    }
}

// ========== READ PH VALUE ==========
float readPH() {
    int raw = analogRead(PH_PIN);
    float voltage = raw * (3.3 / 4095.0);
    
    // pH = 7 + (2.5 - voltage) * (7 / 1.5)
    float ph = 7.0 + (2.5 - voltage) * 4.67;
    ph = constrain(ph, 3.0, 9.0);
    return ph;
}

// ========== GET SOIL RECOMMENDATIONS ==========
String getSoilRecommendations(int moisture, float temp, 
                               float nitrogen, float phosphorus, 
                               float potassium, float ph) {
    String rec = "";
    
    if (moisture < 35) rec += "⚠️ Soil dry - Irrigate soon. ";
    else if (moisture > 75) rec += "⚠️ Soil wet - Reduce watering. ";
    else rec += "✅ Moisture optimal. ";
    
    if (temp < 15) rec += "❄️ Soil cool - Delay planting. ";
    else if (temp > 35) rec += "🔥 Soil hot - Increase mulch/water. ";
    else rec += "✅ Temperature optimal. ";
    
    if (nitrogen < 30) rec += "🌿 Low nitrogen - Add manure/fertilizer. ";
    else if (nitrogen > 100) rec += "⚠️ Excess nitrogen - Reduce fertilizer. ";
    
    if (phosphorus < 15) rec += "🌱 Low phosphorus - Add bone meal. ";
    if (potassium < 150) rec += "🍌 Low potassium - Add wood ash/potash. ";
    
    if (ph < 5.5) rec += "🧪 Soil acidic - Add lime. ";
    else if (ph > 7.5) rec += "🧪 Soil alkaline - Add sulfur/organic matter. ";
    else rec += "✅ pH optimal (6.0-7.0). ";
    
    return rec;
}

// ========== SEND TO OCEANREMOTE ==========
void sendToCloud(int moisture, float temp, 
                  float nitrogen, float phosphorus, 
                  float potassium, float ph) {
    if (WiFi.status() != WL_CONNECTED) return;
    
    HTTPClient http;
    http.begin("https://api.oceanremote.net/device/state");
    http.addHeader("Content-Type", "application/x-www-form-urlencoded");
    
    String data = "token=" + String(oceanRemoteToken);
    data += "&soil_moisture=" + String(moisture);
    data += "&soil_temperature=" + String(temp);
    data += "&nitrogen=" + String(nitrogen);
    data += "&phosphorus=" + String(phosphorus);
    data += "&potassium=" + String(potassium);
    data += "&ph=" + String(ph);
    data += "&recommendation=" + getSoilRecommendations(moisture, temp, nitrogen, phosphorus, potassium, ph);
    
    http.POST(data);
    http.end();
}

// ========== DISPLAY REPORT ==========
void displayReport(int moisture, float temp,
                    float nitrogen, float phosphorus,
                    float potassium, float ph) {
    Serial.println("\n╔══════════════════════════════════════════════════════════════╗");
    Serial.println("║              🌱 SOIL HEALTH MONITORING REPORT                 ║");
    Serial.println("╚══════════════════════════════════════════════════════════════╝");
    
    Serial.println("\n💧 SOIL MOISTURE:");
    Serial.printf("   %d%% - ", moisture);
    if (moisture < 35) Serial.println("Needs irrigation");
    else if (moisture > 75) Serial.println("Reduce watering");
    else Serial.println("✅ Optimal");
    
    Serial.println("\n🌡️ SOIL TEMPERATURE:");
    Serial.printf("   %.1f°C - ", temp);
    if (temp < 15) Serial.println("Too cool");
    else if (temp > 35) Serial.println("Too hot");
    else Serial.println("✅ Optimal for most crops");
    
    Serial.println("\n🌿 SOIL NUTRIENTS:");
    Serial.printf("   Nitrogen (N): %.1f mg/kg - ", nitrogen);
    Serial.println(nitrogen < 30 ? "Low" : (nitrogen > 100 ? "High" : "Optimal"));
    Serial.printf("   Phosphorus (P): %.1f mg/kg - ", phosphorus);
    Serial.println(phosphorus < 15 ? "Low" : (phosphorus > 50 ? "High" : "Optimal"));
    Serial.printf("   Potassium (K): %.1f mg/kg - ", potassium);
    Serial.println(potassium < 150 ? "Low" : (potassium > 300 ? "High" : "Optimal"));
    
    Serial.println("\n⚗️ SOIL pH:");
    Serial.printf("   %.1f - ", ph);
    if (ph < 5.5) Serial.println("Acidic (Add lime)");
    else if (ph > 7.5) Serial.println("Alkaline (Add sulfur)");
    else Serial.println("✅ Optimal (6.0-7.0)");
    
    Serial.println("\n🎯 RECOMMENDATIONS:");
    Serial.println("   " + getSoilRecommendations(moisture, temp, nitrogen, phosphorus, potassium, ph));
    
    Serial.println("\n══════════════════════════════════════════════════════════════\n");
}

void setup() {
    Serial.begin(115200);
    
    // Initialize sensors
    soilTemp.begin();
    pinMode(SOIL_MOISTURE_PIN, INPUT);
    pinMode(PH_PIN, INPUT);
    
    // Initialize RS485 for NPK sensor
    Serial2.begin(9600, SERIAL_8N1, RS485_RX, RS485_TX);
    pinMode(RS485_RE_DE, OUTPUT);
    digitalWrite(RS485_RE_DE, LOW);
    npkSensor.begin(1, Serial2);
    
    // Connect to WiFi
    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED) delay(500);
    Serial.println("✅ WiFi connected!");
    
    Serial.println("═══════════════════════════════════════════");
    Serial.println("🌱 COMPLETE SOIL MONITORING STATION v2.0");
    Serial.println("   Soil Health Monitoring System");
    Serial.println("═══════════════════════════════════════════\n");
}

void loop() {
    int moisture = readSoilMois
        
        
        
        
        
        
        
        
        
        
        
        
💡 Key Takeaways:
  • Apply these concepts directly to your farm or project.
  • Take notes on important details for the quiz.
  • Use the button below to track your progress.