Skip to content

Repository files navigation

🤖 Sprinkletron

An affectionately faithful plant waterer 🤖 💖 🌱 🦾

It runs in two modes.

  1. Interval mode - waters every N hours for M minutes
  2. Soil moisture mode - waters when soil is dry, checks every N hours, waters if necessary.

You can find either program in the sketch folder. Drag it out into src and rename to main.cpp to use. Interval should run on any architecture, soil moisture mode is currently ESP32 only.

If using rainbird gph heads, you can provide the total gallons per hour and it will make sure the pump doesn't dry out.

Alt 1 Alt 2
sad and forgotten 😢 happy and taken care of 😎 🦾

Interval mode

Alt 1 Alt 2
interval mode with two power sources GPH heads setup

Install

This project uses PlatformIO as the build toolchain. Get the VSCode extension or just install the CLI tool.

pio project init --board esp32dev

Build and deploy

pio run -e esp32dev -t upload

Hardware

ESP32 microcontroller - A low-power microcontroller with built-in Wi-Fi and Bluetooth capabilities. It is used to control the watering system.

Breadboard power supply - A power supply module that can be plugged into a breadboard to provide power to the ESP32 and other components. It provides 3.3V and 5V outputs.

Capacitive Soil Moisture Sensor - Corrosion Resistant Moisture Detection Garden Watering for Arduino DIY 3.3~5.5V

Submersible 3V DC Pump - A small 3V DC pump that can be used to water plants. a DC motor that is powered with 3V and draws 100mA. When powered, the pump sucks water in from the side of the plastic casing and pushes it out the tubing port. The pump must be primed by keeping it inside water at all times. You can PWM the motor power to speed up or slow down the flow rate.

N-Channel Power MOSFET - The MOSFET when it recieves 3.3v HIGH signal from the ESP32 will complete the pump circuit to ground allowing the pump to run. The MOSFET is used to switch the pump on and off.

Schottky Diode - A diode that is used to protect the MOSFET from back EMF when the pump is turned off. The cathode of the diode is connected to the +3.3V supply and the anode is connected to the pump negative terminal.

NOTE: RAINBIRD GPH HEADS:

If you want to use these heads, just realize you may need two power sources as they cause the pump to draw more current causing MCU brownout if both are connected to the same 3v3 rail. Instead connect your MCU to power using the usb power input and connect the pump to a separate 3.3V power supply. Also it can help to add a large capacitor across the pump terminals to smooth out current spikes.

Wiring

Sprinkletron GPIO Pinout

For basic configuration I used a breadboard to wire the components together. The wiring is as follows:

  • Soil moisture sensor:

    • VCC → 3V3
    • GND → GND
    • A0 → GPIO36 (ADC1)

    Sensor values vary, best to test in your own setup.

  • Pump:

    • VCC → 3V3
    • GND → GND
    • IN → GPIO18 (MOSFET gate)
  • MOSFET:

    • Source → GND
    • Drain → Pump GND
    • Gate → (GPIO18 → 220Ω → GATE → 100kΩ pulldown to GND to keep it off at boot)
  • Diode:

    • Cathode → in front of pump +3.3V
    • Anode → in front of Pump negative terminal
  • ESP32:

    • GND → GND
    • power supply → 5V
    • pin GPIO18 → Pump MOSFET gate

Sprinkletron GPIO Pinout

PWM Overview

Digital devices output 1's and 0's. i.e HIGH or LOW signal. So how do we change the power of the motor if we can only tell it to be ON or OFF? It turns out that we can approximate an analog signal by switching the pump on for a period of time and off again in a repeating cycle. This technique is called Pulse Width Modulation (PWM). The ratio of the time the pump is on to the total time of the cycle is called the duty cycle. The duty cycle is expressed as a percentage, where 100% means the pump is always on, and 0% means it is always off.

Lets say we want the water pump to run at 80% of its maximum power.

Given that the pump runs at 20,000 cycles per second.

$$ f = 20000 \text{ Hz} $$

Then the time it takes to complete a single cycle is expressed as the period $T$:

$$ T = f^{-1} = \frac{1}{20000} = 0.00005 \text{ seconds} = 50 \mu s $$

For the $50\mu s$ in each cycle, we want the pump to be on for 80% of the time and off for 20%.

$$ T_{on} = D * T = 0.8 * 50 \mu s = 40 \mu s $$

$$ T_{off} = (1 - D) * T = 0.2 * 50 \mu s = 10 \mu s $$

The math is for illustration. The actual timing is handled at a lower level. All we need to do is set the appropriate values in the programming interface and it calculates and fires the PWM pulses itself. For the esp32 microcontroller we need to configure the PWM channel range. What does this mean? We are setting the denominator in the duty cycle ratio. In our case we set it to 10 bits, which gives us a range of values from 0 to 1023.

$$ \text{channel 0 bit space} = 2^{10} - 1 = 1023 $$

$$ \text{duty cycle} = D * T = 0.8 * 1023\approx 818 $$

//setup PWM channel
ledcSetup(0, 20000, 10);

// notice that D in the programming case is an integer value 80, not a floating point 0.8
// We do this in integer math the entire time. For embedded systems this is important
// Avoiding the floating point overhead keeps the code fast and efficient
int maxDuty = (1 << PWM_RES_BITS) - 1; // 1023 for 10 bits
int duty = (80 * maxDuty) / 100; // 80% duty cycle
ledcWrite(PWM_CH, duty);

Now for each $50 \mu s$ cycle we get the pump on for $40 \mu s$ and off for $10 \mu s$. This approximates 80% power with a digital signal.

About

Waters my plants

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages