Mixing Timers and interrupts

This might also be served in the feasibility forum, but I’m having an issue with a project involving running code at a set time over several days. I’ve got code to run the water pump in my greenhouse anytime between 13:30-13:59 every third day. I’m trying to also include code that if a button is pressed also begins the watering routine. My original code is implemented using the delay function and it was only after trying and failing to do the same thing with an interrupt did I discover that it’s not feasible. The code is below

#include <Wire.h>
#include<TimeLib.h>
#include<DS1307RTC.h>

#define CHANNEL_1 7
#define CHANNEL_2 8
#define buttonPin 2

tmElements_t tm;
void setup() {
bool parse=false;
  bool config=false;

  Serial.begin(9600);
  while (!Serial) ; // wait for Arduino Serial Monitor
  delay(200);
  if (parse && config) {
    Serial.print("DS1307 configured Time=");
    Serial.print(__TIME__);
    Serial.print(", Date=");
    Serial.println(__DATE__);
  } else if (parse) {
    Serial.println("DS1307 Communication Error :-{");
    Serial.println("Please check your circuitry");
  } else {
    Serial.print("Could not parse info from the compiler, Time=\"");
    Serial.print(__TIME__);
    Serial.print("\", Date=\"");
    Serial.print(__DATE__);
    Serial.println("\"");
  }
  
  pinMode(CHANNEL_1, OUTPUT);
  pinMode(CHANNEL_2, OUTPUT);
  pinMode(buttonPin, INPUT);
  digitalWrite(CHANNEL_1, HIGH);
  digitalWrite(CHANNEL_2, HIGH);
  attachInterrupt(digitalPinToInterrupt(buttonPin), runPump, RISING);

void loop() {
  if (tm.Hour == 13) {
    if (tm.Minute < 30) {
      delay(minToMillis(30 - tm.Minute));
    }else{
      if (tm.Day % 3 == 0) {
        runPump();
        delay(hoursToMillis(.5));
      }else{
        delay(hoursToMillis(1));
      }
    }
  }
  else {
    if (tm.Minute < 30) {
      delay(hoursToMillis(1));
    }else {
      delay(hoursToMillis(.5));
    }
  }
  
}

void runPump() {
  if (on == 0) {
    Serial.println("running 1");
    delay(5000);
    digitalWrite(CHANNEL_1, LOW);
    delay(minToMillis(1.25));
    digitalWrite(CHANNEL_1, HIGH);
    delay(5000);
    Serial.println("running 2");
    digitalWrite(CHANNEL_2, LOW);
    delay(minToMillis(1.25));
    digitalWrite(CHANNEL_2, HIGH);
  }
}

So my biggest question is just about if it’s possible to get the same functionality without delay, in particular just the waiting until the right time on the right day kind of thing. If it is, it should be pretty simple to use the button with interrupt. Thanks in advance!

It is, but the clock in an Arduino is not all that accurate over a long period of time. What you need is a RTC breakout board with a backup battery. For about $5 Adafruit RTC breakout.

The other route you could go is to just water from a moisture level. (This is now I do it.) You can get cheap capacitive moisture sensors from Amazon.

-jim lee

Thank you for the reply, I have an RTC board the DS1307, the issue isn't really with the time keeping which works fine, I just want to add a manual switch that allows me to water in addition to the regular watering schedule. I can't do the moisture sensors as I have about 16 beds and don't want to fill the whole area with wires. You said that it is possible, any suggestions?

void setup() {
  bool parse=false;
  bool config=false;
[..]
  if (parse && config) {

Seems useless, since parse and config will always be false.

void runPump() {
  if (on == 0) {

Variable "on" is not even declared or initialized.

  attachInterrupt(digitalPinToInterrupt(buttonPin), runPump, RISING);

void loop() {

Missing "}" at the end of setup().

  • When you use millis() instead of delay() you won't need an interrupt for the button.

For your first part, that's part of the RTC Setting code which I didn't include all of as it wasn't relevant to this question.
For the second part, that's leftover from a test and isn't part of the actual running code, was left on accident.
For the third part, that's just an issue from my copying and pasting, and not a problem in the actual code.

Finally when you say millis() I believe you're meaning the system where you check the amount of time that's passed right and then check that against a threshold value to see if the thing will run? I don't know if I can do that given I want the pump to run at a certain time on certain days. That's mostly why I posted the question in the first place.

you’re meaning the system where you check the amount of time that’s passed right and then check that against a threshold value

Yes.

Assuming this code works to your satisfaction:

  if (tm.Hour == 13) {
    if (tm.Minute < 30) {
      [etc.]

, you’d only have to change the remaining delay()s!

Okay, I think I understand I'll try it out, thanks for the advice!

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