Community project
Untitled Project
Generated with AIThis automatic plant watering system monitors soil moisture with a capacitive sensor and triggers a 12V water pump when the soil dries out. The ESP32 microcontroller reads moisture levels, controls the pump via a MOSFET switch, and sounds an alert buzzer when watering begins. Builders will receive a complete wiring diagram, parts list, firmware with calibration guidance, and step-by-step assembly instructions covering water line preparation, sensor and buzzer hookup, pump switching circuit, flyback diode protection, power supply verification, and initial moisture calibration.
The system uses an MP1584 buck converter to safely step down 12V to ESP32 logic levels, a logic-level MOSFET to switch the pump on demand, and a 1N4007 diode to protect against inductive kickback. Assembly follows a logical sequence from power isolation through electrical testing to final calibration, ensuring safe handling of both water and high-voltage components.
Wiring diagram
Interactive · read-only
Pan and zoom to explore the wiring. Remix the project to edit it in your own workspace.
Parts list
Bill of materials| Component | Qty | Notes |
|---|---|---|
| Gravity: IP65 Capacitive Soil Moisture SensorSEN0308 | 1 | Capacitive soil moisture sensor with IP65 waterproof and corrosion-resistant construction. Compatible with Arduino, ESP32, and Raspberry Pi. |
| 12V DC Submersible Mini Water Pump12 V | 1 | Two-wire brushed DC submersible water pump for small irrigation or circulation projects. It is an external load and must be driven through a relay, MOSFET, or motor driver; do not connect directly to an MCU GPIO. |
| IRLZ44N Logic-Level N-Channel MOSFETIRLZ44N | 1 | Logic-level N-channel MOSFET commonly used as a low-side switch for DC loads from 3.3V or 5V microcontroller GPIO. Use a gate resistor, a gate pulldown, and a flyback diode for inductive loads. |
| 1N4007 Diode1N4007 | 1 | General-purpose silicon rectifier diode in DO-204AL (DO-41) axial through-hole package. Rated 1A average forward current and 1000V peak reverse voltage (VRRM). Forward voltage drop ~0.7V at typical load (up to 1.1V at full 1A). Used here in series with LM7805 Vout for reverse polarity protection: anode to LM7805 output, cathode to 5V rail, resulting in ~4.3V on the output rail. Not suitable for high-frequency switching (reverse recovery ~2µs–30µs); intended for DC or 50/60Hz rectification only. |
| Buzzer3.3 V active | 1 | Piezo buzzer for sound output |
| 12V Barrel-Jack Adapter12 V / 2 A | 1 | 12 V / 2 A wall adapter with a 5.5 mm / 2.1 mm barrel jack. Used to power motor drivers, LED strips, or boards that need a higher rail. |
| MP1584 Buck ConverterSet to 5.0 V | 1 | Adjustable buck (step-down) DC-DC converter, 4.5-28 V in -> 0.8-20 V out, ~3 A. Configured to 5 V to step a 9 V / 12 V supply or battery pack down to the board's 5 V rail. |
| Resistor100 Ω | 1 | Through-hole resistor (current-limiting in series with an LED) |
| Resistor10 kΩ | 1 | Through-hole resistor (current-limiting in series with an LED) |
Assembly
6 steps断电并准备水路
先不要连接 12V 适配器。将 pump_1 放入水箱,出水管固定在花盆土表面上方,避免水倒流到电子元件。
- Tip: 先用清水短暂测试水泵和管路是否通畅。
- Tip: 让水泵始终浸在水中再运行。
- ⚠ 电子元件、ESP32 和适配器必须放在远离漏水的位置。
- ⚠ 水泵不得干转。
连接湿度传感器和蜂鸣器
soil_sensor_1 的 VCC 接 ESP32 3V3、GND 接 ESP32 GND、AOUT 接 GPIO34。buzzer_1 的 GND 接 GND,SIGNAL 接 GPIO25;若你的蜂鸣器模块另有 VCC 引脚,则接 ESP32 3V3。
- Tip: 只将传感器探头部分插入土中,连接端保持干燥。
- Tip: GPIO34 是仅输入的模拟脚,正适合传感器输出。
- ⚠ 传感器 AOUT 不可接 5V;本设计使用 3.3V 供电,确保 ESP32 模拟输入安全。
搭建水泵 MOSFET 开关
pump_1 的 PUMP+ 接 adapter_1 的 +12V;PUMP- 接 mosfet_1 的 DRAIN;mosfet_1 的 SOURCE 接公共 GND。gate_resistor_1(100Ω)串联在 GPIO26 与 mosfet_1 的 GATE 之间。gate_pulldown_1(10kΩ)一端接 GATE、另一端接公共 GND。
- Tip: IRLZ44N 面向你、引脚朝下时通常为 GATE、DRAIN、SOURCE;仍请以所购器件的数据手册/丝印为准。
- Tip: 把 12V 适配器负极、MOSFET SOURCE、ESP32 GND 接到同一个公共地。
- ⚠ 绝不可把水泵接到 ESP32 GPIO 或 3.3V 引脚。
- ⚠ 确认 MOSFET 引脚顺序后才通电,接反可能损坏器件。
安装续流二极管
flyback_diode_1 并联在 pump_1 两端:有色环的 Cathode 接泵 PUMP+ / +12V;无环的 Anode 接泵 PUMP- / MOSFET DRAIN。
- Tip: 二极管应尽量靠近水泵接线端安装。
- ⚠ 二极管极性不能反:有色环的一端必须接 +12V。接反会造成电源短路。
连接降压供电并检查电压
adapter_1 的 +12V 接 buck_1 VIN,负极接 buck_1 GND。先在未接 ESP32 时给适配器通电,用万用表调节 buck_1,使 VOUT 对 GND 为稳定的 5.0V;断电后再把 VOUT 接 ESP32 VIN、GND 接公共 GND。
- Tip: ESP32 的 USB 连接也可用于上传和串口查看;不要在 USB 供电与 buck 输出接入 VIN 的情况下随意改线。
- Tip: 确认所有地线已经相连后再接上电源。
- ⚠ MP1584 输出必须先调到 5.0V;高于 5V 可能损坏 ESP32 VIN 供电部分。
- ⚠ 不要将 12V 直接接入 ESP32 的 VIN 或 3V3。
首次上电与湿度校准
通电后用 Schematik 的 Deploy 按钮烧录。观察串口输出的 Soil raw 值:记录探头在干土/空气中的值并替换 RAW_DRY,记录在充分湿润土壤中的值并替换 RAW_WET;保持 RAW_DRY 大于 RAW_WET。
- Tip: 程序默认每 60 秒采样一次;湿度低于 20% 时蜂鸣 3 秒并让水泵运行 5 秒。
- Tip: 每次浇水后程序至少等待 5 分钟才允许下一次启动水泵,避免过度浇水。
- ⚠ 首次测试时把出水管对准容器而非花盆,先确认水泵工作时间和流量合适。
Pin assignments
Board wiring reference| Pin | Connection | Type |
|---|---|---|
| 3V3 | soil_sensor_1 VCC | power |
| GND | soil_sensor_1 GND | ground |
| GPIO 34 | soil_sensor_1 AOUT | analog |
| GND | buzzer_1 GND | ground |
| GPIO 25 | buzzer_1 SIGNAL | digital |
| EXT | adapter_1 +12V → MP1584 Buck Converter VIN | power |
| VIN | buck_1 VOUT | power |
| EXT | pump_1 PUMP+ → 12V Barrel-Jack Adapter +12V | data |
| EXT | pump_1 PUMP- → IRLZ44N Logic-Level N-Channel MOSFET DRAIN | data |
| GND | mosfet_1 SOURCE | ground |
| EXT | flyback_diode_1 Cathode → 12V Barrel-Jack Adapter +12V | power |
| EXT | flyback_diode_1 Anode → IRLZ44N Logic-Level N-Channel MOSFET DRAIN | power |
| GPIO 26 | gate_resistor_1 P1 | digital |
| EXT | gate_resistor_1 P2 → IRLZ44N Logic-Level N-Channel MOSFET GATE | digital |
| EXT | gate_pulldown_1 P1 → IRLZ44N Logic-Level N-Channel MOSFET GATE | digital |
| GND | gate_pulldown_1 P2 | ground |
| GND | adapter_1 GND | ground |
| GND | buck_1 GND | ground |
Firmware
ESP32#include <Arduino.h>
// Forward declarations
int readSoilRaw();
int rawToPercent(int raw);
void startAlert(unsigned long now);
void stopAlert();
void startPump(unsigned long now);
void stopPump(unsigned long now);
constexpr int SOIL_PIN = 34;
constexpr int BUZZER_PIN = 25;
constexpr int PUMP_PIN = 26;
// Calibrate these two readings for your own soil and sensor.
// RAW_DRY: probe in air/dry soil; RAW_WET: probe in fully wet soil.
constexpr int RAW_DRY = 3000;
constexpr int RAW_WET = 1500;
constexpr int DRY_THRESHOLD_PERCENT = 20;
constexpr unsigned long SAMPLE_INTERVAL_MS = 60000UL;
constexpr unsigned long PUMP_DURATION_MS = 5000UL;
constexpr unsigned long PUMP_COOLDOWN_MS = 300000UL;
constexpr unsigned long BUZZER_TOGGLE_MS = 150UL;
constexpr unsigned long ALERT_DURATION_MS = 3000UL;
unsigned long lastSampleMs = 0;
unsigned long pumpStartedMs = 0;
unsigned long lastPumpStoppedMs = 0;
unsigned long alertStartedMs = 0;
unsigned long lastBuzzerToggleMs = 0;
bool pumpRunning = false;
bool alertActive = false;
bool buzzerOn = false;
int readSoilRaw() {
long total = 0;
for (int i = 0; i < 16; ++i) {
total += analogRead(SOIL_PIN);
delay(5);
}
return total / 16;
}
int rawToPercent(int raw) {
const long numerator = static_cast<long>(RAW_DRY - raw) * 100L;
const long denominator = RAW_DRY - RAW_WET;
if (denominator == 0) return 0;
return constrain(static_cast<int>(numerator / denominator), 0, 100);
}
void startAlert(unsigned long now) {
alertActive = true;
alertStartedMs = now;
lastBuzzerToggleMs = now;
buzzerOn = true;
digitalWrite(BUZZER_PIN, HIGH);
}
void stopAlert() {
alertActive = false;
buzzerOn = false;
digitalWrite(BUZZER_PIN, LOW);
}
void startPump(unsigned long now) {
pumpRunning = true;
pumpStartedMs = now;
digitalWrite(PUMP_PIN, HIGH);
Serial.println("Pump ON");
}
void stopPump(unsigned long now) {
pumpRunning = false;
lastPumpStoppedMs = now;
digitalWrite(PUMP_PIN, LOW);
Serial.println("Pump OFF");
}
void setup() {
Serial.begin(115200);
analogReadResolution(12);
pinMode(BUZZER_PIN, OUTPUT);
pinMode(PUMP_PIN, OUTPUT);
digitalWrite(BUZZER_PIN, LOW);
digitalWrite(PUMP_PIN, LOW);
delay(200);
lastSampleMs = millis() - SAMPLE_INTERVAL_MS;
Serial.println("Soil watering controller ready");
}
void loop() {
const unsigned long now = millis();
if (pumpRunning && now - pumpStartedMs >= PUMP_DURATION_MS) {
stopPump(now);
}
if (alertActive) {
if (now - alertStartedMs >= ALERT_DURATION_MS) {
stopAlert();
} else if (now - lastBuzzerToggleMs >= BUZZER_TOGGLE_MS) {
lastBuzzerToggleMs = now;
buzzerOn = !buzzerOn;
digitalWrite(BUZZER_PIN, buzzerOn ? HIGH : LOW);
}
}
if (now - lastSampleMs < SAMPLE_INTERVAL_MS) return;
lastSampleMs = now;
const int raw = readSoilRaw();
const int moisture = rawToPercent(raw);
Serial.printf("Soil raw=%d, moisture=%d%%\n", raw, moisture);
if (moisture < DRY_THRESHOLD_PERCENT) {
Serial.println("Soil is below 20%: watering request");
startAlert(now);
if (!pumpRunning && now - lastPumpStoppedMs >= PUMP_COOLDOWN_MS) {
startPump(now);
} else {
Serial.println("Pump cooldown active; warning only");
}
}
}“Deploy to device” opens this project in Schematik, where you can flash it to your board over USB.
Remix this project
Make it yours in one click
Open a full copy of this project in your own Schematik workspace — diagram, code, parts, and assembly steps included. Swap the sensor, add features, or redesign the whole thing with AI. The author's original stays untouched.