Arduino controlled Tomato, Chard and Zucchini watering for the balcony

Tomate1 Tomaten Mangold BewaesserungDropsArduino


Watering my balcony so I have fresh tomatoes every morning for breakfast, plus some zucchini and chard for dinner every week without having to take care about the plants every day. Survival of my plants during my vacations. I do have a power supply on the balcony, but the setup should just use 12v so i can run it on a used car battery later.

It should actively pump water, I do not have a water tap on the balcony and it should work “out in the wild” as well. Failsafe – shouldn’t die if it runs dry.


External 5.25” HDD housing with 12v power supply (From an old, defect hard drive)

Arduino Leonardo

HC Thor Fahrtregler (Fahrtregler)

(I use this one because I want to be able to use the System with a much larger fuel pump later as well)

RC Fuel Pump with 5v Motor e.g. (Zahnradpumpe)

(The fuel pump works perfect, but it quite noisy. Thus, i have replaced it with Tauchpumpe but be aware this one dies if it runs dry. The current code uses the moisture sensor under water to check if there is enough water in the supply. With the fuel pump, all of my neighbours asked me what that strange noise from my balcony is and speculated wildly – but no one was angry, it’s not that loud after all…)

If you connect the fuel pump, you have to heat the micro-drip cable with a lighter close to the end and then pull the end carefully to reduce the diameter. Cut at the minimum diameter so that it fits tightly on the pump pressurized exit.

For the Tauchpumpe, use some shrink tubing that just fits around the pump exit, insert the micro drip cable a centimeter into the pump and heat the shrink tube to firmly connect the components.

Micro Drip System (Micro Drip ) plus one row of cable.

One M-Ohm Resistor


  • Mount Arduino to hard drive housing (Screws/Plastic/…)
  • Program Arduino
  • Connect “Fahrtregler” with yellow and blue line to fuel pump, red and black to 12v power from the HDD power supply. Small brown control is GND on arduino, orange control line goes to a control pin, i used 9. The small red line is the receiver power line, leave it open, we don’t need it.
  • Connect arduino external power to 12v, and ground to HDD ground.
  • I have added a moisture measurement. Three wires, ground, plus, measure. Wiring plus -> 1MOhm resistor -> measurement cable and moisture detector-> Minus. For a moisture detector, you can use e.g two screws connected to wires and spaced by a dowel (just cut the closed end open and add the second screw from there). The screws should have a little space in between. Bury this. If the space in between filled by earth gets wet – lower resistance. Of course this is temperature dependant…. but it works fine for me without temperature compensation.
  • I connected the HDD diodes to display status information.


The current code just runs watering every minute, hour or two hours if the earth is too dry.

Best results for my tomatoes : Run the watering every hour and keep them constantly moist.

Use fresh tomato earth. If the tomatoes don’t grow steady – check for small animals. If none, add some fertilizer. If they still don’t grow fast – move to a more sunny location or do the sundance (Sundance).

// Bewaesserungsprogramm
// Wolfram Teetz <>

#include <Servo.h>

Servo MotorServo; // Liquid Motor servo object to control a servo

int x = 0; // counter for delays between single motor activations
int startval = 250;

long count; // 1/10s of seconds the ardu is running

long onTime1;
long offTime1;

long onTime2;
long offTime2;

int potpin = 0; // analog pin used to connect the potentiometer
int val; // variable to read the value from the analog pin

void cdelay(int d) // counting delay
count += d/100;
count %= 24*36000L;

boolean testTime() // test of we’re active at this time
// Assume watering starts in the evening
if ((digitalRead(1)==LOW)&&(count>=onTime1)&&(count<offTime1)) return true; // Pin 1 closed = water evening
if ((digitalRead(1)==LOW)&&(count>=onTime2)&&(count<offTime2)) return true; // Pin 1 closed = water morning
if (digitalRead(2)==LOW) return true; // Pin 2/3 closed = always water
if (digitalRead(3)==LOW) return true; // Pin 2/3 closed = always water
return false;

void setup()
//Serial.begin(9600); // S E R I A L
MotorServo.attach(9); // attaches the servo on pin 9 to the servo object
MotorServo.write(90); // sets the servo position according to (value between 0 and 180)
cdelay(50); // waits for the servo to get there
x = 0;
count = 0L; // in 1/10 of seconds

onTime1 = 0L; // start immediate (8PM)
offTime1 = 5L*3600L; // +0.5h (9PM)

onTime2 = 130L*3600L; // +13.0h (9AM)
offTime2 = 135L*3600L; // +13.5h (10AM)

// Control pins
// For meaning, see testTime function
pinMode(0, OUTPUT); // sets the digital pin 13 as output
digitalWrite(0, LOW);
for (int i=1; i<=3; i++) {
pinMode(i, INPUT);
pinMode(i, INPUT_PULLUP);

// LED’s
for (int i=4; i<=7; i++) {
pinMode(i, OUTPUT);
digitalWrite(5, LOW); // Led mass
digitalWrite(6, LOW); // Led mass

pinMode(11, OUTPUT); // sets voltage on pin 11 as input to measureing moisture
digitalWrite(11, HIGH); // input on analogue pin 0

void loop()
// Serial.println(val);
// Offen : 1023
// Relativ trockene Erde : 520
// Feuchte Erde : 250
// Pitschnass : 100
// Unter Wasser : 60

// Serial.print(“LOOP “); // S E R I A L

if (x<=0) {

//val = map(val, 0, 1023, 0, 179); // scale it to use it with the servo (value between 0 and 180)
val = analogRead(potpin); // 0–1000 -> SHOW : 0 to 20 CLICKS – 20 is DRY, 0 is WET. 10 Starts watering by default.

// Show value
int highval = val;
if (startval>val) highval=startval;

for (int vx=0; vx<highval; vx++)
if ((vx%2)==0) {
} else {
if (vx < startval) digitalWrite(4, HIGH);
else digitalWrite(4, LOW);
if (vx < val) digitalWrite(7, HIGH);
else digitalWrite(7, LOW);

if (x==0) delay(1000);

// There is water in the bucket
if (val<startval) {
digitalWrite(7, HIGH); // “currently watering” diode on
digitalWrite(4, LOW);
for (int vx=0; vx<44; vx++) // Slowly start
cdelay(100); // one step each 0.1 seconds
MotorServo.write(90+44); // run at ca. 6V, 12V supply
cdelay(30000); // run for 30 seconds
MotorServo.write(90); // turn off
digitalWrite(7, LOW); // “currently watering” diode off
digitalWrite(4, LOW);
x=10*60; // default
if (digitalRead(3)==LOW) x = -1; // constant watering
if (digitalRead(2)==LOW) x = 30*60; // one trigger per 30m
if (digitalRead(1)==LOW) x = 60*60; // one trigger per 1h
} else { // Of val>startval, Means there is no water in the bucket
x=10*60; // default
if (digitalRead(3)==LOW) x = -1; // constant watering
if (digitalRead(2)==LOW) x = 30*60; // one trigger per 30m
if (digitalRead(1)==LOW) x = 60*60; // one trigger per 1h
} // else of val>startval

} // if x==0 (active interval, not sleep interval)

if (x>0) { // sleep interval, count down
x = x – 1;

// Wait


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s