Count down to a specific time limit

Hi all,

In this project, I am counting down to a specific date and time to notify a technician that a certain component needs to be replaced.

To do so, I set a time limit variable during the setup(). I get a value for this variable by reading the actual time from a RTC chip and adding the technician's own instructions (he will input a value through a DIP switch).

I did try to use some librairies at first to simplify the whole thing, but I couldn't figure how to properly do what I wanted to do, so I decided to give it a try by myself, and, obviously, I'am not doing great so far.

I did find a pretty simple program to set my RTC date and time, and from there, I thought that I would be counting up to my time limit.

So I tried to convert every time elements to seconds using the following "math" (please, do note the quotation marks :sweat_smile::

date_ComponentInstalled = (unsigned long) 
(RTC_seconds 
+ (RTC_minutes 		* 60)
+ (RTC_hours		* 3600)
+ (RTC_day		* 24 * 3600)
+ (RTC_month		* 30 * 24 * 3600)
+ (RTC_year		* 365 * 24 * 3600)
);

Then, I did the following to set a time limit, adding a reading from my DIP switch:

date_time_ReplaceComponent = (unsigned long) 
  (RTC_seconds 
+ (RTC_minutes 		* 60)
+ (RTC_hours		* 3600)
+ (RTC_day		* 24 * 3600)
+ (RTC_month		* 30 * 24 * 3600)
+ (RTC_year		* 365 * 24 * 3600)
+ (ReadDIPSwitch() 	* 3600)
);

Then I proceeded to compare the results. It worked nicely for a 120 seconds limit, or even 1 hour limit.

Although the results of my two variables (date_ComponentInstalled and date_time_ReplaceComponent) didn't really match with my own math, it was working somehow. But when the value of the limit set from the DIP switch is above 8, it won't work anymore, the date_time_ReplaceComponent giving me weird results.

It seems to work nice up to 7 hours. But then between 7 and 15, the numbers goes yankee, and then above 15 it looks like it's rolling back below date_ComponentInstalled's own value, which seems odd as I'm adding a value from my DIP switch to it...

I first thought that the issue was coming from my variables casting, but they are unsigned long, as the functions returning them.

Most of the function are not fully implemented (i.e.: the ReadDipSwitch() is fake as I don't have an actual switch yet) but this should not be the issue either.

You will find the whole code attached to get the whole picture of the mess,

But any input would be very much appreciated.

Ps: I have a personal library ("Delaying") to handle millis() in less code lines, which should not be the issue here.

DateTimeLimitComponentReplacement.ino (8.3 KB)

Your calculations involve bytes (RTC_year, etc.) and ints (the literal values and the value returned by ReadDIPSwitch()). That the result is to be stored in an unsigned long does not matter. int-sized registers will be used, and will overflow when ReadDIPSwitch returns a value of 10 or more.

Other overflows will happen, too. In each multiplication, add UL to the end of one (or all) of the literals, to force the math to be done using 32 bit registers rather than 16 bit registers.

Thanks a lot PaulS.

I thought that adding a simple (unsigned long) after an equal "=" sign was enough to cast the entire calculation after it (on the right side of the equal sign), as stated here).

I assumed that an unsigned long variable would be able to handle any other type of variable in a calculation (except strings and chars), but thanks for pointing out the issue with mixing uint8_t / byte and int

So, here is the code now: I changed each variable (RTC_...) to be int instead of simple byte.

date_ComponentInstalled = (unsigned long) 
(RTC_seconds 
+ (RTC_minutes 		* 60UL)
+ (RTC_hours		* 3600UL)
+ (RTC_day		* 24 * 3600UL)
+ (RTC_month		* 30 * 24 * 3600UL)
+ (RTC_year		* 365 * 24 * 3600UL)
);

Everything works out now. Thanks again for your help.