Very long Delay

Hello, I'm making a self watering system for my tomato plants. I want a water pump to turn on for 5 minutes in the morning and five minutes in the evening.

I want to setup the arduino to control a relay that toggles the water pump on and off twice a day. I haven't started writing the code, I'm trying to envision what it looks like.

I think using the delay would be overkill, since one hour is already 3,600,000 ms. Would it be appropriate to use the millis() function since it can run for 50 days? Should I start out my code planning using the "blink without delay" example?

THANKS!

I think using the delay would be overkill, since one hour is already 3,600,000 ms.

If you don't want to do anything else, there's no reason not to use delay.
Just make sure you use the correct data type.

If you really don't need the Arduino doing anything in between waits, delay() will be the simpler solution. Since it takes an unsigned long as input (same type as millis), you can delay for up to just over 4 billion milliseconds, or just over 47 days.

The blink without delay method is mainly necessary when you want the Arduino to do other things while it's waiting (which is very common).

Thank you both, this is helpful. So if I use the following code, I'll be able to run my selfwaterer for 50 days with no problems? I'll be out of town for two weeks and I want to make sure the plants continue to grow.

void setup() {                
  pinMode(13, OUTPUT);     
}

void loop() {
  
  digitalWrite(13, HIGH);  
  delay(300000);             //5 minutes              
  digitalWrite(13, LOW);    
  
  delay(43200000);           //12 hour
  
  digitalWrite(13, HIGH);  
  delay(300000);             //5 minutes              
  digitalWrite(13, LOW);    

  delay(43200000);           //12 hour

}

You haven't accounted for the five minutes every twelve hours, so your timing will slip.

Try defining your constants like

#define SECOND 1000UL
#define MINUTE (SECOND * 60UL)
#define HOUR (MINUTE * 60UL)

and combining appropriately.

command_z:
I'll be able to run my selfwaterer for 50 days with no problems?

That sketch will have no rollover issues to speak of for any period of time. Repeatedly use of delay does not accumulate the time the way millis() does, so the only rollover issue you would have is if you tried to delay for 50+ days.

That being said, your timing will inevitably drift over time, but you will get a 12 hour delay followed by 5 minutes of watering for as long as the setup runs.

OK, so it if I used the #define it would work with the code below?

And if I stick to the delay(43200000);, that would work since it's automatically a UL, correct?

Thank You!

#define MINUTE (60000UL)
#define HOUR (MINUTE * 60UL)

void setup() {                
  pinMode(13, OUTPUT);     
}

void loop() {
  
  digitalWrite(13, HIGH);  
  delay(MINUTE*5);             //5 minutes              
  digitalWrite(13, LOW);    
  
  delay((HOUR*12)-(MINUTE*5));           //12 hour
  
  digitalWrite(13, HIGH);  
  delay(MINUTE*5);             //5 minutes              
  digitalWrite(13, LOW);    

  delay((HOUR*12)-(MINUTE*5));           //12 hour

}

Given that the clock will drift this seems like a good use of a RTC module/shield and the alarm function. Personally I would also guild the Lilly and include a cheap gps module to automatically update the RTC clock with the current time...

Untested or compiled but something along the line of -

const uint8_t       pinWATER_PUMP_RELAY         = 13;

const uint8_t       WATER_PUMP_OFF              = LOW;
const uint8_t       WATER_PUMP_ON               = HIGH;

const unsigned long ONE_SECOND                  = 1000UL;
const unsigned long ONE_MINUTE                  = 60UL * ONE_SECOND;
const unsigned long ONE_HOUR                    = 60UL * ONE_MINUTE;
const unsigned long TWELVE_HOURS                = 12UL * ONE_HOUR;
const unsigned long WATER_PUMP_TIME_ON          = 5UL  * ONE_MINUTE;
const unsigned long WATER_PUMP_TIME_NEXT_CYCLE  = TWELVE_HOURS - WATER_PUMP_TIME_ON;

void setPump(uint8_t state)
{
    digitalWrite(pinWATER_PUMP_RELAY, state);
}

void cycleWaterPump()
{
    setPump(WATER_PUMP_ON);

    delay(WATER_PUMP_TIME_ON);

    setPump(WATER_PUMP_OFF);
}

void loop()
{
    cycleWaterPump();
    delay(WATER_PUMP_TIME_NEXT_CYCLE);
}

void setup()
{
    pinMode(pinWATER_PUMP_RELAY, OUTPUT);

    setPump(WATER_PUMP_OFF);
}

Or a slightly different way to pass the time -

const uint8_t       pinWATER_PUMP_RELAY         = 13;

const uint8_t       WATER_PUMP_OFF              = LOW;
const uint8_t       WATER_PUMP_ON               = HIGH;

const unsigned long ONE_SECOND                  = 1000UL;
const unsigned long ONE_MINUTE                  = 60UL * ONE_SECOND;
const unsigned long ONE_HOUR                    = 60UL * ONE_MINUTE;
const unsigned long TWELVE_HOURS                = 12UL * ONE_HOUR;
const unsigned long WATER_PUMP_TIME_ON          = 5UL  * ONE_MINUTE;
const unsigned long WATER_PUMP_TIME_NEXT_CYCLE  = TWELVE_HOURS - WATER_PUMP_TIME_ON;


// time in milliseconds to trigger next cycle

unsigned long       tmNextTrigger;


// See <http://arduino.cc/playground/Code/TimingRollover>

bool hasTimeExpired(const unsigned long& tmsTarget)
{
    return ((long)(millis() - tmsTarget) >= 0);
}

void setPump(uint8_t state)
{
    digitalWrite(pinWATER_PUMP_RELAY, state);
}

void cycleWaterPump()
{
    setPump(WATER_PUMP_ON);

    delay(WATER_PUMP_TIME_ON);

    setPump(WATER_PUMP_OFF);
}

void loop()
{
    if ( hasTimeExpired(tmNextTrigger) )
    {
        cycleWaterPump();

        tmNextTrigger += WATER_PUMP_TIME_NEXT_CYCLE;
    }
}

void setup()
{
    tmNextTrigger   = millis();

    pinMode(pinWATER_PUMP_RELAY, OUTPUT);

    setPump(WATER_PUMP_OFF);
}

tomato plants.. wel maybe timing isnt as much important as to sunlight levels.
it depends a bit how you "rain" your plants, if its free faling from top, then its bad to rain with sunlight.
The best would be to drain the ground lay tubes with holes to wet the earth (but keep the leaves dry).
i think that for plants rain at night would be just as good or even better, maybe use an LDR and trigger water events.

loop
triger below light levels are at xxx then delay long until light levels get above, and long delay again
loop

it wont need exact times this way but it will work.
other things you might consider if the temp goes above xxx open windows of the glasshouse

The Time and TimeAlarms libraries work great for these types of projects especially when paired with an RTC or GPS module (even contains a auto update method for either of these modules). Its a bit overkill for most simple fixed delays, but once you need actions to occur on set times, even years away it makes these tasks really easy.

I agree with the earlier posters. A real-time clock chip (available for, say $9) means your sketch will always know the date and time. The battery backup will keep the clock going through power outages.

Example:

Without it, inevitably you will have the sketch stop from time to time. If on mains power, when the mains has an outage. If on batteries, when you replace them. After that, how will the sketch know the time of day?

Or you could make/get a soil humidity sensor and water them on need.

command_z:
Hello, I'm making a self watering system for my tomato plants. I want a water pump to turn on for 5 minutes in the morning and five minutes in the evening.

The humidity sensor is a good idea, don't need to water if it is raining. But perhaps they are under cover?

How about a light sensor? Point it to the sky, and if it drops to a certain (low) level and stays there for hours, you can assume it is night. Then when it comes up above a threshold, and stays there for 15 minutes, you can assume it is dawn. Then do your first water, and the second one (say) 8 hours later. You might need to tweak the thresholds a bit to allow for cloudy days, but you should be able to get it to work OK.

You definitely don't want to over or under water plants. Still, so many places now get so little rain a schedule isn't going to end with root rot.

Thanks everyone for your help on this.

I'm getting ready to go away for the weekend, and try my self waterer for the first time.

Here's the code I settled on. Please let me know if you find any errors!

If plug the water pump in at 6pm, the pump will switch on at 8am and 6pm for 45 seconds everyday.

#define SECOND 1000UL
#define MINUTE (SECOND * 60UL)
#define HOUR (MINUTE * 60UL)

void setup() {                
  pinMode(13, OUTPUT);     
}

void loop() {
  
                                                     // 6pm- Plug in
  
  digitalWrite(13, HIGH);  
  delay(SECOND*45);                       // on for 45 Seconds              
  digitalWrite(13, LOW);    
  
  delay((HOUR*14)-(SECOND*45));    // 8am
  
  digitalWrite(13, HIGH);  
  delay(SECOND*45);                       // on for 45 Seconds              
  digitalWrite(13, LOW);    
  
  delay((HOUR*10)-(SECOND*45));    //6pm
  
}

You can correct clock error by reset, but only at 6PM.
It looks like it should do what it's supposed to.