Automated Planter Watering

5A820481-9EC4-4293-AE3F-00E8DC0DEB36_1_105_c.jpeg

 3 months into the pandemic, the weather started to warm up.  Looking to stay busy (and with plenty of motivation from my mother), I thought I’d give tomato plants a try.  Living in Boston, any ground level planting space was basically out of the question so I set out to grow my first batch of porch tomatoes! 

After a few weeks, I convinced myself they weren’t getting enough sun on my covered porch, so I devised a hanging system so I could sling the plants over the railing of the porch.  My solution was fast and dirty, but got the job done and used only things I had laying around in my miscellaneous parts bin.

DC78787C-4109-4CBB-9778-AF265548F9B4_1_105_c.jpeg

I drilled two holes on opposite sides of the pots, passed a threaded eye hooks through each of the holes with a fender washer stiffening each side and tightened down with a lock nut.  I passed a length of rope through each side, tied off a stop knot then wrapped the other end over the railing and hooked it back onto the pot using a 2 hook turnbuckle and let it hang (that was confusing, pictures below).  It honestly worked remarkably well for how quickly a threw it together!  

Now comes the real problem.  What my mother failed to tell me, was how much water tomatoes need in the heat of the summer and if you also don’t know let me tell you now, a lot.  On days I needed to be in the office for work, I would come home to wilted plants, even if I fully saturated them before leaving.

Enter problem, how can I water my plants when I’m not home?  Now I am sure there are off the shelf solutions, but why do that when I could spend more money and time building one myself!  So I pulled out a spare Arduino Mega and formulated a plan.  Thinking about the problem I knew I needed a couple of things.

  1. It needs to be closed loop. I want my solution to be smart enough to know that if it’s cloudy, my plants won’t need as much water. I found these nifty capacitive soil sensors on amazon that I could use to measure the moisture level of the soil. Setting a moisture level for watering would allow the system to only water the plant when it needs it.

  2. It needs to be able to monitor water levels in the reservoir, as to not run the pump dry.


E1D2E036-BEF2-44A0-90B6-A1A22B7E9245_1_105_c.jpeg

I did some quick sketches to map out what the circuit would look like.  Essentially, the soil sensor will feed a mapped 0-100% soil moisture value to the microcontroller.  Based on those readings, the microcontroller will flip a relay and power the pump to water the plant.  Easy enough.  I bench tested a quick mock up with success and later that night whipped up what I think is one of my jankiest prototypes to date (but hey it worked).

I put a submersible pump in a gallon container I had around and strapped the backplane I printed  directly onto the container filled with water.  I also included a water level sensor in the container to avoid running the pump if the reservoir was dry.

I ran tubing from the pump to the planter designed & printed some basic spikes I could use to guide the tubing around the diameter.  I drilled some 1/16” holes in the tube every few inches which helped get a more even water distribution around the pot.

I installed this setup for both my tomato plants and let it run for a few days, filling the container up with water before leaving for work and coming home to happy plants!

Even though it worked, there were definitely some issues I wanted to solve for my final build.  The first problem was the pump.  The pumps I originally sourced only had an outlet port and needed to be submersed to run which limited the distance I could keep the microcontroller and relay away from the water reservoir and how big of a tank I could use.  The other issue was that the pump required 12v but I only needed 5v for the micro controller.  In the prototype setup I had 2 different power supplies powering each.  I knew I could solve this in the final build with an inline voltage regulator. 

819883CE-B257-41F5-996F-6EB5DC55BCE7_1_105_c.jpeg

I found a new pump with inlet and outlet ports and whipped up a box to mount everything in SolidWorks.  With it printed, I assembled everything inside (find the schematics, code, STL’s, and assembly instructions below). 

D2953EEF-1197-4E43-A2EE-58D66C438598_1_105_c.jpeg

In the final design I included expandable ports for more moisture sensors (my thinking here was to include multiple sensors in one pot to get a better average moisture reading in multiple areas).  I also added 2 status LEDs, yellow to tell you that the reservoir was empty but the plants don’t currently need water, and red which lights up in the case where the reservoir  is empty but the plants do currently need water.

Overall I’m super happy with how it came out!  There are definitely things I’d like to add in the future like

  • Button that overrides control loop and waters anyway

  • Basic display that gives information on last water time and current moisture level

  • Green LED for normal operating state

  • Rewire components on perf board for a cleaner implementation


Build Instructions

Bill of Materials

  • 1x Arduino Mini (link)

  • 1x Adjustable buck converter (link)

  • 1x Diaphragm Pump (link)

  • 1x 12v Relay

  • 4x M3x20 Socket Head Cap Screws

  • 4x M3x5 Socket Head Cap Screws

  • 1x Red LED

  • 1x Yellow LED

  • 1x Capacitive Soil Sensor (link)

  • 1x Housing

  • 1x Housing Lid

Design Files

STLs and design files can be found here. My parts were printed on a Mark Two from Markforged but these should be compatible with any FDM 3D printer.

Schematics

The design revolves around an Arduino Mini microcontroller, 12v relay, and the pump.

Auto-Water_bb.jpg

Code

This code should be compatible with any Arduino board and can be pasted directly into the arduino IDE. Apologies for any abhorrent code practices, remember, I’m a mechanical engineer :)

    
//Status LED definiton
#define yLED 1
#define rLED 2

//Relay Definition
#define relay 0

//Soil Sensor Setup
int AirValue = 800;               //Calibrated Soil Sensor to Air
int WaterValue = 325;             //Calibrated Soil Sensor to Water
int soilMoistureValue = 0;              //Set Moisture Value to 0 to start
int soilmoisturepercent = 0;            //Set Moisture Percent Value to 0 to start

//Water Routine Setup
unsigned long start_time = 0;                    //Set start time to 0
unsigned long WaterVolume = 2200;                //2200mL
unsigned long controller_delay = 30000;        //30 minute system controller delay
unsigned long WaterRunTime = 0;                  //Set runtime to 0
unsigned long WaterRate =.0135;                  //ml per second 
  
//Water Sensor Setup
//const int water_threshold = 350;        //Water Detection Threshold
//int water_level = 0;

//Setup timing
unsigned long end_time = 0;
unsigned long run_time = 0;
unsigned long ref_time = 0;
unsigned long elapsed_time = 0;
int elapsed;


void setup() {

  //Setup Water Equation
  WaterRunTime = 10000;
  

  //Setup Relay
  pinMode(relay, OUTPUT);           //Set Relay as Output
  digitalWrite(relay,LOW);          //Start with water pump off
  
  //Setup Status LED
  pinMode(rLED, OUTPUT);           //Set LED as digital output
  pinMode(yLED, OUTPUT);           //Set LED as digital output
  digitalWrite(rLED,LOW);          //Start with red LED off
  digitalWrite(yLED,LOW);          //Start with yellow LED off
  
  
  //Setup Serial Connection
  Serial.begin(9600);               //Initialize serial connection to 9600
 

}

void loop() {
 ref_time = millis();
 elapsed = 0;
 soilMoistureValue = analogRead(A0);                                              //Read Soil Moisture
 soilmoisturepercent = map(soilMoistureValue, AirValue, WaterValue, 0, 100);      //Map to percentage                                                
 elapsed_time = ref_time - end_time;
 Serial.println(elapsed_time);
 

 if(elapsed_time > controller_delay){
  elapsed = 1;
 }
 

 if(soilmoisturepercent < 65 && elapsed == 1){                               
      start_time = millis();                                //Get Start Time
      run_time = 0;                                         //Reset Run Time
      digitalWrite(relay, HIGH);                            //Turn water on
      digitalWrite(yLED, HIGH);
      
      while(run_time < WaterRunTime){                       //While the time the pump has been running for less than WaterRunTimes
           run_time = millis() - start_time;                 //Calculte time since motor came on
        }
      digitalWrite(relay, LOW);                            //Turn water off after complete cycle
      digitalWrite(yLED, LOW);
      end_time = millis();
      }
      
if(soilmoisturepercent < 65 && water_level < water_threshold){
      digitalWrite(Y_LED, LOW);
      digitalWrite(R_LED, LOW);                            //Critical out of water LED ON
   }
    
if(soilmoisturepercent > 65 && water_level < water_threshold){
     digitalWrite(R_LED, LOW);
     digitalWrite(Y_LED, HIGH);
 }

if(soilmoisturepercent > 65 && water_level > water_threshold){
     digitalWrite(R_LED, LOW);
     digitalWrite(Y_LED, LOW);
}
}