Solved: Sketch appears to be ignoring the schedule

Hey everyone, I am a little at a loss here, likely some silly thing, but here's my boggle. I built a box running a clone nano (w/328) that is supposed to read a pot every 500 ms, read analog and digital sensors every hour, then based on the input from the pot and sensors, water a plant, or dont, every 8 hours. Basically if a moisture sensor reads higher (dryer) than threshold (pot) I want it to water the plant, as long as the other sensors for water supply and overflow are in "normal" state.

I get good reads from the sensors and the pot at the intervals I want, but as soon as i adjust the pot to a value lower than the moisture sensors value, it immediately triggers a watering. It doesn't wait for the 8 hour mark. It also repeats the watering cycle over and over (as it hasn't read the moisture sensor to tell it the soil is wet again yet). What it should do is wait for the 8 hour mark, water if needed, then wait again till the next 8 hour mark and water again if need be...

So to sum up the issue, everything seems to work as expected, except the watering itself. It doesn't wait to do its thing, and it does it over and over. I have included the whole void loop code, as I'm not sure where the issue is. Thanks everyone!

void loop()
{
//Threshold detection cycle every .5 seconds begin:
unsigned long currentMillis = millis();

  if(currentMillis - previousMillis1 > thresholdDelay) 
  
  {
  previousMillis1 = currentMillis;
  threshold_val = analogRead(threshold);  //read the value from the potentiometer
  
  lcd.home (); // go home
  lcd.clear();
  lcd.print("Soil:      ");
  lcd.print( moisture_val );
  lcd.setCursor (0,1);        // go to start of 2nd line
  lcd.print("Threshold: ");
  lcd.print( threshold_val  ); 
  }
  
// Power up and Read the sensors once every hour
  if(currentMillis - previousMillis2 > sensorDelay) 
  
  {
  previousMillis2 = currentMillis;
  
  digitalWrite(13, HIGH);           //LED to show that Moisture detection cycle is in progress
  digitalWrite(moisturePWR, HIGH);  //Turn on power for the moisture probe 
  digitalWrite(leakINtrayPWR, HIGH);  //Turn on power for the Overflow sensor
  delay(100);  //small delay to let the sensor settle
  moisture_val = analogRead(moistureSensor); // read the value from the moisture-sensing probe, Dryer the soil, higher the value 
  reservoir_val = digitalRead(reservoirProbe);  
  leakINtray_val = digitalRead(leakINtray);  //check to see if the tray is going to overflow
  Serial.print("Reservoir State ");  //for debugging
  Serial.println(reservoir_val);
  Serial.print("Moisture ");  //for debugging
  Serial.println(moisture_val);
  Serial.print("Threshold ");  //for debugging
  Serial.println(threshold_val);
  Serial.print("Overflow State ");  //for debugging
  Serial.println(leakINtray_val);
  digitalWrite(moisturePWR, LOW);  //Power to probe off
  digitalWrite(leakINtrayPWR, LOW);  //Turn off power for the Overflow sensor
  digitalWrite(13, LOW);  //turn off LED that showed moisture detection cycle in progress (cycle complete)
}
  
//send signals for emails and water the plant on 8 hour cycle
 if(currentMillis - previousMillis3 > cycleDelay)
 {
     if (reservoir_val == HIGH)   //if water level is good:
   {
     reservoirProbeTX();  //Send signal to ethernet link to trigger email about needing water
   }
   
   else
 {
 }

    if (leakINtray_val == LOW)
    {
      overFlow();  //Send signal to ethernet link to trigger email about overflow imminent
    }
    
    else {}
      
 
//Watering (if the soil is too dry, AND there is water available in the tank, AND the tray isnt overflowing AND no leak in housing, turn on pump (pin 4), otherwise, do nothing.   
     if (moisture_val >=threshold_val && reservoir_val == LOW  && leakINtray_val == HIGH) // && leakINhousing_val == HIGH)  
   {
     watering();  //turn on pump, send signal to trigger email advising of plant being watered
    }
    
   else {}

 }

}

Please post your complete program or go to help with code snippets

Sorry about that, I was trying to post the relevant bits, while minimizing how many lines of code I post…lol (there are some lines commented out for future use)

//define what libraries to include:
#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>
#include <VirtualWire.h>

//LCD pinout parameters:
#define I2C_ADDR    0x27
#define BACKLIGHT_PIN     3
#define En_pin  2
#define Rw_pin  1
#define Rs_pin  0
#define D4_pin  4
#define D5_pin  5
#define D6_pin  6
#define D7_pin  7
LiquidCrystal_I2C lcd(I2C_ADDR,En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin);

//define names for all the pins to be used:
int moistureSensor = 0; //The moisture probe
int threshold = 1;      //The potentiometer value that defines when to water the plants
int moisturePWR = 4;    //The probes power pin
int pumpPWR = 5;        //Power to the pump
int txLEDpin = 6;       //LED that indicates when the transmitter is active
int reservoirProbe = 7; //Sensor that tells the system if there is water in the reservoir
int leakINtrayPWR = 8;  //Sensor power
int leakINtray = 9;    //sensor to detect overflow of catch tray under flower bed imminent
//int leakINhousingPWR = 10;  //Sensor power
//int leakINhousing = 11; //sensor to detect watder leak inside controller housing

//set placeholders for numeric values to be used later in the sketch:
int moisture_val;          //Value returned from the moisture probe
int threshold_val;         //potentiometer value
int reservoir_val;         //state of the resrvoir sensor
int leakINtray_val;
//int leakINhousing_val;
long previousMillis1 = 0;
long previousMillis2 = 0;
long previousMillis3 = 0;
long waterAmount = 30000;   //how long to run the pump when on (30 Seconds Runtime)
long pause = 120000;        //Pause between pump runs during watering cycle (2 Minute Pause)
long cycleDelay = 28800000; //how long between watering cycles(8 Hour Cycle)
long thresholdDelay = 500;
long sensorDelay = 3600000;

void setup()
{
  pinMode(13, OUTPUT);
  pinMode(moisturePWR, OUTPUT);
  pinMode(pumpPWR, OUTPUT);
  pinMode(reservoirProbe, INPUT_PULLUP);
  pinMode(txLEDpin, OUTPUT);
  pinMode(leakINtray, INPUT);
  pinMode(leakINtrayPWR, OUTPUT);
  //pinMode(leakINhousing, INPUT);
  //pinMode(leakINhousingPWR, OUTPUT);

//Transmitter and LCD setup:  
  vw_set_tx_pin(3);           // Sets pin D3 as the TX pin
  vw_set_ptt_inverted(true);  // Required for DR3100
  vw_setup(4000);      // Bits per sec
  Serial.begin(9600);
  lcd.begin (16,2);           //define what kind of LCD is being used

  
// Switch on the LCD backlight
lcd.setBacklightPin(BACKLIGHT_PIN,POSITIVE);
lcd.setBacklight(HIGH);
lcd.home ();
}

void loop()
{
//Threshold detection cycle every .5 seconds begin:
unsigned long currentMillis = millis();

  if(currentMillis - previousMillis1 > thresholdDelay) 
  
  {
  previousMillis1 = currentMillis;
  threshold_val = analogRead(threshold);  //read the value from the potentiometer
  
  lcd.home (); // go home
  lcd.clear();
  lcd.print("Soil:      ");
  lcd.print( moisture_val );
  lcd.setCursor (0,1);        // go to start of 2nd line
  lcd.print("Threshold: ");
  lcd.print( threshold_val  ); 
  }
  
// Power up and Read the sensors once every hour
  if(currentMillis - previousMillis2 > sensorDelay) 
  
  {
  previousMillis2 = currentMillis;
  
  digitalWrite(13, HIGH);           //LED to show that Moisture detection cycle is in progress
  digitalWrite(moisturePWR, HIGH);  //Turn on power for the moisture probe 
  digitalWrite(leakINtrayPWR, HIGH);  //Turn on power for the Overflow sensor
  //digitalWrite(leakINhousingPWR, HIGH);  //Turn on power for the Leak sensor
  delay(100);
  moisture_val = analogRead(moistureSensor); // read the value from the moisture-sensing probe, Dryer the soil, higher the value 
  reservoir_val = digitalRead(reservoirProbe);  
  leakINtray_val = digitalRead(leakINtray);  //check to see if the tray is going to overflow
  // leakINhousing_val = digitalRead(leakINhousing);  //Check to see if there is a water leak in controller housing
  Serial.print("Reservoir State ");  //for debugging
  Serial.println(reservoir_val);
  Serial.print("Moisture ");  //for debugging
  Serial.println(moisture_val);
  Serial.print("Threshold ");  //for debugging
  Serial.println(threshold_val);
  Serial.print("Overflow State ");  //for debugging
  Serial.println(leakINtray_val);
  // Serial.print("leakINhousing State ");  //for debugging
  // Serial.println(leakINhousing_val);
  digitalWrite(moisturePWR, LOW);  //Power to probe off
  digitalWrite(leakINtrayPWR, LOW);  //Turn off power for the Overflow sensor
  // digitalWrite(leakINhousingPWR, LOW);  //Turn off power for the Leak sensor  
}
  
 if(currentMillis - previousMillis3 > cycleDelay)
 {
     if (reservoir_val == HIGH)   //if water level is good:
   {
     reservoirProbeTX();  //Send signal to ethernet link to trigger email about needing water
   }
   
   else
 {
 }

    if (leakINtray_val == LOW)
    {
      overFlow();  //Send signal to ethernet link to trigger email about overflow imminent
    }
    
    else {}
      
//    if (leakINhousing_val == LOW)
//    {
//      leakDetected();  //Send signal to ethernet link to trigger email that the pump is leaking
//   }
    
//    else {}
 
//Watering (if the soil is too dry, AND there is water available in the tank, AND the tray isnt overflowing AND no leak in housing, turn on pump (pin 4), otherwise, do nothing.   
     if (moisture_val >=threshold_val && reservoir_val == LOW  && leakINtray_val == HIGH) // && leakINhousing_val == HIGH)  
   {
     watering();  //turn on pump, send signal to trigger email advising of plant being watered
    }
    
   else {}


digitalWrite(13, LOW);  //turn off LED that showed moisture detection cycle in progress (cycle complete)
 }

}

void reservoirProbeTX()  //action to take if unit runs out of water:
{
 //   digitalWrite(pumpCutoff, HIGH);  // Engage the pump shutoff relay
    const char *msg = "dry";   // Message to be sent via transmitter
    digitalWrite(txLEDpin, true);      //Turn on LED to show transmitting
    vw_send((uint8_t *)msg, strlen(msg)); //Sending the message
    vw_wait_tx(); // Wait until the whole message is gone
    delay(500);                 // A short gap.
    digitalWrite(txLEDpin, false);   // Turn the LED off.
   }
   
void watering()
{
    const char *msg = "run";   // Message to be sent via transmitter
    digitalWrite(txLEDpin, true);      //Turn on LED to show transmitting
    vw_send((uint8_t *)msg, strlen(msg)); //Sending the message
    vw_wait_tx(); // Wait until the whole message is gone
    delay(500);                 // A short gap.
    digitalWrite(txLEDpin, false);   // Turn the LED off.
    
    digitalWrite(pumpPWR, HIGH);  //watering cycle start
    delay(waterAmount);
    digitalWrite(pumpPWR, LOW);
    delay(pause);
    digitalWrite(pumpPWR, HIGH);
    delay(waterAmount);
    digitalWrite(pumpPWR, LOW);  //watering complete   
   }

void leakDetected()   //action to take if water leaks in the controller housing
{
    //digitalWrite(pumpCutoff, HIGH);  // Engage the pump shutoff relay
    const char *msg = "wet";   // Message to be sent via transmitter
    digitalWrite(txLEDpin, true);      //Turn on LED to show transmitting
    vw_send((uint8_t *)msg, strlen(msg)); //Sending the message
    vw_wait_tx(); // Wait until the whole message is gone
    delay(500);                 // A short gap.
    digitalWrite(txLEDpin, false);   // Turn the LED off.
   }
   
void overFlow()   //action to take if water is about to overflow the catch tray
 {
    //digitalWrite(pumpCutoff, HIGH);  // Engage the pump shutoff relay
    const char *msg = "tre";   // Message to be sent via transmitter
    digitalWrite(txLEDpin, true);      //Turn on LED to show transmitting
    vw_send((uint8_t *)msg, strlen(msg)); //Sending the message
    vw_wait_tx(); // Wait until the whole message is gone
    delay(500);                 // A short gap.
    digitalWrite(txLEDpin, false);   // Turn the LED off.
   }

A lot of your int's could be bytes to save on SRAM usage.
Your time variables should be unsigned long to keep the math consistent with millis().
Similarly, time variables should have UL at the end, example:
long waterAmount = 30000UL;

Do you have a DR3100? If not, delete this line
vw_set_ptt_inverted(true); // Required for DR3100

You will probably have better results if you limit this to 2000:
vw_setup(4000); // Bits per sec

A short gap?
delay(500); // A short gap.
500mS is not short. 1 or 2mS would be short.

as soon as i adjust the pot to a value lower than the moisture sensors value, it immediately triggers a watering. It doesn't wait for the 8 hour mark.

Where is that in the code?

Forgive me Crossroads, I thought my time variables where unsigned long. the “UL” on the end, not something I’ve yet seen, not sure what that does. As far as where is that in the code, its not, that’s the issue. I don’t want it to begin watering as soon as I adjust the potentiometer to a level below the moisture level.

The "UL" is a signal to the compiler to make the constant an unsigned long, rather than the default int.

The reason it always waters is here

if(currentMillis - previousMillis3 > cycleDelay)

You never set previousMillis3 to anything, It's always 0, so the if statement is pretty much always true. All you have to do (and I'm just assuming this is what you want) is add the line

previousMillis3=currentMillis

in the if statement mentioned above.

Edit: Just noticed that cycleDelay is extremely high, so this doesn't solve the issue...

Thanks Nate, I did miss that line.. I am just wondering how the length of the cycle effect how the code executes?

I have added that line, going to upload and try it..

This was probably just a forgotten legacy comment, but on the line with that same if statement, you say in a comment

turn on pump (pin 4)

I just wanted to make sure you don't actually have the pump wired to pin 4, because it's defined as pin 5

Wow Nate, thanks, good eyes! yes, the pump relay is on pin 5 through a transistor. :slight_smile:

Haha, no problem. Debugging is like 90% of a programmers job. I figured it was on pin 5 but I just wanted to make sure =p

Thanks Nate, admittedly, it'll be about 7 more hours until I know its totally bug free, but I added that missing line. So far, seems to have done the trick!

I'm glad to hear!! Post after the 7 hours are up and you know, haha. Feel free to message or email me if you need anything else

Thanks Nate, your fix worked! I had just forgotten that one line of code..hehe silly mistake on my part..lol

I added code to have the arduino to also send the moisture level sensor output (analog sensor value) via the 433 MHz link to the other arduino that is set up for emailing me alerts about problems. In the receivers sketch I told it :

        Serial.print("Plant Moisture Reading: ");
        Serial.println(Sensor1Data);

The odd thing, it writes in the serial monitor, the "Plant Moisture Reading: " as I told it to, but it picks when to at random..lol (the sender sends the sensor data once an hour, and when the reciever gets that data, sometimes it adds the text, sometimes just puts the numbers..lol)

Quirky!

Arduino does not keep accurate time. You need an RTC, real time clock , if you want an alert every hour.

I’m considering it, although the actual timing isn’t crucial. The part im scratching my head at is the sometimes I’ll execute the code one way, but at random, I’ll do it this way part… lol I guess if i wanted anyone to actually look at what I was talking about, I should put the receivers sketch in the post… There again, its a separate issue, I should actually start its own thread for that issue.

Excuse me while I run and do that. :wink: