Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Soil Moisture Monitoring System

A production-grade, multi-sensor soil moisture monitoring system with real-time visualization and cloud access.

Soil Moisture Dashboard

Overview

This project implements a distributed IoT sensor network for continuous soil moisture monitoring across multiple locations. Each ESP8266-based sensor reads capacitive soil moisture levels every 5 minutes and transmits data to a centralized time-series database, with live visualization through Grafana dashboards accessible globally.

Live Dashboard: https://grafana.owenmedeiros.com

Key Features

Multi-Sensor Architecture

Reliability & Resilience

Remote Access & Monitoring

System Health

Technologies Used

Microcontroller
  • ESP8266 NodeMCU: WiFi-enabled MCU

  • C++: Firmware development

  • PlatformIO: Build system and OTA

  • ArduinoJson: Data serialization

Backend Infrastructure
  • Raspberry Pi 5: Central server (4GB RAM)

  • InfluxDB 2.x: Time-series database

  • Grafana: Dashboard visualization

  • Cloudflare Tunnel: Public HTTPS access

Data & Monitoring
  • Flux: InfluxDB query language

  • NTP: UTC timestamping

  • systemd: Service management

  • Python: System metrics collection

System Architecture

┌─────────────────────────┐
│  Capacitive Sensor      │
│  (Analog Output)        │
└───────────┬─────────────┘
            │
            ▼
┌─────────────────────────┐
│  ESP8266 NodeMCU        │
│  - ADC Reading          │
│  - WiFi Connectivity    │
│  - Offline Queue        │
│  - OTA Support          │
└───────────┬─────────────┘
            │
            │ WiFi (WPA2)
            │ HTTP POST
            ▼
┌─────────────────────────┐
│  Raspberry Pi 5 Server  │
│  ┌────────────────────┐ │
│  │ InfluxDB (:8086)   │ │
│  │ - 365-day retention│ │
│  │ - USB storage      │ │
│  └────────────────────┘ │
│  ┌────────────────────┐ │
│  │ Grafana (:3000)    │ │
│  │ - 6 Dashboards     │ │
│  │ - Anonymous view   │ │
│  └────────────────────┘ │
│  ┌────────────────────┐ │
│  │ Cloudflare Tunnel  │ │
│  └────────────────────┘ │
└───────────┬─────────────┘
            │
            │ HTTPS
            ▼
┌─────────────────────────┐
│  Public Access          │
│  grafana.owenmedeiros   │
│  .com                   │
└─────────────────────────┘

Hardware Components

Per Sensor Unit

ComponentSpecifications
ESP8266 NodeMCU v280/160 MHz, 80KB RAM, 4MB Flash
Capacitive Moisture Sensor v1.2Analog output, corrosion-resistant
Micro-USB Power5V/1A charger + cable
Jumper Wires3× Female-Female

Wiring Diagram

Sensor VCC  ──► ESP8266 3V3
Sensor GND  ──► ESP8266 GND
Sensor AOUT ──► ESP8266 A0

Note: Use 3.3V power only — ESP8266 ADC maximum is 1.0V (NodeMCU has built-in voltage divider)

Firmware Features

Version 2.1.0

Core Functionality

WiFi Management

Data Persistence

Telemetry

OTA Updates

Software Implementation

Sensor Calibration

The ESP8266 ADC returns raw values (0-1023). Capacitive sensors read high when dry, low when wet.

Calibration Steps:

  1. Hold sensor in open air → Note raw=XXX from serial output

  2. Set SENSOR_AIR_VALUE = XXX in config.h

  3. Submerge sensor tip in water → Note raw=XXX

  4. Set SENSOR_WATER_VALUE = XXX in config.h

  5. Re-flash firmware

Configuration

Edit firmware/src/config.h before flashing:

// Unique per sensor
#define DEVICE_ID        "sensor-1"
#define DEVICE_LOCATION  "living-room"

// Network
#define WIFI_SSID        "YourNetwork"
#define WIFI_PASSWORD    "YourPassword"

// InfluxDB
#define DB_SERVER_URL    "http://192.168.1.100:8086/api/v2/write"
#define INFLUX_TOKEN     "your-token-here"
#define INFLUX_ORG       "soil-monitoring"
#define INFLUX_BUCKET    "sensor-readings"

// Calibration (measure in air and water)
#define SENSOR_AIR_VALUE    780
#define SENSOR_WATER_VALUE  360

Data Schema

Measurement: sensor_reading (every 5 minutes)

TagFieldDescription
device_idSensor identifier
locationPhysical location
moistureSoil moisture % (0-100)
raw_adcRaw ADC value
rssiWiFi signal strength (dBm)
uptimeSeconds since boot
free_heapAvailable RAM (bytes)

Measurement: sensor_heartbeat (every 60 seconds)

TagFieldDescription
device_idSensor identifier
uptimeSeconds since boot
free_heapAvailable RAM
rssiWiFi signal strength
queue_sizeOffline queue depth (0-20)

Grafana Dashboards

Dashboard Suite (6 Total)

  1. Soil Moisture Main — Overview with all sensors, gauges, trend plots

  2. Sensor Details — Individual sensor deep-dive with uptime, heap, WiFi

  3. System Health — ESP8266 diagnostics, WiFi stability, critical events

  4. Alerts Overview — Critical alerts, watering notifications, offline detection

  5. Mobile Summary — Mobile-optimized quick view

  6. Raspberry Pi Health — Server CPU, RAM, disk, temperature

Dashboard Features

Raspberry Pi Setup

Server Specifications

Installation

git clone https://github.com/omedeiro/soil-sensor.git
cd soil-sensor/rpi-setup
sudo ./install.sh

Installed Components:

Post-Installation

  1. Configure InfluxDB at http://<pi-ip>:8086

    • Create organization: soil-monitoring

    • Create bucket: sensor-readings (365-day retention)

    • Generate API tokens (write for sensors, read for Grafana)

  2. Configure Grafana at http://<pi-ip>:3000

    • Login: admin / admin (change on first login)

    • Add InfluxDB datasource (Flux mode)

    • Import dashboards from grafana-dashboards/*.json

  3. Enable Public Access

    cd rpi-setup
    ./install-cloudflare-tunnel.sh
    ./configure-grafana-anonymous.sh

System Services

ServiceFunctionAuto-Restart
influxdbTime-series database
grafana-serverDashboard visualization
cloudflaredHTTPS tunnel
sensor-health-monitorFailure detection
sensor-backup.timerDaily backup (3 AM)
system-metrics-collectorPi metrics

Service Management:

# Status check
sudo systemctl status influxdb grafana-server cloudflared

# View logs
journalctl -u influxdb -f

# Restart services
sudo systemctl restart influxdb grafana-server

Performance & Reliability

Uptime Statistics

Data Resilience

Development Workflow

Adding a New Sensor

  1. Edit firmware/src/config.h:

    • Set unique DEVICE_ID (e.g., “sensor-4”)

    • Set DEVICE_LOCATION (e.g., “backyard”)

  2. Flash firmware via USB or OTA

  3. Sensor auto-appears in Grafana dropdown within 5 minutes

OTA Firmware Update

cd firmware
pio run --target upload --upload-port 192.168.1.50
# Enter OTA password when prompted

Troubleshooting

SymptomSolution
WiFi connection failsCheck 2.4 GHz band, move sensor closer to router
HTTP 401 from InfluxDBVerify INFLUX_TOKEN in config.h
Dashboard shows no dataCheck time range (set to “Last 1 hour”)
Sensor offlineCheck power supply, view crash logs via serial
Public URL unreachableVerify Cloudflare Tunnel: sudo systemctl status cloudflared

Future Enhancements

Repository & Documentation

Documentation Structure

Status

Version 2.3.0 — Production deployment with 4 active sensors monitoring residential and garden locations. System has been operational since January 2026 with 99%+ uptime.

Live Access: https://grafana.owenmedeiros.com