Auto watering code with milli()

Hi guys,

I am trying to make auto watering sytem with a soil moisture and i wanted to replace the delay() by milli()

the original code is this one wich is working:

 int moistureSensor = 2;

int relay = 3;


void setup()

{


pinMode(relay, OUTPUT);


Serial.begin(9600); }



void loop()

{



int sensorValue = digitalRead(moistureSensor);

// print out the value you read:

Serial.println(sensorValue);

digitalWrite(relay, HIGH);

if (sensorValue == 1) {


digitalWrite(relay, LOW);

Serial.println("Watering");

delay(10000);

// run pump for 10 seconds

Serial.println("Finished watering"); }

delay(1000);

// delay 1 second between reads

}

And the problem with is i don’t get the serial println like : Serial.println(“Finished watering”)

 int moistureSensor = 2;
unsigned long previousMillis = 0;        
long Onpump = 1800000;;          
long Offpump= 72000000;          
int relay = 3;

void setup()

{

pinMode(relay, OUTPUT);


Serial.begin(9600); }


void loop()

{
  int sensorValue = digitalRead(moistureSensor);

Serial.println(sensorValue);

digitalWrite(relay, HIGH);
unsigned long currentMillis = millis();

if((sensorValue == 1) && (currentMillis - previousMillis >= Onpump))
{

digitalWrite(relay, LOW);

Serial.println("Watering");

previousMillis = currentMillis;

}
else if ((sensorValue == LOW) && (currentMillis - previousMillis >= Offpump))

{
// run pump for 10 seconds

Serial.println("Finished watering"); 

 previousMillis = currentMillis;  
}

It will display 1 or 0 but that’s it; need some help to see what’s wrong.

You need to represent your state somehow - first identify the states and then the transitions between them and what causes each transition..

Hello,

Do you know about those wonderful things called Tropf Blumat ?

I think you need to disconnect the "needs water/does not need water" states from the timing actions.

You need to start watering, if not watering and if water is needed. That has NOTHING to do with time.

You need to stop watering, if watering and the plant is soaking wet. That has NOTHING to do with time.

If you are watering, and have been for a long time, stop. That has NOTHING to do with how wet/dry the soil is.

So should code be like this? Sorry I am bit confuse between the milli() and the moist sensor....

 int moistureSensor = 2;
unsigned long previousMillis = 0;        
long Onpump = 1800000;;          
long Offpump= 72000000;          
int relay = 3;
void setup()
{
pinMode(relay, OUTPUT);
Serial.begin(9600); }
void loop()
{
  int sensorValue = digitalRead(moistureSensor);

Serial.println(sensorValue);
digitalWrite(relay, HIGH);
unsigned long currentMillis = millis();

if((sensorValue == 1) 
(currentMillis - previousMillis >= Onpump))
{

digitalWrite(relay, LOW);

Serial.println("Watering");
  int sensorValue = digitalRead(moistureSensor);

Wouldn't

  int moisturePinValue = digitalRead(moistureSensorPin);

make more sense?

bool needsWater = moisturePinValue == HIGH;

Compare the value read from the moisture sensor to HIGH. Assign the result to needsWater.

Now, you can do:

  if(needsWater)
  {
     if(!watering)
       startWatering();
  }
  else
  {
     // Soggy as all get out
     if(watering)
        stopWatering();
  }

startWatering() would, obviously, set watering to true AND record when that happened. After that code, you would have:

   if(watering)
   {
      if(millis() - startedWatering > timeToWater)
      {
         stopWatering();
      }
   }

By using names that make sense, and putting code in appropriately named functions, the code almost writes itself.

Surely, you can figure out the types for watering (boolean), startedWatering (unsigned long), timeToWater (unsigned long), and appropriate (initial) values.

Surely, you can figure out what startWatering() and stopWatering() should do.

I too had a hard time learning to use millis() timing.
Part of that I think is the terrible variable names they chose. And that they always show a continuously repeating timer so it is hard to see where the timing starts and stops.

Here is an example that I hope more clearly shows how the timing starts and finishes.

unsigned long startTime = 0;
const long interval = 1000;  // 1 second = 1000 millis
bool timeFlag = false;

void setup()
{
}

void loop()
{
  if (something you want to Time) // <<<<< Put the sensor == 1 here
  {
    timeFlag = true;
    startTime = millis();     // Begin timing sequence
    // do stuff here when timing sequence starts <<<<< turn pump on here
  }

  unsigned long currentTime = millis();
  if (timeFlag == true && currentTime - startTime >= interval) // End timing sequence
  {
    timeFlag = false;
    // do stuff here when time is up    <<<<<<<< turn pump off here
  }
}

Thanks the answers look easier i gonna try this !

So i follow your instruction Hutkikz the code should be that?

This code is really bothering me when i put digitalWrite(relay, LOW); that should stop watering not start? [My pump is connected to the relay]

int moistureSensor = 2;
int relay = 3;
unsigned long startTime = 0;
const long interval = 1000;  // 1 second = 1000 millis
bool timeFlag = false;

void setup()
{
pinMode(relay, OUTPUT);
Serial.begin(9600);

}

void loop()
{
int sensorValue = digitalRead(moistureSensor);

  if (sensorValue == 1) // <<<<< Put the sensor == 1 here
  {
    timeFlag = true;
    startTime = millis();     // Begin timing sequence
   
digitalWrite(relay, LOW);
Serial.println("Watering");
  }

  unsigned long currentTime = millis();
  if (timeFlag == true && currentTime - startTime >= interval) // End timing sequence
  {
    timeFlag = false;  
digitalWrite(relay, HIGH); 
// do stuff here when time is up    <<<<<<<< turn pump off here
  }
}

And i tryed as well with your advice PaulS but not very confident of the result :s

 int moistureSensorPin = 2;  
bool needsWater = moisturePinValue == HIGH;

int relay = 3;

void setup()
{
pinMode(relay, OUTPUT);
Serial.begin(9600); }
void loop()
{
int moisturePinValue = digitalRead(moistureSensorPin);

Serial.println(moistureSensorPin);
unsigned long currentMillis = millis();

  if(needsWater)
  {
     if(!watering)
       startWatering();
  }
  else
 {

digitalWrite(relay, LOW); // do I need this?
}
if(watering)
   {
      if(millis() - startedWatering > timeToWater)
      {
         stopWatering();

digitalWrite(relay, HIGH);

      }
   }

My code is a shame lol do you think i can find a code wich fit better my expectations?

bool needsWater = moisturePinValue == HIGH;

should NOT be a global variable. Put it AFTER reading the pin, like I had done.

void setup()
{
pinMode(relay, OUTPUT);
Serial.begin(9600); }

The } ALWAYS goes on a new line. Use white space between functions. Use Tools + Auto Format. Your code is hard as hell to read.

unsigned long currentMillis = millis();

  if(needsWater)
  {

It is NOT necessary to store the value of millis() in a variable.

  else
 {

digitalWrite(relay, LOW); // do I need this?
}

Yes. IN A FUNCTION!

Does HIGH turn the relay on? Or does HIGH turn it off?

Where are the startWatering() and stopWatering() functions?

Thanks for the answers;

From what i have tried with the previous code low turn the relay on and high turn it off but doesn't make much sense for me

And i have the relay functions it's plug on the pin 3

Sorry PaulS i don't get where to go with the code what am i suppose to do with startWatering() and stopwatering()?

what am i suppose to do with startWatering() and stopwatering()?

Don't the names suggest anything?

Everything that has to do with starting watering goes in the startWatering() function - turning the pump on, recording the time, setting the watering flag, etc.

Everything that has to do with stopping watering goes in the stopWatering() function - turning the pump off, clearing the time, clearing the watering flag, etc.