ESP32C3 Smart Irrigation System with OLED Display and Soil Moisture Sensor
View and Edit Project In Cirkit Designer
Circuit Documentation
Summary
This circuit is designed to automate the watering of plants using a capacitive soil moisture sensor, an ESP32C3 microcontroller, and a 5V mini water pump. The system reads the soil moisture level and activates the water pump when the moisture level falls below a predefined threshold. The circuit also includes an OLED display for real-time monitoring and pushbuttons for user interaction.
Component List
ESP32C3 Supermini
- Description: A microcontroller with Wi-Fi and Bluetooth capabilities.
- Pins: GPIO05, GPIO06, GPIO07, GPIO08, GPIO09, GPIO10, GPIO20, GPIO21, GPIO00, GPIO01, GPIO02, GPIO03, GPIO04, 3.3V, GND, +5V
0.96" OLED
- Description: A small OLED display for visual output.
- Pins: GND, VDD, SCK, SDA
DFRobot Capacitive Soil Moisture Sensor (V1.0)
- Description: A sensor to measure soil moisture levels.
- Pins: A, VCC, GND
Pushbutton (4 units)
- Description: Buttons for user input.
- Pins: Pin 3 (out), Pin 4 (out), Pin 1 (in), Pin 2 (in)
5V Mini Water Pump
- Description: A small water pump for irrigation.
- Pins: positive pin, negative pin
5V Battery
- Description: Power source for the circuit.
- Pins: +, -
Wiring Details
ESP32C3 Supermini
- GPIO10: Connected to the positive pin of the 5V mini water pump.
- GPIO00: Connected to Pin 2 (in) of a pushbutton.
- GPIO01: Connected to Pin 2 (in) of another pushbutton.
- GPIO02: Connected to Pin 2 (in) of another pushbutton.
- GPIO03: Connected to Pin 2 (in) of another pushbutton.
- GPIO04: Connected to pin A of the DFRobot Capacitive Soil Moisture Sensor.
- 3.3V: Connected to pin VCC of the DFRobot Capacitive Soil Moisture Sensor and pin VDD of the 0.96" OLED.
- GND: Connected to pin GND of the DFRobot Capacitive Soil Moisture Sensor, pin GND of the 0.96" OLED, pin 4 (out) of all pushbuttons, the negative pin of the 5V mini water pump, and the negative pin of the 5V battery.
- +5V: Connected to the positive pin of the 5V battery.
0.96" OLED
- GND: Connected to GND of the ESP32C3 Supermini.
- VDD: Connected to 3.3V of the ESP32C3 Supermini.
- SCK: Not connected.
- SDA: Not connected.
DFRobot Capacitive Soil Moisture Sensor (V1.0)
- A: Connected to GPIO04 of the ESP32C3 Supermini.
- VCC: Connected to 3.3V of the ESP32C3 Supermini.
- GND: Connected to GND of the ESP32C3 Supermini.
Pushbuttons
- Pin 2 (in): Connected to GPIO00, GPIO01, GPIO02, and GPIO03 of the ESP32C3 Supermini respectively.
- Pin 4 (out): Connected to GND of the ESP32C3 Supermini.
5V Mini Water Pump
- positive pin: Connected to GPIO10 of the ESP32C3 Supermini.
- negative pin: Connected to GND of the ESP32C3 Supermini.
5V Battery
- +: Connected to +5V of the ESP32C3 Supermini.
- -: Connected to GND of the ESP32C3 Supermini.
Code Documentation
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <EEPROM.h>
#include <AT24C256.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
#define AT24C256_ADDRESS 0x50
AT24C256 eeprom(AT24C256_ADDRESS);
// EEPROM Address Constants
#define EEPROM_DRY_VALUE_ADDR 0
#define EEPROM_WET_VALUE_ADDR (EEPROM_DRY_VALUE_ADDR + sizeof(int))
#define EEPROM_LOW_THRESHOLD_ADDR (EEPROM_WET_VALUE_ADDR + sizeof(int))
#define EEPROM_HIGH_THRESHOLD_ADDR (EEPROM_LOW_THRESHOLD_ADDR + sizeof(int))
#define EEPROM_PUMP_DURATION_ADDR (EEPROM_HIGH_THRESHOLD_ADDR + sizeof(int))
#define EEPROM_WAIT_DURATION_ADDR (EEPROM_PUMP_DURATION_ADDR + sizeof(int))
// Pin definitions
#define SOIL_SENSOR_PIN A4 // ADC pin for soil moisture sensor
#define PUMP_PIN 10 // Pump control pin
#define MODE_BTN 0 // Mode button pin
#define SELECT_BTN 1 // Select button pin
#define UP_BTN 2 // Up button pin
#define DOWN_BTN 3 // Down button pin
// Screen states
enum Screen {
MAIN_SCREEN,
CALIBRATION,
SET_THRESHOLD,
SET_DURATION,
MANUAL
};
enum CalibrationOption {
DRY,
WET
};
enum ThresholdOption {
LOW_THRESHOLD,
HIGH_THRESHOLD
};
enum DurationOption {
PUMP_DURATION,
WAIT_DURATION
};
// Variables
Screen currentScreen = MAIN_SCREEN;
CalibrationOption currentCalibrationOption = DRY;
ThresholdOption currentThresholdOption = LOW_THRESHOLD;
DurationOption currentDurationOption = PUMP_DURATION;
int moistureValue = 0;
int moisturePercent = 0;
int threshold_low = 30;
int threshold_high = 80;
int pumpDuration = 10000; // 10 seconds in milliseconds
int waitDuration = 20000; // 20 seconds in milliseconds
bool isPumping = false;
bool canPump = true;
unsigned long pumpStartTime = 0;
unsigned long waitStartTime = 0;
unsigned long lastReadTime = 0;
// Calibration values
int dryValue = 3460;
int wetValue = 1240;
// Change tracking
bool calibrationChanged = false;
bool thresholdChanged = false;
bool durationChanged = false;
void saveToEEPROM() {
EEPROM.put(EEPROM_DRY_VALUE_ADDR, dryValue);
EEPROM.put(EEPROM_WET_VALUE_ADDR, wetValue);
EEPROM.put(EEPROM_LOW_THRESHOLD_ADDR, threshold_low);
EEPROM.put(EEPROM_HIGH_THRESHOLD_ADDR, threshold_high);
EEPROM.put(EEPROM_PUMP_DURATION_ADDR, pumpDuration);
EEPROM.put(EEPROM_WAIT_DURATION_ADDR, waitDuration);
}
void loadFromEEPROM() {
int storedDryValue, storedWetValue, storedLowThreshold,
storedHighThreshold, storedPumpDuration, storedWaitDuration;
EEPROM.get(EEPROM_DRY_VALUE_ADDR, storedDryValue);
EEPROM.get(EEPROM_WET_VALUE_ADDR, storedWetValue);
EEPROM.get(EEPROM_LOW_THRESHOLD_ADDR, storedLowThreshold);
EEPROM.get(EEPROM_HIGH_THRESHOLD_ADDR, storedHighThreshold);
EEPROM.get(EEPROM_PUMP_DURATION_ADDR, storedPumpDuration);
EEPROM.get(EEPROM_WAIT_DURATION_ADDR, storedWaitDuration);
// Validate stored values to prevent using uninitialized EEPROM
if (storedDryValue > 0 && storedDryValue < 4096) dryValue = storedDryValue;
if (storedWetValue > 0 && storedWetValue < 4096) wetValue = storedWetValue;
if (storedLowThreshold >= 0 && storedLowThreshold <= 100) threshold_low = storedLowThreshold;
if (storedHighThreshold >= 0 && storedHighThreshold <= 100) threshold_high = storedHighThreshold;
if (storedPumpDuration > 0 && storedPumpDuration < 60000) pumpDuration = storedPumpDuration;
if (storedWaitDuration > 0 && storedWaitDuration < 120000) waitDuration = storedWaitDuration;
}
void setup() {
Serial.begin(115200);
// Load saved settings
loadFromEEPROM();
// Initialize OLED
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
for (;;);
}
display.clearDisplay();
// Initialize pins
pinMode(PUMP_PIN, OUTPUT);
pinMode(MODE_BTN, INPUT_PULLUP);
pinMode(SELECT_BTN, INPUT_PULLUP);
pinMode(UP_BTN, INPUT_PULLUP);
pinMode(DOWN_BTN, INPUT_PULLUP);
digitalWrite(PUMP_PIN, LOW);
}
int readSoilMoisture() {
int sum = 0;
// Take 5 readings for smoothing
for (int i = 0; i < 5; i++) {
sum += analogRead(SOIL_SENSOR_PIN);
delay(10);
}
int avgReading = sum / 5;
// Convert to