Potted plant watering system. (Involves water pumps.)

Mr Google hasn't been too helpful, so I thought I would ask here.

Although I am still working on a project, the next one is raising its head.

Watering plants. Not rocket science, I know.

My "situation" is that I have a "reserve" of water in a tank and I have 5 plants/pots. Different sizes/different needs for amount of water per pot.

My basic idea was to have a daily/set period to water them.

Call it daily only for simplicity.

Each day, the unit checks there is water in the tank, turns on a pump, opens solenoid 1 for x seconds, repeats for 2 to 5 then shuts down.

It doesn't need to be "high pressure" water, and a valve would be included so the water line could "vent" back into the tank if the line pressure was too high.

There would also be a "rain detector" so if it is "bucketing down" it doesn't water the plants.

When the water level gets below a certain point, it lights an LED and I know it is time to fill the tank again.

Nice. Did you select the parts (pump, sensors etc)?

No not yet.

I am trying (yeah, right) to keep it simple.

Basically there will be a pump; 5 (unless I get more pots) solenoids; a vent valve and a rain sensor.
Oh, sorry: And an LED.

Sensors? You mean for the rain detection? No not yet. Don't know how to detect rain electronically yet.

You mean for the rain detection?

If this is for outdoors, then why not use a sprinkler-kind-of-system powered on a timer?

The pots are "local" to me, and though are out doors, are not in a garden as such.

They are undercover and there is no way I can use sprinklers to water them. Too wasteful.

This way I am using the water I gather (GREY water as it is called) and using it to water the plants if/when they need it.

Reading another thread, maybe instead of "rain detection" I put sensors in the pots with detect the moisture of the soil.
Basically two nails. One to +5v, and the other an analogue input.

I'm still scoping the idea.

Previous similar post for reading.

https://www.google.com/search?hl=en&as_q=hydroponics&as_epq=&as_oq=&as_eq=&as_nlo=&as_nhi=&lr=&cr=&as_qdr=all&as_sitesearch=http%3A%2F%2Farduino.cc%2Fforum&as_occt=any&safe=off&tbs=&as_filetype=&as_rights=

Thanks.

I didn't think of "hydroponics" for the search.

Ok, I am trying to optimise the code loops.

Here is what I am wanting to do:

I have 5 outputs, and they are called solenoid_1 - 5.

I have read the 5 values in for their run times, and want to make a loop to turn them on/off by doing a

for i = 1 to 5
digitalwrite(solenoid_i,HIGH)
next

kind of thing.

or the real code:

void Solenoid()
{
    //
    for (int i=0;i<5;i++)
    {
        //  Get time value for i
        //  Turn on soldenoid i
        //  Wait the specified time
        //  Check sensor for input
        //  Abort if active
        //  Turn off solenoid i
        digitalwrite(solenoid_
    }
}

But I am stumped how to translate the "i" into the command.

I know I have been through this similar thing with printing things on the display with the sprintf(), but don't know if that works with this situation.

Please.

Check out arrays in the learning section: http://arduino.cc/en/Tutorial/Array.

BTW, you probably could have chosen a better title, such as 'Potted plant watering system', since 'Pot plant watering system' says to me the growing of marijuana. Even if that is what is in your potted plants, it may have limited the responses.

Thanks.

I've looked and thought I had it.

This is driving me nuts.

Ok, so I make it read something like:
digitalWrite(solenoid_,LOW);
and it should work.
SHOULD!
This is my code now:
```
/
   Automamtic plant pot watering system.
   
   Concept:
   Daily or weekly it waters plant pots.
   Sensors detect if the saucer under the pot is
   full or not, and stop the pump when it detects
   the water depth.
   There is also a "timeout" period per pot incase
   there is a problem with filling the pot.
   
*/

#include <arduino.h>
#include <Wire.h>
#include <stdio.h>
#include "DS1307_1.h"
#include "alarm_clock.h"

//  These are the sensors for each pot and the main reserve
#define sensor_Main 14
#define sensor_1 15
#define sensor_2 16
#define sensor_3 17
#define sensor_4 18
#define sensor_5 19

//  These are the pins to drive each solenoid for each pot.
//  They are OR'd together to turn on the motor/pump.
int solenoin[5];
#define solenoid_1 0
#define solenoid_2 1
#define solenoid_3 2
#define solenoid_4 3
#define solenoid_5 4

#define LED 5
#define btn_1 6

//  Set time for daily run.
//int run_time_dow 2;
int run_time_hr = 12;
int run_time_mn = 00;
//int run_time_sec = 00;

//  Array for each pot's fill time
int sol_run_time[5];
//  Array for the values for the system to look for to indicate "full"
int level[6];

// RTC stuff
int rtc[7];
DS1307 RTC=DS1307();             // Create RTC object

//#define setRTC
#ifdef setRTC
// Set/init RTC
 RTC.stop();
 RTC.set(DS1307_SEC,0);
 RTC.set(DS1307_MIN,50);
 RTC.set(DS1307_HR,0);
 RTC.set(DS1307_DOW,3);           // value from 1 to 7. User define whether 1 is sun or mon.
 RTC.set(DS1307_DATE,10);
 RTC.set(DS1307_MTH,06);
 RTC.set(DS1307_YR,12);
 RTC.start();
#endif

void setup()
{
   //
   pinMode(sensor_Main,INPUT);
   pinMode(sensor_1,INPUT);
   pinMode(sensor_2,INPUT);
   pinMode(sensor_3,INPUT);
   pinMode(sensor_4,INPUT);
   pinMode(sensor_5,INPUT);

pinMode(btn_1,INPUT);    
   
   pinMode(solenoid_1,OUTPUT);
   pinMode(solenoid_2,OUTPUT);
   pinMode(solenoid_3,OUTPUT);
   pinMode(solenoid_4,OUTPUT);
   pinMode(solenoid_5,OUTPUT);

pinMode(LED,OUTPUT);
   
   digitalWrite(LED,LOW);
   digitalWrite(solenoid_1,LOW);
   digitalWrite(solenoid_2,LOW);
   digitalWrite(solenoid_3,LOW);
   digitalWrite(solenoid_4,LOW);
   digitalWrite(solenoid_5,LOW);

// Time in seconds each pot takes to be "filled".
   //  All values to be set.
   sol_run_time[1] = 20;
   sol_run_time[2] = 20;
   sol_run_time[3] = 20;
   sol_run_time[4] = 20;
   sol_run_time[5] = 20;
   
   //  All values to be set.
   level[1] = 20;
   level[2] = 20;
   level[3] = 20;
   level[4] = 20;
   level[5] = 20;
   level[6] = 20;      //  This will be the main reserve, and when it is empty rather than full.

}

void loop()
{
   //  Get time from RTC.
   int rtc[7];
   RTC.get(rtc,true);
   int flag;
   //  Have time, check what time it is.
   if (btn_1 == HIGH)
   {
       Solenoid();
   }
   //
   if (rtc[2] == run_time_hr)
   {
       if (rtc[1] == run_time_mn)
       {
           if (flag == 0)
           {
               //
               Solenoid();
               flag = 1;
           }
       }
   }
   
}

//*************************************************************************************************

void Solenoid()
{
   int i;
   for (i=0;i<5;i++)
   {
       //  Get time value for i
       //  Turn on soldenoid i
       //  Wait the specified time
       //  Check sensor for input
       //  Abort if active
       //  Turn off solenoid i
       digitalWrite(solenoid_[i],HIGH);
       sensor_delay(i);
   }
}

//*************************************************************************************************

int sensor_delay(int x)
{
   //  Read threashold values for all sensors.
   //  i is current one, but Main gets read every time anyway.
   int i = x;
   int reading;
   int TTG;
   int time_up;
   TTG = sol_run_time[i];
   time_up = timer(TTG);
   if (time_up > 0)
   {
       reading = digitalRead(sensor_Main);
       if (reading > level[6])      //  Main reserve is good.
       {
           reading = digitalRead(sesnor_[i]);
           if (reading > level[i])
           {
               //  Water level reached.  Stop pumping and go to next plant.
               TTG = 0;
               digitalWrite(solenoid_[i],LOW);
           }
           //  This is if the plant's water is already good
       }
       //  This is if the main level is not good.
   }
   // time_up = 0
}
return;
   
//*************************************************************************************************
   
int timer(int foo)
{
   static int counter;
   counter = foo;
   int rtc[7];
   int min_flag;
   RTC.get(rtc,true);
       if (counter >0)
       {
          if (min_flag != rtc[1])
          {
              min_flag = rtc[1];
              counter = counter - 1;
          }
       }
   return counter;
}

//**************************************************************************************************
* *It given me errors.* *What really annoys/upsets me is I am still missing what is going on.* *I can be writing away and it complies. Haven't even got to testing it yet. I do some small changes, and it just falls over in a big heap.* *Errors everywhere.* *V1.cpp: In function 'void Solenoid()':* *V1:160: error: 'solenoid_' was not declared in this scope* *V1.cpp: In function 'int sensor_delay(int)':* *V1:182: error: 'sesnor_' was not declared in this scope* *V1:187: error: 'solenoid_' was not declared in this scope* *V1.cpp: At global scope:* *V1:195: error: expected unqualified-id before 'return'* *Ok:* *'solenoid_ was not declared in this scope.'* *Yeah, because I changed it from solenoid_[1] to solenoid_* _*See this PART of the code referred below:*_ _*_
void loop() {
 // loop from the lowest pin to the highest:
 for (int thisPin = 0; thisPin < pinCount; thisPin++) {
   // turn the pin on:
   digitalWrite(ledPins[thisPin], HIGH);  
   delay(timer);                  
   // turn the pin off:
   digitalWrite(ledPins[thisPin], LOW);

```
Here, [thisPin] is used instead of the [ i ] which I am using in the case. (Spaces optional and added only to make visible.)
I hope I have obeyed the rules, but it doesn't seem to like me.

There is a world of difference between

         digitalWrite(solenoid_[i],HIGH);

and

    digitalWrite(ledPins[thisPin], HIGH);

The compiler converts names to addresses. Then, it discards the names. There is nothing in the hex file that gets uploaded to the Arduino that is called solenoid_ anything.

You can create an array of pins that the solenoids are attached to (solenoidPins[]), similar to ledPins[] in the code that works, and then use

         digitalWrite(solenoidPins[i],HIGH);

Repeating what I suggested in a prior similar thread:

Consider raising the captured water container so you can use gravity feed. Then you can dispense with level detection and the pump.

PaulS:
There is a world of difference between

         digitalWrite(solenoid_[i],HIGH);

and

    digitalWrite(ledPins[thisPin], HIGH);

The compiler converts names to addresses. Then, it discards the names. There is nothing in the hex file that gets uploaded to the Arduino that is called solenoid_ anything.

You can create an array of pins that the solenoids are attached to (solenoidPins[]), similar to ledPins[] in the code that works, and then use

         digitalWrite(solenoidPins[i],HIGH);

So this _ character makes a big difference?

I was starting to think along those lines, but had not got around to checking myself on it.

Thanks for the info.

WRT lifting the water and using gravity:
Well, nice idea, but it is a LOT of water. Probably 100 Litres or more. That is a lot of weight to eleveate. That means making a support for the container and all that kind of stufff.

Thanks, but for now I am wanting to concentrate on the programming side of things and not have to get too muchh into the mechanical side of building "structures" to support 100KG of water above a certain height.

Well,

"I give up".

Here is what I did:

//  Array for each pot's fill time
int sol_run_time[5];
//  Array for the values for the system to look for to indicate "full"
int level[6];
//  Solenoid array
int solenoid[5];
//  Sensor array
int sensor[6];


//  These are the sensors for each pot and the main reserve
#define sensor[0] 14
#define sensor[1] 15
#define sensor[2] 16
#define sensor[3] 17
#define sensor[4] 18
#define sensor[5] 19



//  These are the pins to drive each solenoid for each pot.
//  They are OR'd together to turn on the motor/pump.
//int solenoid[5];
#define solenoid[1] 0
#define solenoid[2] 1
#define solenoid[3] 2
#define solenoid[4] 3
#define solenoid[5] 4



#define LED 5
#define btn_1 6

//  Set time for daily run.
//int run_time_dow 2;
int run_time_hr = 12;
int run_time_mn = 00;
//int run_time_sec = 00;

// RTC stuff
int rtc[7];
DS1307 RTC=DS1307();             // Create RTC object


//#define setRTC
#ifdef setRTC
// Set/init RTC
  RTC.stop();
  RTC.set(DS1307_SEC,0);
  RTC.set(DS1307_MIN,50);
  RTC.set(DS1307_HR,0);
  RTC.set(DS1307_DOW,3);           // value from 1 to 7. User define whether 1 is sun or mon.
  RTC.set(DS1307_DATE,10);
  RTC.set(DS1307_MTH,06);
  RTC.set(DS1307_YR,12);
  RTC.start();
#endif


void setup()
{
    //
    pinMode(sensor[0],INPUT);
    pinMode(sensor[1],INPUT);
    pinMode(sensor[2],INPUT);
    pinMode(sensor[3],INPUT);
    pinMode(sensor[4],INPUT);
    pinMode(sensor[5],INPUT);

The rest is not included.

Still fails.

V1.cpp: In function 'void setup()':
V1:83: error: expected primary-expression before '[' token
V1:84: error: expected primary-expression before '[' token
V1:85: error: expected primary-expression before '[' token
V1:86: error: expected primary-expression before '[' token

So I am really missing something.

Hang on!

Ok, "Pins" is missing in the text.

Changing now.

Eurika!

Is this it?

/*
    Automamtic plant pot watering system.
    
    Concept:
    Daily or weekly it waters plant pots.
    Sensors detect if the saucer under the pot is
    full or not, and stop the pump when it detects
    the water depth.
    There is also a "timeout" period per pot incase
    there is a problem with filling the pot.
    
*/

#include <arduino.h>
#include <Wire.h>
#include <stdio.h>
#include "DS1307_1.h" 
#include "alarm_clock.h"


//  Array for each pot's fill time
int sol_run_time[5];
//  Array for the values for the system to look for to indicate "full"
int level[6];
//  Solenoid array
int solenoid[5];
//  Sensor array
int sensor[6];


//  These are the sensors for each pot and the main reserve
#define sensorPins[0] 14
#define sensorPins[1] 15
#define sensorPins[2] 16
#define sensorPins[3] 17
#define sensorPins[4] 18
#define sensorPins[5] 19



//  These are the pins to drive each solenoid for each pot.
//  They are OR'd together to turn on the motor/pump.
//int solenoid[5];
#define solenoidPins[1] 0
#define solenoidPins[2] 1
#define solenoidPins[3] 2
#define solenoidPins[4] 3
#define solenoidPins[5] 4



#define LED 5
#define btn_1 6

//  Set time for daily run.
//int run_time_dow 2;
int run_time_hr = 12;
int run_time_mn = 00;
//int run_time_sec = 00;

// RTC stuff
int rtc[7];
DS1307 RTC=DS1307();             // Create RTC object


//#define setRTC
#ifdef setRTC
// Set/init RTC
  RTC.stop();
  RTC.set(DS1307_SEC,0);
  RTC.set(DS1307_MIN,50);
  RTC.set(DS1307_HR,0);
  RTC.set(DS1307_DOW,3);           // value from 1 to 7. User define whether 1 is sun or mon.
  RTC.set(DS1307_DATE,10);
  RTC.set(DS1307_MTH,06);
  RTC.set(DS1307_YR,12);
  RTC.start();
#endif


void setup()
{
    //
    pinMode(sensor[0],INPUT);
    pinMode(sensor[1],INPUT);
    pinMode(sensor[2],INPUT);
    pinMode(sensor[3],INPUT);
    pinMode(sensor[4],INPUT);
    pinMode(sensor[5],INPUT);

    pinMode(btn_1,INPUT);    
    
    pinMode(solenoid[1],OUTPUT);
    pinMode(solenoid[2],OUTPUT);
    pinMode(solenoid[3],OUTPUT);
    pinMode(solenoid[4],OUTPUT);
    pinMode(solenoid[5],OUTPUT);

    pinMode(LED,OUTPUT);
    
    digitalWrite(LED,LOW);
    digitalWrite(solenoid[1],LOW);
    digitalWrite(solenoid[2],LOW);
    digitalWrite(solenoid[3],LOW);
    digitalWrite(solenoid[4],LOW);
    digitalWrite(solenoid[5],LOW);

    // Time in seconds each pot takes to be "filled".
    //  All values to be set.
    sol_run_time[1] = 20;
    sol_run_time[2] = 20;
    sol_run_time[3] = 20;
    sol_run_time[4] = 20;
    sol_run_time[5] = 20;
    
    //  All values to be set.
    level[1] = 20;
    level[2] = 20;
    level[3] = 20;
    level[4] = 20;
    level[5] = 20;
    level[6] = 20;      //  This will be the main reserve, and when it is empty rather than full.

}

void loop()
{
    //  Get time from RTC.
    int rtc[7];
    RTC.get(rtc,true);
    int flag;
    //  Have time, check what time it is.
    if (btn_1 == HIGH)
    {
        Solenoid();
    }
    //
    if (rtc[2] == run_time_hr)
    {
        if (rtc[1] == run_time_mn)
        {
            if (flag == 0)
            {
                //
                Solenoid();
                flag = 1;
            }
        }
    }
    
}

//*************************************************************************************************

void Solenoid()
{
    int i;
    for (i=0;i<5;i++)
    {
        //  Get time value for i
        //  Turn on soldenoid i
        //  Wait the specified time
        //  Check sensor for input
        //  Abort if active
        //  Turn off solenoid i
        digitalWrite(solenoid[i],HIGH);
        sensor_delay(i);
    }
}

//*************************************************************************************************

int sensor_delay(int x)
{
    //  Read threashold values for all sensors.
    //  i is current one, but Main gets read every time anyway.
    int i = x;
    int reading;
    int TTG;
    int time_up;
    TTG = sol_run_time[i];
    time_up = timer(TTG);
    if (time_up > 0)
    {
        reading = digitalRead(sensor[0]);
        if (reading > level[6])      //  Main reserve is good.
        {
            reading = digitalRead(sensor[i]);
            if (reading > level[i])
            {
                //  Water level reached.  Stop pumping and go to next plant.
                TTG = 0;
                digitalWrite(solenoid[i],LOW);
            }
            //  This is if the plant's water is already good
        }
        //  This is if the main level is not good.
    }
    // time_up = 0
}
//return 0;
    
//*************************************************************************************************
    
int timer(int foo)
{
    static int counter;
    counter = foo;
    int rtc[7];
    int min_flag;
    RTC.get(rtc,true);
        if (counter >0)
        {
           if (min_flag != rtc[1])
           {
               min_flag = rtc[1];
               counter = counter - 1;
           }
        }
    return counter;
}

//*************************************************************************************************

It complies ok.

It complies ok.

I'm guessing it doesn't work though.

pinMode(sensor[0],INPUT);

All of "sensor" was initialised to zero by the compiler, so "sensor [0]", "sensor [1]" all have the value zero, so you're setting the pinMode of pin zero multiple times.

#define sensorPins[0] 14
#define sensorPins[1] 15

I've been programming in C a long time, and I've never seen that construct before.

Did you mean const byte sensorPins [] = { 14, 15 etc ?

int solenoid[5];
    pinMode(solenoid[5],OUTPUT);

You don't have a "solenoid[5]" to set the pinMode of.

Just to throw a spanner in the works (no, not Graham Taylor), how about some kind of feedback from the soil?

You can detect how wet the soil is to know if it's been raining or not, and even if the plants need watering - no need for "timing" then, you can make it intelligent.

There's 2 normal ways of detecting soil moisture content:

  1. Resistance.

This involves passing a current through the soil and measuring the voltage drop - essentially using the soil as one half of a potential divider. It is incredibly simple to do, but you will end up corroding your electrodes in no time.

  1. Capacitance.

This is the better way of doing it. Two probes in the ground, both insulated, and close together. As the soil moisture content changes, so does the capacitance between the two electrodes. This is a much harder way of sensing the moisture content as you have to detect the capacitance not the resistance, but the electrodes can last for many many years (decades, millennia) longer as they aren't in direct contact with the soil.

What kind of pump, solenoids and valves are you gonna use? I have made something similar to water my tomato plants. It's really simple; a 10 l bucket of water, a cheap aquarium pump from Sparkfun, and a Uno set up to start the pump for about one second each 4 hours. I'm running a silicon hose from the pump to the potted plants at the moment. I've cut a hole halfway on the hose where it passes plant no 1, then the end of the hose goes to the second plant. If I had some valves I could get better control of the amount of water for each plant

Morning folks.

It is 07:13 here. Day kind of just starting.

AWOL:
Yes, I am probably not making sense. However as I have said I know jack about this type of code. I look at what is and try to work out what does what and make it do what I want.

Your question/suggestion for what I want is probably true, but I have NO knowledge of the structure and vocabulary.

I shall have to research that "command" and see if that is what I want to do.

Yes, I probably don't have all the assignments worked out. The code was constructed "on the fly" and I kind of just "cut/paste" the lines a few times and made the numbers sequencial.

Majenko:
The sensors.
I haven't got that far yet. I have defined their inputs and done an "example" idea of how their values change indicating the different "staes". Either with or without water detected.

As to moisure content, etc. Well the idea is that the sensors will simply detect the water levevl in the saucer that the pot is sitting. Nothing too elaborate.

I resolved that moisture would/may not be good because if I am watering the pots and the water isn't detected soon enough they will "over fill". Although I have timeout values I am opting for a simple level detection.

It was mentioned about corrosion on the "sensors". So someone suggested I use gavanised nails. They won't rust.

Ferryp:
Again: The types of solenoids/valves are still future work. I am working on the program for now.
Though probably something like what you are suggesting with a cheap pump.

The only difference is that the size and ammount of water each plant/pot needs is too different to use
ONE hose with holes. Thus the solenoids.

As this is only my firt full sketch I am not wanting to get too far ahead of myself by looking at the hardware
until I get the software working.

OK, some vocab.

#define sensorPins[0] 14

(this is a macro definition)
Here, I assume you're trying to tell your sketch that there's an array called "sensorPins", and element zero has the value 14.
At some point, I assume, you're going to set the pinMode of pin 14 to be INPUT.
So, I search your sketch (as you could have done) for the string "sensorPins", but apart from the five other similar macro definitions, there are no occurrences of the string "sensorPins", so you never use it anywhere.

Instead, you confuse the pin a sensor is attached to with the value you're eventually going to read from that sensor.

//  Sensor array
int sensor[6];

and

   pinMode(sensor[0],INPUT);
    pinMode(sensor[1],INPUT);
    pinMode(sensor[2],INPUT); // etc

But you haven't given the elements of the array "sensor" any values, so, because "sensor" has global scope, the compiler has kindly assigned the value zero to all of its elements. So, you're setting the pinMode of pin zero to be INPUT six times.

Similar, but subtly more dangerous situation with the solenoids, you have macros for the pins but never use them.
However:int solenoid[5];

  pinMode(solenoid[1],OUTPUT);
    pinMode(solenoid[2],OUTPUT);
    pinMode(solenoid[3],OUTPUT);
    pinMode(solenoid[4],OUTPUT);
    pinMode(solenoid[5],OUTPUT);

The array "solenoid" has five elements with subscripts 0, 1, 2, 3 and 4, and again the compiler has helpfully set all the elements that it knows about to zero.
But then, you invent a sixth element (no doubt starring Bruce Willis), retrieve it value (do you know what it is? I don't), and set the corresponding pin's mode to be an OUTPUT.

 sol_run_time[1] = 20;
    sol_run_time[2] = 20;
    sol_run_time[3] = 20;
    sol_run_time[4] = 20;
    sol_run_time[5] = 20;

Ditto.

//#define setRTC
#ifdef setRTC

Don't even think about removing the // comment marks off that macro definition.

int i = x;
    int reading;
    int TTG;
    int time_up;
    TTG = sol_run_time[i];
    time_up = timer(TTG);

is bad for the eyes.

int i = x;
    int TTG = sol_run_time[i];
    int time_up = timer(TTG);

is shorter and easier on the eyes.