Hello.
I am attempting to create an automatic garden watering system.
Currently I have a pump and sprinkler system where I just plug in the pump for ~1/2 hour in the evening each day provided it has not rained.
To automate the watering, I have two sensors and an Arduino nano.
The senors are: (1) moisture sensor that uses resistance and (1) flow meter sensor that uses the Hall Effect to transmit pulses to the nano.
The problem I am having is a programming issue: I have the nano reading the moisture sensor and pump flow rate. If the soil is dry and the flow rate from the pump is adequate, It turns the pump HIGH, (pump is represented by an LED right now). I have a interrupt to turn pump on for 3 seconds prior to checking the flow rate. This allows the pump enough time to produce an adequate flow of water. If the flow is too low, then it shuts the pump (LED) off LOW.
This sort of works but only for one cycle (loop). If the moisture sensor calls for water again, the nano sees the flow rate at zero so it does not turn the pump HIGH. I tried "delays" but it keeps looping the 3 second priming, and will keep the pump on HIGH all the time.
I need this flow rate check in the program to prevent any damage to the pump. Occasionally the pump intake will clog or sticks (frozen) at start-up.
Attached is the code I believe to be the problem area: I am not a programmer, just a hobbyist so bare with me and thank for any input.
while((millis() - oldTime2) < interval)
{
if (sensorValue > 750)
digitalWrite(pump, HIGH); //turn pump on for 3 seconds for flow
}
if (sensorValue > 750 && flowRate > 2) // low moisture and pump flow ok, pump on
{
digitalWrite(pump, HIGH);
}
else
{
digitalWrite(pump, LOW);
Hi Nick,
I'm new to this and do not understand your request.
I thought this was the Arduino forum for asking technical questions regarding programming?
This is not a personnel message either.?
Looking for a way to turn a pin HIGH for three seconds each time the sensor pin calls for the pump on as shown in the posted code. Need to be able to do this each time, not once.
Thanks.
Tom
Attached is the code I believe to be the problem area:
I am asking you to post all your code. I have a boilerplate button to ask that as I have to do it, like, 20 times a day. As listed in the forum posting guidelines: How to use this forum
If you don't know what the problem is, exactly, you cannot know what the problem area is. If you post all your code we might be able to help you.
Congratulations on using code tags, though. That is one less thing to ask you to do. 
If your code is long you can attach it to your post.
In the instructions, one place it says to post the problem area as to keep the code short and uncluttered. Then under your instructions it states to post the entire code. So I guess it's the entire code.
Here is the whole program/sketch: I know it's not clean/fully completed and I was performing tests to try to make it perform as I wanted, so again, bare with me.
Thanks.
byte sensorInterrupt = 1; // 1 = digital pin 3
byte sensorPin = 3;
float calibrationFactor = 4.5;
volatile byte pulseCount;
int pump =2; //pump pin D2
int ledRed = 6; //Red LED on pin D6
int powerLED = 13;
float flowRate;
unsigned int flowMilliLitres;
unsigned long oldTime;
unsigned long oldTime2;
unsigned long oldTime3;
int interval = 3000;
void setup()
{
pinMode(pump, OUTPUT);
pinMode(ledRed, OUTPUT);
pinMode(powerLED, OUTPUT);
pinMode(sensorPin, INPUT);
digitalWrite(sensorPin, HIGH);
Serial.begin(38400);
digitalWrite(powerLED, HIGH);
pulseCount = 0;
flowRate = 0.0;
flowMilliLitres = 0;
oldTime = 0;
attachInterrupt(sensorInterrupt, pulseCounter, FALLING);
}
void loop()
{
int sensorValue = analogRead(A0); // read input on analog pin A0
if((millis() - oldTime) > 1000) // Only process counters once per second
{
detachInterrupt(sensorInterrupt);
Serial.print("Mosture Value = ");
Serial.println(sensorValue);
flowRate = ((1000.0 / (millis() - oldTime)) * pulseCount) / calibrationFactor;
oldTime = millis();
flowMilliLitres = (flowRate / 60) * 1000;
unsigned int frac;
while((millis() - oldTime2) < interval)
{
if (sensorValue > 750)
digitalWrite(pump, HIGH); //turn pump on for 3 seconds for flow
}
if (sensorValue > 750 && flowRate > 2) // low moisture and pump flow ok, pump on
{
digitalWrite(pump, HIGH);
}
else
{
digitalWrite(pump, LOW);
}
if (flowRate < 2 && sensorValue > 750) //test if pump flow rate is too low
{
digitalWrite(ledRed, HIGH); // pump not flowing enough
}
else
{
digitalWrite(ledRed, LOW);
}
if((millis() - oldTime3) < interval)
{
if (sensorValue > 750)
digitalWrite(pump, HIGH);
}
Serial.print("Flow rate: ");
Serial.print(int(flowRate)); // Print the integer part of the variable
Serial.print("."); // Print the decimal point
frac = (flowRate - int(flowRate)) * 10;
Serial.print(frac, DEC) ; // Print the fractional part of the variable
Serial.println("L/min");
pulseCount = 0;
attachInterrupt(sensorInterrupt, pulseCounter, FALLING);
}
}
void pulseCounter()
{
pulseCount++;
}
If you have a problem with something like 2 + 2 not giving 4, it helps to post a small program the reproduces the problem. With other things of a timing nature, it helps to see things like datatypes and so on.
while((millis() - oldTime2) < interval)
{
if (sensorValue > 750)
digitalWrite(pump, HIGH); //turn pump on for 3 seconds for flow
}
This looks confusing. For one thing you are turning on the pump thousands of times - itself not really an issue. But since you are waiting anyway, why not use delay?
if (sensorValue > 750)
{
digitalWrite(pump, HIGH); //turn pump on for 3 seconds for flow
delay (interval);
digitalWrite(pump, LOW); //turn pump off now
}
if (sensorValue > 750 && flowRate > 2) // low moisture and pump flow ok, pump on
{
digitalWrite(pump, HIGH);
}
else
{
digitalWrite(pump, LOW);
}
if (flowRate < 2 && sensorValue > 750) //test if pump flow rate is too low
{
digitalWrite(ledRed, HIGH); // pump not flowing enough
}
else
{
digitalWrite(ledRed, LOW);
}
if((millis() - oldTime3) < interval)
{
if (sensorValue > 750)
digitalWrite(pump, HIGH);
}
Now I'm just confused. All this stuff is if the sensorValue > 750, right? Why not make that the major condition?
if (sensorValue > 750)
{
// do some stuff
}
else
{
// do other stuff
}
Don't keep re-testing the same thing.
The site I read to post minimal code was not this site, it was HOWTO get help with your arduino project - adafruit industries #6 when I was looking for programming help today.
Anyway, the hall effect sensor (flow meter) needs the interrupts (or polling) so delays do not work with interrupts.
A simple solenoid valve on city/well water would be much easier to program but I'm using a dedicated pump.
Yes, the major condition is "(sensorValue > 750)", but I also need to make sure there is enough flow from the pump or else there is something wrong and the pump needs to shut off. I have a red LED come on if that happens to show a "fault".
The reason I have the pump coming on multiple times in the program is because it needs to come on ~2-3 seconds first to show it has enough flow rate, then it can stay on until either the sensorValue < 750 (I still need to add a range) or the flow rate drops below 2 liters/min (which would be a pump problem).
I've been working on this program for a few weeks and it has become somewhat messy. It does work with sensors hooked up but stuck on how to turn pump on for 3 seconds prior to the major condition each time. The only other thing I though about doing was an internal reset every 12 hours or so, but I don't like that idea.
I'll try to clean up the code some more. Just stumped why it only turns pump on once for the 3 seconds. I did try delays and it keeps looping and the pump stays on all the time. My logic is faulty, so I need to rethink the whole approach.
Anyway, the hall effect sensor (flow meter) needs the interrupts (or polling) so delays do not work with interrupts.
You aren't turning interrupts off, nor are you doing a delay in an ISR, so this doesn't apply.
while((millis() - oldTime2) < interval)
oldTime2 never changes, so you may as well write:
while(millis() < interval)
Which will only ever be true for a short time. Ditto for oldTime3.
The site I read to post minimal code was not this site ...
That site said:
If you must post code, post the minimal code that demonstrates what doesn't work
They said "minimal code" not "a snippet which has no hope of compiling".
Look, if you said:
a = b + 2;
How come a is not 6?
We would need to know what b contained, right? Minimal code is not "a couple of lines". It is something we can compile, and test, which demonstrates your problem.