Reset a value at the same time every day

TLDR: Does anyone have code to reset a value at the same time every day?

I have an Arduino-powered weather station and am trying to write code that will keep track of the daily high and daily low. My thought is for the Arduino to compare the current temp to the recorded low temp and if it's below set the low temp to the current temp. The same thing for high but in reverse.

But in order for it to be daily, I need the Arduino to reset the low temp / high temp at a given time each day. I'm having trouble thinking through the logic of how to accomplish that. Before I burn too many brain cells, I thought I'd see if anyone has already figured this out.

I know I could write a code that says "if the time is greater than minute X and less than minute Y, reset the value" but what if the unit happened to be powered off during that one X-Y minute? Could it figure out when it came back on that minute X-Y had passed and reset? I don't know how likely that scenario is, but still I'd like to account for it if not too complicated.

For reference, in addition to millis I also have the Time library (GitHub - PaulStoffregen/Time: Time library for Arduino) so I can call the current year, day, hour, minute, etc. as well as a unix time.

Writing about it must have jogged my brain, because the answer came to me right after I posted my question:

Set two global variables:

unsigned long highTempReset = 0;
unsigned long lowTempReset = 0;

The use the following code (resets at 5:30 every day)

int timeAsInt = ( ( hour() * 100 ) + minute() )

if ( timeAsInt > 530 && ( now() - highTempReset ) > 86400 ) {
	
	highTempRounded = temperatureCelsiusRounded;
	highTempReset = now()
	
}

Well, maybe it didn't jog my brain enough. :blush:

It just hit me that the "unit happened to be powered off during that one X-Y minute" scenario would never be necessary because powering off resets all the values!

So a simple if ( timeAsInt > 529 && timeAsInt < 530 ) would be sufficient.

Oh, well. Maybe it will be helpful to someone for something.

I never use the "do something when time is between x and y" method, it has complications. Rather, I compare the current time to see if it exceeds some time, if so I do something and then clear a flag so it won't repeat during the same time period (one of the between x and y problems). Then, I set the flag at the beginning of every new time period (day in this case). Seconds past midnight is a convenient number to use if your time period is one day.

Your oversight isn’t as obvious as it might seem !
There’s a good case in this type of application to save progressive totals in EEPROM, hence the values don’t need to be lost with a reset, only when you want to reset them.

The choice is of course up to you, and how you want to wrangle the data.

Enjoy.

If you already use the TimeLib, then you can add the TimeAlarms library: https://www.pjrc.com/teensy/td_libs_TimeAlarms.html.

What is the source of the time data in your sketch ?

I never use the "do something when time is between x and y" method, it has complications.

Can you elaborate? I'd be interested to know what to look out for if I have issues in the future.

Rather, I compare the current time to see if it exceeds some time, if so I do something and then clear a flag so it won't repeat during the same time period...

This was what I was originally thinking, but I couldn't work it out in my head. Particularly how to get the flag reset to not repeat multiple times. If you can post or link to an example, I'd be very interested.

Consider this. At midnight you set a flag 'alarmTriggered' to false.
You want to trigger a simple event around 1pm, you don't care about the minutes or seconds.
In loop(), you repeatedly check whether 'alarmTriggered' is false, and also the current hour is greater than or equal to 13.
If it is, you run the event, and set 'alarmTriggered' to true. This will lock out further event triggers.
Nice thing about this way, you can ignore minutes and seconds if you like...

The importance of the flag is obvious, without it, you continue to check the time for as many times loop() executes in your smallest time period (e.g. one hour, minute or second). In a well designed program, that could be thousands of times.

The coding itself has no tricks really, that's why I'm elaborating on a concept rather than posting or linking to code.

At midnight you set a flag 'alarmTriggered' to false.

What does the conditional statement for this look like? If you use
hour() == 0
then it would reset the flag over and over for a whole hour, creating another version of the whole problem we're trying to avoid.

I guess you could create a global variable int alarmTriggeredHourPrevious and do something like

if ( hour() < alarmTriggeredHourPrevious ) alarmTriggered = false;
if ( alarmTriggeredHourPrevious  != hour() ) alarmTriggeredHourPrevious = hour();

which would be able to detect the change from 23 to 0.

Does that sound about right, or is there a simpler / better solution?

You're trying to think in code, instead of logic.

Here is an example for once an hour logic:

if hour > last hour
{
last hour = hour
... do your once an hour something
}

For your daily alarm,

if alarmTriggered
  {
  if hour == 0
    { alarmTriggered = false }
  }
else
  {
  if hour > alarmHour
    {
    alarmTriggered = true
  ... do the alarm things here...
    }
  }

Sorry, I'm still not sure that I understand why this wouldn't cause alarmTriggered to reset to false over and over for an entire hour.

Anyway, I was thinking about the code I proposed above and realized that I could combine it with my original code to make something that doesn't require a flag reset at all.

// global variables
int timeAsIntPrev;
float highTempRounded = -50;
int highTempTime;
float lowTempRounded = 150;
int lowTempTime;

// in loop
int timeAsInt = ( ( hour() * 100 ) + minute() );

if ( timeAsInt == 530 && timeAsIntPrev == 529 ) highTempRounded = temperatureCelsiusRounded;  // for reset

if ( temperatureCelsiusRounded > highTempRounded ) {
	
	highTempRounded = temperatureCelsiusRounded;
	highTempTime = timeAsInt;
	
}

if ( timeAsInt == 2030 && timeAsIntPrev == 2029 ) lowTempRounded = temperatureCelsiusRounded;  // for reset

if ( temperatureCelsiusRounded < lowTempRounded ) {
	
	lowTempRounded = temperatureCelsiusRounded;
	lowTempTime = timeAsInt;
	
}

if ( timeAsIntPrev != timeAsInt ) timeAsIntPrev = timeAsInt;

Because I assigned the value 'true' to it. That forces the 'if' clause to execute from that time onwards, until it's reset when hour == 0.

You need to develop the skill of walking through the code mentally and keeping track of variable states and values. In this case, the code is so simple that an explanation is more complicated. :slight_smile: