Understanding Soil Moisture Thresholds
π Understanding Soil Moisture Thresholds - The Science of Smart Irrigation
π± What You'll Learn in This Lesson:
- π Understand Field Capacity (FC) and Permanent Wilting Point (PWP)
- π§ Calculate Available Water Capacity (AWC) for your soil type
- π― Determine the perfect time to start and stop irrigation
- πΎ Apply crop-specific thresholds for 15+ African crops
- π» Program your ESP32 with optimal soil moisture ranges
π The Three Critical Soil Moisture Thresholds
Field Capacity (FC)
Typical range: 60-80% on capacitive sensors
The maximum amount of water soil can hold against gravity. After heavy rain or irrigation, excess water drains away, leaving soil at Field Capacity. Plants can easily extract water at this level.
Permanent Wilting Point (PWP)
Typical range: 20-30% on capacitive sensors
The moisture level where plants can no longer extract water from soil. Below this point, plants will wilt permanently and die - even if you water them later, the damage is irreversible.
Management Allowed Depletion (MAD)
Ideal trigger: 40-50% depletion
The optimal point to START irrigation. This is when plants have used 40-50% of available water - before they experience stress, but early enough to prevent wilting.
π Understanding Available Water Capacity (AWC)
π Formula:
Available Water = Field Capacity (FC) - Permanent Wilting Point (PWP)
Example: If FC = 70% and PWP = 25%, then Available Water = 45%
When available water drops to 50% (MAD), you should irrigate: 50% of 45% = 22.5% depletion β irrigate at 70% - 22.5% = 47.5% soil moisture
πΎ Soil Type Effects on Field Capacity
| Soil Type | Field Capacity (FC) | Wilting Point (PWP) | Available Water | MAD Trigger |
|---|---|---|---|---|
| ποΈ Sandy Soil | 35-45% | 10-15% | 25-30% | Water at 25-28% (needs frequent irrigation) |
| πΎ Loamy Soil (Best!) | 60-75% | 20-25% | 40-50% | Water at 35-40% (ideal) |
| π§΄ Clay Soil | 75-85% | 30-35% | 40-50% | Water at 50-55% (holds water longer) |
| πͺ¨ Sandy Loam | 45-60% | 15-20% | 30-40% | Water at 30-35% |
Take a handful of moist soil and squeeze it:
- Sandy: Falls apart immediately, feels gritty
- Loamy: Forms a ball that breaks apart easily - BEST for farming!
- Clay: Forms a tight ball that stays together, feels smooth
π Crop-Specific Thresholds for African Farmers
| Crop | Start Watering (%) | Stop Watering (%) | MAD (%) | Critical Below (%) | Sensitivity |
|---|---|---|---|---|---|
| π½ Maize/Corn | 45-50% | 70-75% | 55% | 25% | Medium |
| π Tomatoes | 50-55% | 75-80% | 50% | 30% | High |
| πΆοΈ Peppers | 50-55% | 75-80% | 50% | 30% | High |
| π₯¬ Cabbage | 55-60% | 80-85% | 45% | 35% | Very High |
| πΎ Wheat | 40-45% | 65-70% | 60% | 20% | Low |
| π₯ Potatoes | 45-50% | 70-75% | 55% | 25% | Medium |
| π§ Onions | 35-40% | 60-65% | 65% | 20% | Low (drought tolerant) |
| π₯ Carrots | 40-45% | 65-70% | 60% | 25% | Medium |
| π Eggplant | 45-50% | 70-75% | 55% | 30% | Medium |
| π Watermelon | 40-45% | 65-70% | 60% | 25% | Low |
| πΏ Beans | 40-45% | 65-70% | 60% | 25% | Medium |
| π Strawberries | 50-55% | 75-80% | 50% | 35% | Very High |
| π» Sunflower | 35-40% | 60-65% | 65% | 20% | Low |
| πΎ Sorghum | 30-35% | 55-60% | 70% | 15% | Very Low (drought tolerant) |
| π₯ Groundnuts | 35-40% | 60-65% | 65% | 20% | Low |
| πΏ Cotton | 40-45% | 65-70% | 60% | 25% | Medium |
Adjust thresholds based on crop development:
- π± Seedling/Early growth: Keep moisture HIGH (add 5-10% to thresholds) - roots are shallow
- πΏ Vegetative growth: Normal thresholds - plant is establishing
- πΎ Flowering/Fruiting: Keep moisture HIGH (add 5% to thresholds) - critical period!
- π Ripening/Harvest: Reduce moisture (subtract 5-10%) - stress can improve flavor
π» Arduino Code: Smart Threshold-Based Irrigation
/* * Smart Irrigation Using Soil Moisture Thresholds * Implements Field Capacity, Wilting Point, and MAD * * Features: * - Crop-specific thresholds * - Growth stage adjustment * - Automatic irrigation based on MAD * - Alerts for critical conditions */ #include// ========== PIN DEFINITIONS ========== #define SOIL_PIN 32 #define RELAY_PIN 5 // ========== SOIL CALIBRATION (CALIBRATE THESE!) ========== const int DRY_VALUE = 3800; // Sensor in dry air const int WET_VALUE = 1500; // Sensor in water // ========== SOIL THRESHOLDS (Based on your soil type) ========== const float FIELD_CAPACITY = 70.0; // FC: 70% (after watering) const float WILTING_POINT = 25.0; // PWP: 25% (plants die) const float AVAILABLE_WATER = FIELD_CAPACITY - WILTING_POINT; // 45% // ========== CROP CONFIGURATION ========== struct CropConfig { const char* name; float mad; // Management Allowed Depletion (50-70%) float moistureTarget; // Calculate: FC - (AVC * MAD/100) float criticalPoint; // Below this = emergency! }; // Pre-calculated thresholds for common crops CropConfig crops[] = { {"Tomatoes", 50, FIELD_CAPACITY - (AVAILABLE_WATER * 0.50), 30}, {"Maize", 55, FIELD_CAPACITY - (AVAILABLE_WATER * 0.55), 25}, {"Peppers", 50, FIELD_CAPACITY - (AVAILABLE_WATER * 0.50), 30}, {"Cabbage", 45, FIELD_CAPACITY - (AVAILABLE_WATER * 0.45), 35}, {"Onions", 65, FIELD_CAPACITY - (AVAILABLE_WATER * 0.65), 20}, {"Potatoes", 55, FIELD_CAPACITY - (AVAILABLE_WATER * 0.55), 25}, {"Beans", 60, FIELD_CAPACITY - (AVAILABLE_WATER * 0.60), 25}, {"Sorghum", 70, FIELD_CAPACITY - (AVAILABLE_WATER * 0.70), 15} }; int currentCrop = 0; // Index of selected crop int growthStage = 2; // 1=Seedling, 2=Vegetative, 3=Flowering, 4=Ripening // ========== READ SOIL MOISTURE ========== float readSoilMoisture() { int raw = analogRead(SOIL_PIN); float moisture = map(raw, DRY_VALUE, WET_VALUE, 0, 100); return constrain(moisture, 0, 100); } // ========== GET GROWTH STAGE ADJUSTMENT ========== float getGrowthStageAdjustment() { switch(growthStage) { case 1: return 8.0; // Seedling: +8% (keep wetter) case 2: return 0.0; // Vegetative: normal case 3: return 5.0; // Flowering: +5% (critical) case 4: return -5.0; // Ripening: -5% (stress for flavor) default: return 0.0; } } // ========== DETERMINE IRRIGATION ACTION ========== String getIrrigationAction(float moisture, CropConfig crop, float growthAdj) { float adjustedTarget = crop.moistureTarget + growthAdj; float adjustedCritical = crop.criticalPoint + growthAdj; if (moisture <= adjustedCritical) { return "π¨ CRITICAL: EMERGENCY IRRIGATION! Soil below critical point!"; } else if (moisture <= adjustedTarget) { return "π§ IRRIGATE: Soil below MAD threshold. Starting irrigation..."; } else if (moisture >= FIELD_CAPACITY) { return "βΈοΈ STOP: Soil at Field Capacity. Stop irrigation!"; } else { return "β OK: Soil moisture adequate. No action needed."; } } // ========== CALCULATE WATER NEEDED ========== int calculateWaterNeeded(float moisture, CropConfig crop, float growthAdj) { float adjustedTarget = crop.moistureTarget + growthAdj; if (moisture <= adjustedTarget) { // Calculate how much water to add float deficit = FIELD_CAPACITY - moisture; int duration = (deficit / 20.0) * 300; // Rough guide: 20% deficit = 5 minutes // Ensure reasonable limits duration = constrain(duration, 180, 1200); // 3-20 minutes return duration; } return 0; } // ========== DISPLAY COMPLETE REPORT ========== void displaySoilReport(float moisture, CropConfig crop, float growthAdj) { float adjustedTarget = crop.moistureTarget + growthAdj; float adjustedCritical = crop.criticalPoint + growthAdj; Serial.println("\nββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ"); Serial.println("β π SOIL MOISTURE THRESHOLD REPORT β"); Serial.println("ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ"); Serial.println("\nπ± CROP INFORMATION:"); Serial.printf(" Crop: %s\n", crop.name); Serial.printf(" Growth Stage: "); switch(growthStage) { case 1: Serial.println("Seedling (keep wetter +8%)"); break; case 2: Serial.println("Vegetative (normal)"); case 3: Serial.println("Flowering/Fruiting (critical +5%)"); case 4: Serial.println("Ripening/Harvest (dry down -5%)"); default: Serial.println("Unknown"); } Serial.println("\nπ SOIL THRESHOLDS:"); Serial.printf(" Field Capacity (FC): %.0f%% (Stop watering here)\n", FIELD_CAPACITY); Serial.printf(" Wilting Point (PWP): %.0f%% (CRITICAL - plants die)\n", WILTING_POINT); Serial.printf(" MAD Trigger: %.0f%% (Start watering here)\n", adjustedTarget); Serial.printf(" Critical Point: %.0f%% (Emergency below this)\n", adjustedCritical); Serial.println("\nπ§ CURRENT STATUS:"); Serial.printf(" Current Moisture: %.1f%%\n", moisture); // Visual gauge int bars = moisture / 5; Serial.print(" ["); for (int i = 0; i < 20; i++) { if (i < bars) Serial.print("β"); else Serial.print("β"); } Serial.println("]"); Serial.println("\nπ― DECISION:"); String action = getIrrigationAction(moisture, crop, growthAdj); Serial.printf(" %s\n", action.c_str()); int waterNeeded = calculateWaterNeeded(moisture, crop, growthAdj); if (waterNeeded > 0) { Serial.printf(" π§ Recommended watering: %d minutes (%.0f minutes)\n", waterNeeded, waterNeeded/60.0); } Serial.println("\nββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n"); } void setup() { Serial.begin(115200); pinMode(SOIL_PIN, INPUT); pinMode(RELAY_PIN, OUTPUT); digitalWrite(RELAY_PIN, HIGH); // Pump OFF initially Serial.println("βββββββββββββββββββββββββββββββββββββββββββ"); Serial.println("π SMART THRESHOLD-BASED IRRIGATION"); Serial.println(" Field Capacity, Wilting Point & MAD"); Serial.println("βββββββββββββββββββββββββββββββββββββββββββ\n"); Serial.println("Crop Selection:"); for (int i = 0; i < 8; i++) { Serial.printf(" %d: %s (MAD: %.0f%%, Target: %.0f%%)\n", i+1, crops[i].name, crops[i].mad, crops[i].moistureTarget); } // Set crop (change this to your crop) currentCrop = 0; // 0 = Tomatoes Serial.printf("\nβ Selected: %s\n", crops[currentCrop].name); Serial.printf(" Start watering at: %.0f%%\n", crops[currentCrop].moistureTarget); Serial.printf(" Stop watering at: %.0f%% (Field Capacity)\n\n", FIELD_CAPACITY); } void loop() { float moisture = readSoilMoisture(); CropConfig crop = crops[currentCrop]; float growthAdj = getGrowthStageAdjustment(); displaySoilReport(moisture, crop, growthAdj); // Decision logic float adjustedTarget = crop.moistureTarget + growthAdj; if (moisture <= adjustedTarget) { // Start irrigation int duration = calculateWaterNeeded(moisture, crop, growthAdj); Serial.printf("π§ Starting irrigation for %d seconds...\n", duration); digitalWrite(RELAY_PIN, LOW); // Pump ON delay(duration * 1000); digitalWrite(RELAY_PIN, HIGH); // Pump OFF Serial.println("β Irrigation complete\n"); } else if (moisture >= FIELD_CAPACITY) { Serial.println("βΈοΈ Soil at Field Capacity - Skipping irrigation\n"); } else { Serial.println("β Soil moisture adequate - Waiting for next check\n"); } // Check every 6 hours (21,600,000 ms) or adjust as needed delay(21600000); }
A tomato farm in Tanzania implemented threshold-based irrigation:
- π Before: Watered daily regardless of soil condition β 25% wasted water
- π¬ Measurement: Found Field Capacity = 72%, Wilting Point = 28%
- π― Threshold: Set MAD at 50% β Start irrigation at 50% moisture
- π§ Result: Water usage decreased 35%, tomato yield increased 22%
- π° Savings: $200/month + higher quality tomatoes
"Understanding Field Capacity and Wilting Point changed everything. We now water exactly when the plants need it - not on a fixed schedule." - Farm Manager, Tanzania
Many farmers continue irrigating even after soil reaches Field Capacity. This causes:
- π§ Water wasted (drains below root zone)
- πΈ Fertilizer leaching (washed away)
- π± Root rot from anaerobic conditions
- π Lower yields (stressed plants)
Solution: Always stop irrigation when moisture reaches 70-80% (Field Capacity)!
You now understand soil moisture thresholds scientifically!
- β Field Capacity, Wilting Point, and Available Water explained
- β Soil type effects (sandy, loamy, clay) with numerical values
- β Crop-specific thresholds for 15+ African crops
- β Growth stage adjustments for seedlings, flowering, ripening
- β Complete Arduino code implementing all thresholds
Next step: Calibrate your specific soil sensor and apply these thresholds!
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β SOIL MOISTURE THRESHOLD QUICK REFERENCE β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€ β β β π΄ 0-20%: CRITICAL DRY - Plants at Permanent Wilting Point! β β β EMERGENCY IRRIGATION REQUIRED! β β β β π‘ 20-40%: DRY - Approaching MAD threshold β β β Plan irrigation within 24-48 hours β β β β π’ 40-65%: IDEAL RANGE - Optimal for most crops β β β Maintain with regular irrigation β β β β π’ 65-75%: MOIST - Approaching Field Capacity β β β Reduce irrigation frequency β β β β π΅ 75-100%: VERY WET - At or above Field Capacity β β β STOP irrigating! Risk of root rot β β β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€ β FORMULAS: β β Available Water = FC - PWP β β MAD Trigger = FC - (Available Water Γ MAD%) β β Example (Loam): FC=70%, PWP=25%, AWC=45%, MAD=50% β β β Irrigate at: 70% - (45% Γ 0.5) = 47.5% β β β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- 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.