APIS - Automated Plant Irrigation System




Introduction: APIS - Automated Plant Irrigation System

About: A maker and electronics enthusiast.

The HISTORY: (a next evolution of this system is available here)

There are quite a few instructables on the topic of plant watering, so I barely invented something original here. What does make this system different is amount of programming and customization that went into it, allowing better control and integration into day-to-day life.

Here is a video of a watering run: watering run

This is how APIS came into existence:

We have two red hot chili pepper plants, which have barely "survived" several of our vacations, and almost considered family members at this point. They have been through extreme drought, and over-watering, but always recovered somehow.

The idea to build Arduino-based plant watering was almost the first idea how Arduino could be applied as a home automation project. So a simple plant watering system was built.

However, Version 1 did not have any indication of soil humidity, and there was not way to tell whether it was about to water the plants, or watering was a few days away.

Curiosity, as we all know, killed the cat, and Version 2 was built with a 4 digit 7 segment module to display current humidity at all times.

That was not enough. The next question was "when was the last time it watered the plants"? (Since we were rarely home to witness it). Version 3 used the 7 segment module to also display how long ago the last watering run occurred (as a running text string).

One night, the watering kicked off at 4 am, waking everyone up. Frustrating... Finding it too much work to turn APIS off for the night, and on for the day to prevent watering in the middle of night, a real time clock was added to put the device to sleep at night as part of Version 4.

Since real time clock requires periodic adjustments (like daylight savings time switch for instance), Version 5, includes three buttons allowing setting a variety of plant watering parameters.

It did not stop there. I noticed that humidity probe tend to erode rather quickly, quite possibly due to the fact that it was (by design) under constant voltage, and therefore there was constant electrical current between the probes (eroding anode). The cheap soil probe from China survived about a week. Even a galvanized nail was "eaten up" in a month. A stainless steel probe was holding better, but I noticed that even that was giving up. Version 6 turns the probe on for only 1 minute every hour (and on all the time during watering), thus dramatically reducing erosion (~16 minutes a day vs. 24 hours a day).


Develop plant watering system with the following capabilities:

  1. Measure soil humidity
  2. Upon reaching a predefined "low" humidity mark, turn on water pump and water the plants until a "high" humidity mark is reached
  3. Watering should be done in several runs, separated by periods of inactivity to allow water saturation through the soil
  4. The system should deactivate itself at night between "sleep" and "wake up" times
  5. "Wake up" time should be adjusted for weekends to a later value
  6. The system should keep the log of pumping runs
  7. The system should display current reading of soil humidity
  8. The system should display date/time of last pump run
  9. Watering parameters should be adjustable without re-programming
  10. Stop pumping and indicate Error condition if pump run does not lead to change in humidity (out of water, or sensor problems) preventing flooding the plant and leaking water
  11. The system should turn humidity probe on/off to avoid metal erosion
  12. The system should drain water from the tubes to prevent mold from forming inside them

The following parameters should be configurable via buttons:

  1. Humidity "low" mark, in %, to start pump run (default = 60%)
  2. Humidity "high" mark, in %, to stop pump run (default = 65%)
  3. Duration of a single watering run, in sec (default = 60 seconds)
  4. Number of retries to reach target humidity (default = 4 runs)
  5. Military time to deactivate for the night, hours only (default = 22 or 10 pm)
  6. Military time to activate in the morning, hours only (default = 07 or 7 am)
  7. Weekend adjustment for morning activation, delta hours (default = +2 hours)
  8. Current date and time

APIS writes date/time of 10 last watering runs into the EEPROM memory. The log could be displayed, showing date and time of the runs.

One of many things we learned from APIS is that you don't actually need to water plants every day, which was our routine until we saw the soil humidity readings on a 7 segment display...

Step 1: PARTS and TOOLS

You will need the following parts to build APIS:


  1. Arduino Uno board: on Amazon.com
  2. 12v Peristaltic Liquid Pump with Silicone Tubing: on Adafruit.com
  3. 4X Numeric LED Display Digital Tube JY-MCU Module: on Fasttech.com
  4. DS1307 Real Time Clock breakout board kit: on Adafruit.com (optional)
  5. Microtivity IM206 6x6x6mm Tact Switch: on Amazon.com
  6. Vero board: on Amazon.com
  7. L293D motor driver IC: on Fasttech.com
  8. 3 x 10kOhm resistors
  9. Arduino projects plastic case: on Amazon.com
  10. 12v AC/DC adaptor with a 2.1 mm power jack: on Amazon.com
  11. Bamboo skewers
  12. Tread and a bit of supercement glue
  13. Super Soft Latex Rubber Tubing 1/8" ID, 3/16" OD, 1/32" Wall, Semi-Clear Amber, 10 ft. Length: on McMaster.com
  14. Durable Nylon Tight-Seal Barbed Tube Fitting, Tee for 1/8" Tube ID, White, packs of 10: on McMaster.com
  15. Durable Nylon Tight-Seal Barbed Tube Fitting, Wye for 1/8" Tube ID, White, packs of 10: on McMaster.com
  16. As usual, wires, soldering tools, etc.


  1. Small piece of wood (1/4" x 1/4" x 1")
  2. 2 x Stainless steel acne extraction needles: on Amazon.com
  3. Soil Humidity Detection Sensor Module: on Fasttech.com


Soil humidity is measured based on the resistance between two metal probes inserted into the ground (about 1 inch apart). The schematics are represented on the picture.

First probe I tried was the one you can buy from a number of internet providers (like this).

The problem with those is that the foil level is relatively thin, and erodes quickly (a matter of one or two weeks), so I quickly abandoned this pre-manufactured one for the sturdier sensor, based on galvanized nail (pls. see next step).


The "next generation" probe was home made from two galvanized nails, a wooden board and a couple of wires.

Since I already had a worn-out manufactured probe, I re-used the connection piece and the electronics module from it, basically just replacing the soil component.

Galvanized nails, to my surprise, also eroded (albeit slower than thin foil), but still faster than I would like.

Another probe was designed, based on a stainless steel acne removal needles. (see next step).


The stainless steel probe (resembling samurai sword, hence the name) is the one currently use.

I believe the quick erosion could be attributed to the fact that the probe was always under electrical voltage (24x7) regardless of how often the actual measurement took place.

To mitigate this, I changed the measurement intervals to be once in 1 hour (after all, this is NOT a real time system), and connected the probe to one of the digital pins instead of permanent 5v. Currently, the probe is being powered only ~16 minutes per day instead of 24 hours, which should increase its lifespan dramatically.


APIS is based on Arduino UNO board.

APIS measures soil humidity once an hour, and if it falls below a pre-defined threshold, turns the pump on for a pre-defined time period pre-defined number of times separated by "saturation" intervals.

Once a target humidity threshold is reached, the process goes back to once-an-hour measurement mode.

If the target humidity cannot be reached, but the lower limit was reached, that is OK as well (at least some watering took place). The reason could be unfortunate probe placement, where it is too far from the moist soil.

However, if even the lower humidity limit could not be reached, an error condition is declared. (Most probably a probe issue, or supply bucket ran out of water, etc.). Under error condition, the unit will sleep for 24 hours without doing anything, and then will try again.



Originally, APIS did not have any display capability. It was impossible to tell current soil humidity level without connecting via USB.

To fix that I added a 4 digit 7 segment display to the system : on Fasttech.com

I could not find a library to work with this module anywhere (neither a data sheet for it), so after a few hours of I²C port probing and experimentation, I decide to write a driver library myself.

It supports displays up to 16 digits (with 4 being a default), can display basic ASCII characters (please note not all characters could be constructed with 7 segments, so letters like W, M, etc. are not implemented)., supports decimal point display on the module, running string of characters (to display more than 4 letters), and supports 16 degrees of brightness.

The library is available on arduino.cc playground here. TM1650 driver library

Sample video is available here


A bit of 7 segment animation is implemented during a water run.

  • While pump is engaged, the digital dots on the display are running in a left to right pattern, symbolizing a water run: watering animation video
  • During "saturation" period, the dots are running from the center of display outward, symbolizing saturation: saturation animation video

Unnecessary, but a nice touch.



I used 12v Peristaltic Liquid Pump (available here) for watering the plants. The pump provides about 100 mL/min (which is about 1/2 of a glass - good to remember when configuring the water run time to avoid overflows, and it did happen 8-) )


The pump is controlled via L293D motor driver chip. Since the rotation direction is pre-set, you really only need to use the chip enable pin for control. The direction pins could be wired directly to +5v and GND permanently.

If you (like me) were not sure which direction the pump will go, you can still connect all three pins to Arduino and control direction programmatically. Less re-soldering.



I used three buttons to configure and control APIS.

All button presses are processed based on the pin interrupts (PinChangeInt library).

  • Red (rightmost) is a SELECT button. It makes APIS enter configuration mode, and also confirms the values.
  • Black leftmost and middle buttons (PLUS and MINUS respectively) are used to increase/decrease configurable values (in the configuration mode), or display current date/time and last watering run information (in normal mode).

Since most of the time the display is turned off, all the buttons will first "wake" APIS up, and only then, on a second press, perform their function.

Display turns off after 30 seconds of inactivity (unless a watering run is in progress).

APIS runs through the configuration parameters upon startup for review: video


APIS has four configuration modes:

  1. Configure watering parameters
  2. Setup Real Time Clock
  3. "Force" watering run
  4. Review watering log


  1. Low soil humidity threshold (start watering)
  2. High soil humidity threshold (stop watering)
  3. Duration of a single watering run (in seconds)
  4. Number of watering runs in one batch
  5. Duration of the soil saturation period between runs within one batch (in minutes)
  6. Night mode activation time (military time, hours only)
  7. Night mode end time (military time, hours only)
  8. Weekend adjustment for night mode end time (in hours)


  1. Century (i.e 20 for 2015)
  2. Year (i.e. 15 for 2015)
  3. Month
  4. Day
  5. Hour
  6. Minute

The clock is adjusted with seconds set to 00 upon confirmation of minutes.

Setting have a timeout period of 15 seconds, after which all changes are canceled.

Upon save, parameters are saved to the EEPROM memory.


Still not sure why I implemented it, but it is there. Once activated, APIS enters the watering mode. The watering mode, however, is still subject to thresholds. This means, that if you force watering run, but the soil humidity is above the HIGH mark, the watering run will immediately end. Basically this works only if soil humidity is between LOW and HIGH thresholds.


APIS keeps a log of the last 10 watering runs in the EEPROM memory, which user can review. Only Date/Time of the watering run is stored. Thresholds (at the time), and number of runs it took to reach HIGH threshold is not stored (although in the next version they might be).



Once APIS woke me up at night, an idea to implement a "night mode" came to mind.

A night mode is when no measurements take place, display is off, and no watering runs.

On a usual business day APIS "wakes up" at 7 am (configurable), and enters night mode at 10 pm (configurable).
On a weekend APIS uses a "weekend adjustment" setting to delay a wake up (to 9 am for example, if weekend adjustment is 2 hours).


I used hardware RTC (available here) to keep track of the date/time and enter/exit night modes.

It is optional to use, as sketches could be compiled to use so called "software" RTC (using millis() functionality of arduino).

The drawback of using software RTC is that you have to set the time every time APIS powers up.

I modified the standard RTC library to match API exactly, and also to work around millis rollover issue. (Please see the sketches step for downloads).


The entire system (except for probe) including the pump fits into a small box for Arduino Uno.

  1. TM1650 display uses TWI interface, so the SDA and SDC wires go to Arduino pins A4 and A5 respectively. The other two wires are +5v and GND.
  2. RTC board uses TWI interface, so same as above. (TM1650 and RTC use different ports, so they coexist peacefully). RTC +5v pin is connected to arduino pin 12 (powered via digital pin instead of +5v). Don't remember why I did it, you don't have to.
  3. L293D pins are connected as follows: enable (pin 1) to D5, and direction control pins 2 and 7 to arduino pins D6 and D7 respectively.
  4. BUTTONS are connected to pins D2, D8 and D9 for SELECT, PLUS and MINUS respectively. (Buttons are implemented with a pull-down 10K resistors - in the "active-high" configuration).
  5. PROBE module's +5v power is connected to arduino pin 10 (to enable periodic measurments), and probe is connected to analog pin A1.

NOTE: Fritzing schematics file has been added to the github repository.

Step 11: SKETCHES and More

March 2015 update:

  1. Added functionality to drain the tubes after watering run to prevent mold forming up
    (Boy! I am happy I did not hard-wired pump rotation direction on L293D!)
  2. More extensive logging includes date/time of the watering run start and end, beginning and ending humidity and how many times pump was engaged during the watering run
  3. Error routine updated: device will hard-reset after 24 hours of entering the error condition
  4. Recompiled with TaskScheduler 2.1.0
  5. Various other bug fixes

As of November 18, 2015 APIS was upgraded with the following additional features:

  1. Use of DirectIO library for faster and easier pin changes
  2. Use of the Timezone library to correctly switch between EST and EDT
  3. Added button de-bouncing logic using TaskScheduler only
  4. Added button repeat functionality (values cycle if button is pressed and held, with speed of cycle increasing after 5 cycles)
  5. Recompiled with IDE 1.6.6 AVR 1.6.9 against TaskScheduler 1.8.4
  6. Moved to Github


APIS is based on the following libraries:

  • EEPROM - part of Arduino IDE
  • Wire - part of Arduino IDE
  • EnableInterrupt - available on Github
  • Timezone - available on Github
  • DirectIO - available on Github

Modified (forked) by me:

Developed by me:

  • TM1650 - available on Github
  • TaskScheduler - available on Github
  • AvgFilter - available on Github


Latest version of the APIS sketch, including fritzing schematics file, is available on Github


Step 12: *** WE WON !!! ***

This project won Second Prize in the Home Automation contest sponsored by Dexter Industries.

Check it out! WOO-HOO!!!

Home Automation

Second Prize in the
Home Automation

1 Person Made This Project!


  • Big and Small Contest

    Big and Small Contest
  • For the Home Contest

    For the Home Contest
  • Make It Bridge

    Make It Bridge



7 years ago on Introduction

Thanks for this great submissions. Do you happen to have a sketch of the wiring you can put here with Fritzing or the like?


Reply 7 years ago

unfortunately I didn't create any... will do if I have some time.


Reply 4 years ago

Posted a schematic if you are still interested.


6 years ago

Very cool project. This instructable has inspired me to do something similar. I am new to Arduino and I am confused as to how you are powering the 12v pump. From the picture it looks like the pump is only connected to the motor driver chip and one other chip (not sure what that one is) and these two chips are connected directly to the Arduino. If the Arduino is being powered by the 12 v ac/dc adapter, but can only output a max of 5v, how is the pump being powered? Obviously, I am missing something.

Looking through the comments you mentioned putting together a schematic a while back, time permitting. Any chance that has happened yet?

It's also nice to see an author of an instructable be so responsive to others comments.

I really appreciate your help.


Reply 6 years ago


If you check this picture of the UNO pinout:


you'll notice on the left there is a pin called Vin. That pin outputs the voltage that UNO is powered with (not USB - through the plug). And that is the pin I use to power the motor circuit of L293D.

Note that L293D has to have 2 power lines: one for the logic circut (5V), and one for the motor circut (12V in my case). Does this help?

I am also working on an updated internet-enabled (ESP8266) version which:

1. Will measure the water level in the container, and alert if close to empty
2. Will detect if there is water under the pot, and stop watering if there is

Those are from the experience with leaks and running out of water in the container...


Reply 6 years ago

Very helpful indeed. A similar project (which others have commented on already https://www.instructables.com/id/Self-Watering-Pla... used a 9 volt battery to power the arduino, which is not ideal at all in my opinion. I thought it must be due to some limitation on the arduino's output capacity (what I thought was a max of 5v). Instead, the ability to power up to 12v using the arduino's power source (12v) via that Vin pin makes much more sense.



Reply 4 years ago

Posted a schematic if you are still interested.


Reply 6 years ago

Very helpful indeed. A similar project (which others have commented on already https://www.instructables.com/id/Self-Watering-Pla... used a 9 volt battery to power the arduino, which is not ideal at all in my opinion. I thought it must be due to some limitation on the arduino's output capacity (what I thought was a max of 5v). Instead, the ability to power up to 12v using the arduino's power source (12v) via that Vin pin makes much more sense.



Reply 6 years ago

Very helpful indeed. A similar project (which others have commented on already https://www.instructables.com/id/Self-Watering-Pla... used a 9 volt battery to power the arduino, which is not ideal at all in my opinion. I thought it must be due to some limitation on the arduino's output capacity (what I thought was a max of 5v). Instead, the ability to power up to 12v using the arduino's power source (12v) via that Vin pin makes much more sense.



6 years ago

Hi ! Do you have the schema of all of that please? I'will be great to understand how all its work! Thx and great work!


Reply 6 years ago

Unfortunately not... If I ever have the time to draw something, I will, but not in the immediate future. Apologies.


Reply 6 years ago

I understand no problem I will explore :p


Reply 4 years ago

Posted a schematic if you are still interested.


4 years ago

Great project. I have purchased all the components you listed. I was ready to start construction and realized I could not find a circuit diagram. Did I miss a link? Is there a circuit diagram? I don't know how to begin construction without one. Thanks


Reply 4 years ago

Apologies, but there is no diagram. STEP 10 explains how to connect specific components to specific pins. This is as close as I got to building a diagram...


Reply 4 years ago

Posted a schematic if you are still interested.


4 years ago

Hi, I could use a little help: I changed line 1452 in the Arduino code from

#define SET_TIME 1420113600L // 1/1/2015 12:00:00 PM
#define SET_TIME 1543709361L // 12/02/2018 12:09:00 AM

Unfortunately the time on the APIS LED reads 2018-12-130 1.745
Does anyone have any insight into this behavior? Thanks!


Reply 4 years ago

That's clearly unexpected behavior. I will need to run a test at home for this.
A few questions:
1. Do you have a Real Time Clock board attached?
2. Which of the compilation keys are activated from lines 81-83?:
//#define _DEBUG_
//#define _TEST_
//#define _USERTCMILLIS_

Reply 4 years ago

I just checked the code, and all three of the compilation keys are commented out. Thanks.


Reply 4 years ago

I cannot replicate this behavior. Now, something is definitely off with the Time library - are you using the libraries listed in the instructables page above? Some were forked by me and modified.