Irrigation Project

Hi Guys,

I live between a remote property and my house in the city(near the beach). It is summer here at the moment and i cannot leave my remote property to go to the beach as my gardens will die of dehydration.

I have 4 zones i would like to water. I have got half working code minus a few features i would like to implement.

I would like to somehow water 1 zone at a time with intervals ie 10mins and cycle through these zones at a set time once per day.
I have implemented the onebutton library and i am working on getting this to control manual operation.

I would also like to implement a DHT11 to take a reading at a set time and based on this reading do something at another certain time.

Example// If say the temp is above 30Deg Celcius at 2:00pm then run the watering intervals again at 6:00pm

I have a UNO with a RTC, DHT11 and Relayboard.

Here is my current code... It is most likely allot of excess as i have used code from others projects and tried to Taylor it for my needs.
If anyone could help me specifically with getting the 4 zones to cycle and with the temp sampling to create an event. That would be awesome. Thanks

#include <elapsedMillis.h>
#include "OneButton.h"
#include <Wire.h>
#include "RTClib.h"
#include <Time.h>
#include <TimeAlarms.h>
#include <idDHT11.h>

RTC_DS1307 RTC;
//Timers to replace Delay()
elapsedMillis timer0;
elapsedMillis timer1;
#define interval_1 3000
#define interval 1000
int idDHT11pin = 2; //Digital pin for comunications
int idDHT11intNumber = 0; //interrupt number (must be the one that use the previus defined pin (see table above)
void dht11_wrapper();
// Lib instantiate
idDHT11 DHT11(idDHT11pin,idDHT11intNumber,dht11_wrapper);

// RELAYS

int zone1 = 3;
int zone2 = 4;
int zone3 = 5;
int zone4 = 6;

//BUTTONS

OneButton button(7, true);


// the setup routine runs once when you press reset:
void setup() {

  button.attachDoubleClick(doubleclick);
  button.attachClick(click);
    Serial.begin(9600); 
    Wire.begin();
    RTC.begin();
   if (! RTC.isrunning()) {
    Serial.println("RTC is NOT running!");
    // following line sets the RTC to the date & time this sketch was compiled
      }

  // initialize the digital pin as an output.
  pinMode(zone1, OUTPUT); 
  pinMode(zone2, OUTPUT); 
  pinMode(zone3, OUTPUT); 
  pinMode(zone4, OUTPUT); 
  //Set relay pins high so they are off
  digitalWrite(zone1, HIGH);
  digitalWrite(zone2, HIGH);
  digitalWrite(zone3, HIGH);
  digitalWrite(zone4, HIGH);
  Serial.println("Startup Completed");  
    //Alarm.alarmRepeat(23,00,0, zone1on);  // 8:30am every day
    //Alarm.alarmRepeat(06,00,0, zone1off);  // 8:30am every day
    //Alarm.alarmRepeat(21,55,30, zone2on);  // 8:30am every day
    }
  
void dht11_wrapper() {
  DHT11.isrCallback();
}
// the loop routine runs over and over again forever:
void loop() {
  displaytemp();
  button.tick();
  displaytime();
  
  //Alarm.delay(1000); // wait one second between clock display
 delay(10);
 
 }

void displaytemp(){
  
  if (timer1 > interval_1) {
    timer1 -= interval_1;
  Serial.print("\nRetrieving information from sensor: ");
  Serial.print("Read sensor: ");
  //delay(100);
  int result = DHT11.acquireAndWait();
  switch (result)
  {
  case IDDHTLIB_OK: 
    Serial.println("OK"); 
    break;
  case IDDHTLIB_ERROR_CHECKSUM: 
    Serial.println("Error\n\r\tChecksum error"); 
    break;
  case IDDHTLIB_ERROR_TIMEOUT: 
    Serial.println("Error\n\r\tTime out error"); 
    break;
  case IDDHTLIB_ERROR_ACQUIRING: 
    Serial.println("Error\n\r\tAcquiring"); 
    break;
  case IDDHTLIB_ERROR_DELTA: 
    Serial.println("Error\n\r\tDelta time to small"); 
    break;
  case IDDHTLIB_ERROR_NOTSTARTED: 
    Serial.println("Error\n\r\tNot started"); 
    break;
  default: 
    Serial.println("Unknown error"); 
    break;
  }
  Serial.print("Humidity (%): ");
  Serial.println(DHT11.getHumidity());

  Serial.print("Temperature (oC): ");
  Serial.println(DHT11.getCelsius());
  }
}
  
void allon () {
  zone1on();
  zone2on();
  zone3on();
  zone4on();
}
void alloff () {
  zone4off();
  zone3off();
  zone2off();
  zone1off();
}
void zone1on() {
 digitalWrite(zone1, LOW); // 
   Serial.println("Zone 1 on");  
}

void zone1off() {
 digitalWrite(zone1, HIGH); // 
   Serial.println("Zone 1 off");  
}

void zone2on() {
 digitalWrite(zone2, LOW); // 
   Serial.println("zone 2 on");  
}

void zone2off() {
 digitalWrite(zone2, HIGH); // 
   Serial.println("Zone 2 off");  
}

void zone3on() {
 digitalWrite(zone2, LOW); // 
   Serial.println("Zone 3 on");  
}

void zone3off() {
 digitalWrite(zone2, HIGH); // 
   Serial.println("Zone 3 off");  
}

void zone4on() {
 digitalWrite(zone2, LOW); // 
   Serial.println("Zone 4 on");  
}

void zone4off() {
 digitalWrite(zone2, HIGH); // 
   Serial.println("Zone 4 off");  
}
void doubleclick() {
  allon(); 
  Serial.println("Double Click");
}

void click() {
  alloff(); 
  Serial.println("Click");
}
void displaytime() {
  if (timer0 > interval) {
    timer0 -= interval;
DateTime now = RTC.now();
    Serial.print(now.hour(), DEC);
    Serial.print(':');
    Serial.print(now.minute(), DEC);
    Serial.print(':');
    Serial.print(now.second(), DEC);
    Serial.println();
    }    
}

I have managed to get a sample working using an Alarm.alarmRepeat to trigger a function which changes a variable "temp"

Is there anyway i can possibly use an "if" statement to create another "Alarm.alarmRepeat" maybe?
and then delete it after it has run? I am sure i am on the wrong path... but i am just racking ideas......

Thanks anyone?

New Code

// Irrigation Project by Jason Pine 12/2013


//Librarys
#include <elapsedMillis.h>
#include "OneButton.h"
#include <Wire.h>
#include <DS1307RTC.h>
#include <Time.h>
#include <TimeAlarms.h>
#include <idDHT11.h>

//Timers to replace Delay()
elapsedMillis timer0;
elapsedMillis timer1;
#define interval_1 3000
#define interval 1000

//variables
int idDHT11pin = 2; //Digital pin for comunications
int idDHT11intNumber = 0; //interrupt number (must be the one that use the previus defined pin (see table above)
int temp = 0;
void dht11_wrapper();

// Lib instantiate
idDHT11 DHT11(idDHT11pin,idDHT11intNumber,dht11_wrapper);

// RELAYS

int zone1 = 3;
int zone2 = 4;
int zone3 = 5;
int zone4 = 6;

//BUTTONS

OneButton button(7, true);


// the setup routine runs once when you press reset:
void setup() {

  button.attachDoubleClick(doubleclick);
  button.attachClick(click);
    Serial.begin(9600); 
    setSyncProvider(RTC.get);   // ***the function to get the time from the RTC***
  if(timeStatus()!= timeSet) 
     Serial.println("Unable to sync with the RTC");
  else
     Serial.println("RTC has set the system time");
    // following line sets the RTC to the date & time this sketch was compiled
    


  // initialize the digital pin as an output.
  pinMode(zone1, OUTPUT); 
  pinMode(zone2, OUTPUT); 
  pinMode(zone3, OUTPUT); 
  pinMode(zone4, OUTPUT); 
  //Set relay pins high so they are off
  digitalWrite(zone1, HIGH);
  digitalWrite(zone2, HIGH);
  digitalWrite(zone3, HIGH);
  digitalWrite(zone4, HIGH);
  Serial.println("Startup Completed");  
    Alarm.alarmRepeat(14,58,0, tempsample);  // 8:30am every day
    //Alarm.alarmRepeat(14,23,0, alloff);  // 8:30am every day
    //Alarm.alarmRepeat(21,55,30, zone2on);  // 8:30am every day
    }
    
  
void dht11_wrapper() {
  DHT11.isrCallback();
}
// the loop routine runs over and over again forever:
void loop() {
  displaytemp();
  button.tick();
  displaytime();
  
  Alarm.delay(1000); // wait one second between clock display
 delay(10);
 
 }
void tempsample(){
  Serial.println ("  ");
  Serial.println ("*************Taking temp sample*******************");
  temp = (DHT11.getCelsius());
  Serial.print("Sample: ");
  Serial.print(temp);
  Serial.println ("*************DONE!*******************");
}

void displaytemp(){
  
  if (timer1 > interval_1) {
    timer1 -= interval_1;
  Serial.print("\nRetrieving information from sensor: ");
  Serial.print("Read sensor: ");
  //delay(100);
  int result = DHT11.acquireAndWait();
  switch (result)
  {
  case IDDHTLIB_OK: 
    Serial.println("OK"); 
    break;
  case IDDHTLIB_ERROR_CHECKSUM: 
    Serial.println("Error\n\r\tChecksum error"); 
    break;
  case IDDHTLIB_ERROR_TIMEOUT: 
    Serial.println("Error\n\r\tTime out error"); 
    break;
  case IDDHTLIB_ERROR_ACQUIRING: 
    Serial.println("Error\n\r\tAcquiring"); 
    break;
  case IDDHTLIB_ERROR_DELTA: 
    Serial.println("Error\n\r\tDelta time to small"); 
    break;
  case IDDHTLIB_ERROR_NOTSTARTED: 
    Serial.println("Error\n\r\tNot started"); 
    break;
  default: 
    Serial.println("Unknown error"); 
    break;
  }
  Serial.print("Humidity (%): ");
  Serial.println(DHT11.getHumidity());

  Serial.print("Temperature (oC): ");
  Serial.println(DHT11.getCelsius());
  }

}
  
void allon () {
  zone1on();
  zone2on();
  zone3on();
  zone4on();
}
void alloff () {
  zone4off();
  zone3off();
  zone2off();
  zone1off();
}
void zone1on() {
 digitalWrite(zone1, LOW); // 
   Serial.println("Zone 1 on");  
}

void zone1off() {
 digitalWrite(zone1, HIGH); // 
   Serial.println("Zone 1 off");  
}

void zone2on() {
 digitalWrite(zone2, LOW); // 
   Serial.println("zone 2 on");  
}

void zone2off() {
 digitalWrite(zone2, HIGH); // 
   Serial.println("Zone 2 off");  
}

void zone3on() {
 digitalWrite(zone2, LOW); // 
   Serial.println("Zone 3 on");  
}

void zone3off() {
 digitalWrite(zone2, HIGH); // 
   Serial.println("Zone 3 off");  
}

void zone4on() {
 digitalWrite(zone2, LOW); // 
   Serial.println("Zone 4 on");  
}

void zone4off() {
 digitalWrite(zone2, HIGH); // 
   Serial.println("Zone 4 off");  
}
void doubleclick() {
  allon(); 
  Serial.println("Double Click");
}

void click() {
  alloff(); 
  Serial.println("Click");
}
void displaytime() {
  if (timer0 > interval) {
    timer0 -= interval;
// digital clock display of the time
  Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.print(" ");
  Serial.print(day());
  Serial.print(" ");
  Serial.print(month());
  Serial.print(" ");
  Serial.print(year()); 
  Serial.println(); 
    }    
}
void printDigits(int digits){
  // utility function for digital clock display: prints preceding colon and leading 0
  Serial.print(":");
  if(digits < 10)
    Serial.print('0');
  Serial.print(digits);
}

It seems i am only talking to myself here but its working!!! hahaha

I managed to get my Temp sample at a "specific" time and then manage to, depending on the sample set another alarm..

it works so far... is there any reason this is not good code??

This code is called by an alarm at a set time everyday.

void tempsample(){
  Serial.println ("  ");
  Serial.println ("*************Taking temp sample*******************");
  temp = (DHT11.getCelsius());
  Serial.print("Sample: ");
  Serial.print(temp);
  Serial.println ("*************DONE!*******************");
  
  if(temp > second_water_temp) {
     Serial.println("Its been hot today. I will schedule another water for this evening say 6:00pm?....");
     Alarm.alarmOnce(15,41,0,allon);  // 5:45pm every day
  }
  else
  {
   Serial.println("It has not been hot enough today to schedule another water for this evening....");
  }
}

Mostly working now,

All i need to do now is write a function to

Turn on zone1 for 10 mins
Turn off zone1
wait 5 seconds
Turn on zone2 for 10 mins
Turn off zone2
wait 5 seconds
Etc Etc through all the zones. If its all in a single function then i will be able to start it manually with my button??

It would have been easy to just set alarm timers for these events but then making it impossible to run manually.

Any suggestions guys?
I don't seem to be generating any interest... Do i need to offer free hugs?? hahaha
Thanks

All i need to do now is write a function to

Turn on zone1 for 10 mins
Turn off zone1
wait 5 seconds
Turn on zone2 for 10 mins
Turn off zone2
wait 5 seconds
Etc Etc through all the zones. If its all in a single function then i will be able to start it manually with my button??

It would have been easy to just set alarm timers for these events but then making it impossible to run manually.

Any suggestions guys?

State machine and blink without delay.

Think about how YOU would perform the tasks that the Arduino is to perform. You could stand there with a garden how in your hand, frying in the sun, for 10 minutes. Or you could start a sprinkler running, and sit in the shade drinking beer until it was time to turn the sprinkler off. delay() is standing there in the sun frying. The blink without delay example shows how to drink beer in the shade instead.

I don't seem to be generating any interest... Do i need to offer free hugs?

You need to recognize that this is a worldwide forum, and that not everyone is on on your schedule. Patience, grasshopper.

Thanks PaulS,

I am just keen to leave here and get to the beach soon!

As usual your answers seem cryptic and subtle. I like it!!

Give a thirsty man a drink of water and he may be grateful.....But show him to the lake and he will never be thirsty again.

Cheers.

Give a thirsty man a drink of water and he may be grateful.

But, give him a cold beer, and he'll be a friend forever. 8)

This makes my brain hurt!!
http://playground.arduino.cc/Code/FiniteStateMachine

Maybe i should just drink the beer and get a hose?? (With a hat on)

Seems out of my depth :~

jasonthebass:
This makes my brain hurt!!
Arduino Playground - HomePage

Maybe i should just drink the beer and get a hose?? (With a hat on)

Seems out of my depth :~

Suppose you had that list of tasks to perform. You could keep track of whether you were in the watering the grass for 10 minutes state, or not, couldn't you. If you are, it might, or it might not, be time to turn the water off.

If not, you might, or might not, be in the waiting for time to do the next zone state. If you are, it might, or might not, be time to do the next state.

A state machine simply means that have several states that you might be in, and there are things that trigger a transition to another state, and there are things that should happen when that transition occurs.

You really only have a few states - watering zone n, waiting to move to zone n+1, and waiting to start the whole process over again.

The transition from watering zone n to waiting to move to zone n+1 involves turning the water off and incrementing n.

The transition from waiting to move to zone n to watering zone n involves turning the water on.

The transition from waiting to start the whole process over to watering zone 1 involves setting n to 1, and happens when the switch is pressed.

The only time that the switch is of interest, the way your requirements are defined, is when you are in the waiting for the whole process to start over state.

Of course, the other transitions happen at a specific time, relative to when the previous transition happened.

You might want to make the situation more complicated by making the watering times a function of temperature, light, or moisture level.

Or, you might want to make it simpler, and just buy a multi-zone timer setup.