Automated watering system of vegetable garden - solar powered

Hi guys/ladies,

Last summer i started a project in which i would like to water my 150m2 (a stretch of 6 meter x 25 meter vegetable garden automatically.

My general idea is the following: The vegetable garden is split up into 4 stations. These stations control 16-valves individually basically turning 1 valve after the other on thereby watering around 2 m2 at the time.
Last month you creative forum members have helped me solve my issue with the 16-way valves so it looks like this concept of the stations is working now. Since the tips were sooo great i would assume that your can also improve my main controller.

What about the controller. The controller is basically an Arduino Mega which is located against my greenhouse. This greenhouse has a couple of nice features built in... such as a groundwaterwell (14 meters deep, dug myself), 3 30 watt solar panels and 3 batteries (100 kAh each). These batteries are partly used in my automated greenhouse on hydroponics (which is running successfully for a couple of years) but there is some room for more automation left.

The idea of this controller is the following. It will basically sleep and is just checking once every hour how much light there is out there. In the dark it would activate once per day. Basically when activated it would power Station 1 and at the same time start pumping water from the waterreservoir next to the greenhouse. After a specific period it would switch to watering Station 2 and turning on pump 2. Idem for Station 3 and 4.
What makes it more interesting is that the reservoir is around 200 liters and i would say a general Wateringday would look like the distribution of around 2000 liters of water. Therefore i build in 2 water level float switches to detect the water level and once the reservoir is not full it would already start to pump ground water into the reservoir to avoid that it gets empty. If 'empty' it should temporarely stop the system. Fill up the reservoir completely and resume the remaining time. Also worth mentioning that the Arduino must be in sleep mode in the time that it is not active because else even an arduino is able to drain a 100kAh battery completely (in a few days)

As attachment a rough overview of the different components and connections. Furthermore some insights into the controller and the code.
Any suggestions what to improve? (i have my doubts about the code around the light sensor and maybe you have suggestions how to resume or deal with an empty reservoir?)

#define onderstesensor 9
#define bovenstesensor 8
#define relaygrondwater 11
#define lichtsensor 12

#define box1 41
#define box2 42
#define box3 43
#define box4 44

int box1time = 200;
int box2time = 200;
int box3time = 200;
int box4time = 200;

bool emptyreservoir = false;
bool volreservoir = false;
bool malfunction = false;

void setup() {
  Serial.begin(9600);
  
  pinMode(onderstesensor, INPUT_PULLUP);
  pinMode(bovenstesensor, INPUT_PULLUP);
  pinMode(relaygrondwater, OUTPUT);
  pinMode(lichtsensor, INPUT_PULLUP);

  pinMode(box1, OUTPUT);
  pinMode(box2, OUTPUT);
  pinMode(box3, OUTPUT);
  pinMode(box4, OUTPUT);

  digitalWrite(relaygrondwater, HIGH);
  digitalWrite(box1, HIGH);
  digitalWrite(box2, HIGH);
  digitalWrite(box3, HIGH);
  digitalWrite(box4, HIGH);

  //SETUP WATCHDOG TIMER
  WDTCSR = (24);//change enable and WDE - also resets
  WDTCSR = (33);//prescalers only - get rid of the WDE and WDCE bit
  WDTCSR |= (1<<6);//enable interrupt mode

  //Disable ADC - don't forget to flip back after waking up if using ADC in your application ADCSRA |= (1 << 7);
  ADCSRA &= ~(1 << 7);
  
  //ENABLE SLEEP - this enables the sleep mode
  SMCR |= (1 << 2); //power down mode
  SMCR |= 1;//enable sleep
}

void loop() {
  // put your main code here, to run repeatedly:
  int licht = digitalRead(lichtsensor);
  if (licht == 1){
    Serial.println("it is dark");
  /in this scenario we would like to water the plants..
  /*
   * 
   * 
   */

  //first check whether tank is full and turn on groundwaterpump
  
  //check waterlevel
  //scenario 1: tank full
  if(digitalRead(bovenstesensor) == LOW)
    { 
      //check both sensors
      if (digitalRead(onderstesensor) == HIGH)
        { 
            Serial.println("waterlevels unrealistic");
            //waterniveau's onrealistisch
        }
       // confirmed tank full:
      else if (digitalRead(onderstesensor) == LOW)
        {
            Serial.println("waterlevel high");
            volreservoir = true;
            //tank full ... up to the next step
            
        }
       else
        {
            Serial.println("error 404.. cannot detect sensors");
            //error, sensors niet gedetecteerd

        }
    }
    //scenario 2: tank half full
    else if (digitalRead(bovenstesensor) == HIGH)
    {
        //check bottom sensor
        if (digitalRead(onderstesensor) == LOW)
        {
          //tank half full confirmed
          Serial.println("tank half full");
          
        }
        else if (digitalRead(onderstesensor) == HIGH)
        //tank empty
        {
          Serial.println("tank empty, action required");
          //tank empty
          //change status of emptyreservoir
          emptyreservoir = true;
        }
        else
        {
           Serial.println("error 404.. cannot detect sensors");
           //sensors niet gedetecteerd
        }
    }
    else 
    {
      Serial.println("error 404.. cannot detect sensors");
      //sensors niet gedetecteerd
    }

  //wenn waterlevels are too low, fill water to upper waterlevel
  
  if(volreservoir == false){
    Serial.println("entered fill loop");
    //for 30 minutes run procedure... 
    int j = 0;
    for (int i = 0; i <= 300; i++) {
      digitalWrite(relaygrondwater, LOW);
      j = j+1;
      Serial.println("j teller: " +j);
      delay(10000);

      //immediately shut off loop when sensor says reservoir is full  
      
      if (digitalRead(bovenstesensor) == LOW)
      {
        Serial.println("break performed");
        volreservoir = true;
        emptyreservoir = false;
        break;
      }

      //if entire loop is run...pump has been filling for half an hour.  turn on malfunction to indicate that sensors or pump are not functioning properly
      if (i == 298){
        malfunction = true;
        Serial.println("safety switch activated");
      }
    }
     //turn water off and set emptyreservoir on false;
     digitalWrite(relaygrondwater, HIGH);
     emptyreservoir = false; 

  //when enough water, turn box 1 during .... minutes. Turn box1 on and flow groundwater. 

  //////////////////////////////////////////////////////
  digitalWrite(box1, LOW);
  digitalWrite(relaygrondwater, LOW);
   
  for (int i = 0; i <= box1time; i++) {
    Serial.println("loop box1");
    if(digitalRead(onderstesensor) == HIGH){
        //reservoirtak low, shut down box and refill reservoir... de relaypump is still running. 
        digitalWrite(box1, HIGH);
        Serial.println("reservoirtank low, enter fill loop");
        for(int j = 0; j <= 200; j++) {
            if(digitalRead(bovenstesensor) == LOW){
                //tank is back full and we can continue running 

                Serial.println("tank is again full"); 
                break;
            }
            delay(10000);
        }
        //restart box... has been resetted back to the beginning. 
        digitalWrite(box1, LOW);     
    }
    delay(10000);   
  }
  digitalWrite(box1, HIGH);
  digitalWrite(relaygrondwater, HIGH);

  //////////////////////////////
  //daarna wanneer voldoende vol box2 aangeschakelen gedurende ... minuten
  //box1 aanschakelen en grondwater laten stromen. 

  //next when reservoir is full enough turn box2 on during ... minutes. 
  //switch on box1 and let ground water flush. 
  //////////////////////////////////////////////////////

centralupperlayer - kopie.jpg

centralmiddle layer - kopie.jpg

centralupperlayer - kopie.jpg

centralmiddle layer - kopie.jpg

Take one channel from you block diagram and make a proper schematic showing the components.

Show it to us.

Your code doesn't compile. It looks like some of it is missing at the bottom.

And the rest of the code...

//////////////////////////////
  //daarna wanneer voldoende vol box2 aangeschakelen gedurende ... minuten
  //box1 aanschakelen en grondwater laten stromen. 

  //next when reservoir is full enough turn box2 on during ... minutes. 
  //switch on box1 and let ground water flush. 
  //////////////////////////////////////////////////////
  digitalWrite(box2, LOW);
  digitalWrite(relaygrondwater, LOW);
   
  for (int i = 0; i <= box2time; i++) {
    Serial.println("loop box2");
    if(digitalRead(onderstesensor) == HIGH){
        //reservoirtank low, shut off box and fill up reservoir... relaispump is still running
        digitalWrite(box2, HIGH);
        Serial.println("reservoirtank low, enter fill loop");
        for(int j = 0; j <= 200; j++) {
            if(digitalRead(bovenstesensor) == LOW){
                //tank is back full and we can continue
                Serial.println("tank is full again"); 
                break;
            }
            delay(10000);
        }
        //restart box 1. Has been reset to the beginning.. 
        digitalWrite(box2, LOW);     
    }
    delay(10000);   
  }
  digitalWrite(box2, HIGH);
  digitalWrite(relaygrondwater, HIGH);

  //////////////////////////////
  //daarna wanneer voldoende vol box3 aangeschakelen gedurende ... minuten
  //box1 aanschakelen en grondwater laten stromen. 
  //////////////////////////////////////////////////////
  digitalWrite(box3, LOW);
  digitalWrite(relaygrondwater, LOW);
   
  for (int i = 0; i <= box3time; i++) {
    Serial.println("loop box3");
    if(digitalRead(onderstesensor) == HIGH){
        //reservoirtank low, box uitschakelen en reservoir bijvullen... de relaypomp liep nog
        digitalWrite(box3, HIGH);
        Serial.println("reservoirtank low, enter fill loop");
        for(int j = 0; j <= 200; j++) {
            if(digitalRead(bovenstesensor) == LOW){
                //de tank is weer vol en we kunnen weer door
                Serial.println("tank is weer vol"); 
                break;
            }
            delay(10000);
        }
        //opnieuw box aanzetten... is weer gereset naar het begin
        digitalWrite(box3, LOW);     
    }
    delay(10000);   
  }
  digitalWrite(box3, HIGH);
  digitalWrite(relaygrondwater, HIGH);

  //////////////////////////////
  //daarna wanneer voldoende vol box4 aangeschakelen gedurende ... minuten
  //box1 aanschakelen en grondwater laten stromen. 
  //////////////////////////////////////////////////////
  digitalWrite(box4, LOW);
  digitalWrite(relaygrondwater, LOW);
   
  for (int i = 0; i <= box4time; i++) {
    Serial.println("loop box4");
    if(digitalRead(onderstesensor) == HIGH){
        //reservoirtank low, box uitschakelen en reservoir bijvullen... de relaypomp liep nog
        digitalWrite(box4, HIGH);
        Serial.println("reservoirtank low, enter fill loop");
        for(int j = 0; j <= 200; j++) {
            if(digitalRead(bovenstesensor) == LOW){
                //de tank is weer vol en we kunnen weer door
                Serial.println("tank is weer vol"); 
                break;
            }
            delay(10000);
        }
        //opnieuw box aanzetten... is weer gereset naar het begin
        digitalWrite(box4, LOW);     
    }
    delay(10000);   
  }
  digitalWrite(box4, HIGH);
  digitalWrite(relaygrondwater, HIGH);

  //6 hours of delay to bridge the night. 
  for(int i=0; i<2700; i++){
    //BOD DISABLE - this must be called right before the __asm__ sleep instruction
    MCUCR |= (3 << 5); //set both BODS and BODSE at the same time
    MCUCR = (MCUCR & ~(1 << 5)) | (1 << 6); //then set the BODS bit and clear the BODSE bit at the same time
    __asm__  __volatile__("sleep");//in line assembler to go to sleep
  }
  //////////////////////////////


  }
  else{
    Serial.println("it is day");
    for(int i=0; i<2700; i++){
    //BOD DISABLE - this must be called right before the __asm__ sleep instruction
    MCUCR |= (3 << 5); //set both BODS and BODSE at the same time
    MCUCR = (MCUCR & ~(1 << 5)) | (1 << 6); //then set the BODS bit and clear the BODSE bit at the same time
    __asm__  __volatile__("sleep");//in line assembler to go to sleep
  }
  }
  delay(1000);
}
}

ISR(WDT_vect){
  //DON'T FORGET THIS!  Needed for the watch dog timer.  This is called after a watch dog timer timeout - this is the interrupt function called after waking up
}// watchdog interrupt

Interesting project. I am curious where you got a 100kAh battery, that is 100,000 amp hours. I think you meant 100mAh. What if a shadow hits your light sensor? Posting a schematic showing all connections, not a frizzy thing would be a great addition for all of us.

Your loop function is very long and contains a lot of repetition. Consider refactoring some of it out into separate functions. One to start with might be the code that checks and fills the reservoir.

Hi,
As your pictures show you have got hardware connected , you must have a proper schematic of your project.
Please include PV, power supplies. pumps, etc and please label your connections and pins.

A pen(cil) and paper schematic would be fine, and you will probably find it easier that using a graphics program to produce.

Tom… :slight_smile:

gilshultz:
Interesting project. I am curious where you got a 100kAh battery, that is 100,000 amp hours. I think you meant 100mAh. What if a shadow hits your light sensor? Posting a schematic showing all connections, not a frizzy thing would be a great addition for all of us.

Good point, it is a 100Ah battery (I actually have 2 of them in my greenhouse... (initially they were used to power my electric motor of my boat) so a decent amount of capacity...
Attached my best attempt to draw the connections in this box.

Do you have kickback diodes across the pumps ?

What is a Box/Station ?

How are float switches wired ?

Might want to consider a ‘Buck Converter’ between 12v and Mega.

4 relays all on might be too much for Mega 5v.

What does the groundwater relay circuit look like ?

I'm not watering my house plants on the OP's scale.

Using an ESP32, I have a thread that runs every 10ms. The thread triggers other threads that take moisture readings, checks water level in the tank, sends receives MQTT, and other info. 10ms later the main thread again wakes up, checks the status of the water level, is pump running, is water level in the tank still good, has a safety margin been exceeded, sends status to the MQTT broker, receives any updates from the MQTT Broker, apply changes if needed, makes the proper 'decisions', triggers the threads to do the work, and 10ms later do it all over again.

On a Mega such is possible with a state machine and there are several good task schedulers such as the uTimerLib, TaskManagerIO, and a few others.

I have a similar project, about 4 years old, that has 4x relay outputs, adds 4x inputs, 4G-locked RTC, and a lot of variable logic / timers etc. as well as SMS control and notifications for ten users.

Your assembly looks pretty good. Great to hear it’s doing what you want

Sadly my website is currently down, but if you are interested to move on later, drop me a line.

larryd:
Do you have kickback diodes across the pumps ?
No i don't. I am using many of these pumps for a couple of years and of the 3 major projects involving multiple pumps i did not see any negative effects not having diodes across them.

What is a Box/Station ?
A box/station is in principle a 16 way valve. A separate Arduino mega is controller 2x 8-relais module which is turning the 12 volt valves open and closed. Here we do have diodes across them :wink: Attached a picture and the latest schematic with 8 relais shown.

How are float switches wired ?
Just directly. One to ground, one to PIN on arduino. No additional resistors.

Might want to consider a ‘Buck Converter’ between 12v and Mega.
Actually there are Converters between the 12 volts and Mega. A Controller is basically making sure that the power generated by the solar power are stably converted via a converter. The Arduino mega is directly connected via the usb port of this converter.

4 relays all on might be too much for Mega 5v.
I will only turn on 1 relais at a time. if it is about the boxes. Only in the case that the groundwaterpump should be running this relais is also closed. (so max 2 in total)

What does the groundwater relay circuit look like ?
The groundwater relay circuit is in principle a circuit which has an own battery (attached to a converted and a solar panel) powering 1 pump. An arduino (and just a physical switch can controll this circuit. This project is basically making use of the same pump (since i only can fit 1 pump in my groundwaterwell :wink:

Thanks for the suggestions and questions Larry.
Thanks for the suggestions on the libraries Idahowalker! i was not aware of them.
@lastchancename: i am interested to see your project!

Hi,
Is this the same project as this?
Why two threads on the same project?

Tom… :o

Website is up again… take a look at the user guide (down the bottom) if you’re interested.
www.SL4P.net

A post was split to a new topic: Sequential watering

Sorry for the delay…
www.SL4P.net

Have you done the basic calculations of energy required to lift the amount of water you are talking about and comparing ( taking efficiencies into account ) with your solar panel output .

If this is Insufficient you may have a serious issue.

You will be lifting 2tonnes of water through 14 meters each day .

Your solar panels might do it depending on the amount of power you actually get from them, but check !!

Just some general suggestions.
An in- line turban style water flow sensor. Large diameter bore. To measure flow rate.

The relays will have a lot of power draw. At about 80mA ea x number of of relays working.

An FET might be workable an be lower power.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.