I have an output that adds makeup water to my pool. There's a couple of things that can make the output turn on - button being pushed, low pressure detected, start of day - stays on for 30 minutes. I don't want the output to be on for more then 60 minutes each day. I'm looking for a way to time how long the output is on, then reset it at the end of the day. Resetting is simple, but I'm scratching my head to figure out how to add up the time for the output. It could be on several times during the day, so it's not a matter of just timing one event. I'm sure I can do it, but everything I think if is kind of kludgy and complex, I'm hoping someone has already figured this out and has a better solution.
Use a variable to track the amount of time it is on.
You'll need one to track totalTime. Then you'll need one to track when an output goes on. Store the value of millis() when you turn the OUTPUT on. Subtract the current value of millis when then OUTPUT is turned off. Add that difference to your totalTime.
I agree to James that using the millis() value is the right way to go. I do not know how long the Arduino will run without reset, but please be aware that there is an rollover where the millis() counter is flipping back to "0" after appr. 50 days.
but please be aware that there is an rollover where the millis() counter is flipping back to "0" after appr. 50 days.
So? Your watch rolls over every night. Has that ever caused you grief? Can you not determine how long you slept when you get up in the morning?
Here's what I came up with
bool waterFillOnTrigger; // one shot trigger when water fill valve is turned on
void setup(){
waterFillOnTrigger = false;
}
void loop() {
static uint8_t waterAddedToday; // minutes of water added today
static uint32_t waterFillStart; // Saves millis() setting of when water fill timer starts
// Check to see if water fill valve has just opened
if(digitalRead(WATER_OUTPUT) == HIGH && waterFillOnTrigger == false)
{
// Valve just opened, set waterFillOnTrigger and add millis to start time
waterFillOnTrigger = true;
waterFillStart = millis();
}
// check to see if water fill valve has just closed
if(digitalRead(WATER_OUTPUT) == LOW && waterFillOnTrigger == true)
{
// Valve just closed, reset waterFillOnTrigger
waterFillOnTrigger = false;
// Calculate time (minutes) that valve was on and to daily timer
waterAddedToday += (millis() - waterFillStart) / 60000;
}
// Reset waterAddedToday every night at 11PM
if (poolTime > 23.0)
{waterAddedToday = 0;}
}
Here's what I came up with
And that compiled? I doubt it. Where is poolTime declared? Valued? Why is it compared to 23.0?
waterAddedToday += (millis() - waterFillStart) / 60000;
Literal constants (60000) are, in the absence of directives to the contrary, interpreted as ints. 60000 is not a valid int value. You need to tell the compiler to interpret 60000 differently, by adding UL (unsigned long) to the end.
I didn't include the whole sketch, just the parts relevant to this thread. Thanks for the tip about 60000.
ScottG:
I didn't include the whole sketch, just the parts relevant to this thread. Thanks for the tip about 60000.
Code that is posted must do two things:
- Compile as-is
- Demonstrate the problem
Posting anything less is problematic. Many times the code posted isn't the problem, it is issues elsewhere in the code.
soulid:
please be aware that there is an rollover where the millis() counter is flipping back to "0" after appr. 50 days.
Rollover is not an issue if unsigned subtraction is used.
if ((long)(millis() - waitUntil) >= 0)
Assuming waitUntil is defined as an unsigned long, this code will properly calculate the difference after rollover.
Edit: Thanks Peter. Corrected typo.
That may have been a typo - did you mean unsigned?