I use the Sleep_n0m1 library to sleep the arduino duemilanove board for a long time (about one hour) to read different temperature sensors at each hour o'clock.
This is the library:
This is the pieceof code what send the arduino board to sleep :
sleep.pwrDownMode(); // Set the sleep mode to maximum power save
sleep.sleepDelay(sleepTime, abortSleep); // Start to sleep during the calculated period, until waked up
I am using a ds1307 rtc to read the time, and then i calculate for how long should sleep the board by this simple equation included in the code:
DateTime now = RTC.now(); // Calculate sleeping time until next measurement
sleepTime = (3600000-(((now.minute()*60)-now.second())*1000)); // Mileseconds to reach the next hour o'clok
Serial.println(sleepTime);
what goes inmediatly before to call the sleep procedure.
The problem is what when i run the program, the sleep time printed on the serial port was 3608192 but it should be not more than 900000 miliseconds to the next time o'clock!
So, what am i doing wrong?
I tested by using smaller frequency (1 minute), and i observed that the first 2 measurements does not fitt, but at the third one it returns correct values...
Any idea of this rare behaviour?
Thanks!
The problem is that this calculation:
(((now.minute()*60)-now.second())*1000)
is done in 16-bit integer arithmetic. You need to cast it to force the use of unsigned long.
You also should not be subtracting .second.
Try this:
sleepTime = (3600000UL-(((now.minute()*60UL)+now.second())*1000UL));
Pete
Hi Pete,
You are my hero! Thanks so much for your explanation and code. I didn´t know that about the arithmetic!
However, i still think that it is necesary to substract the seconds to reach the time o'clok... THis is how i see it:
If time is, for example: 21:30:40, it means that the next time to measure is at 22:00:00, the, it means 29 minutes and 20 seconds, it is: 29 minutes X 60 seconds = 1740 seconds + 20 seconds = 1760 seconds, right?
By the equation i presented above, it reads the minutes (30), and the seconds (40), then: 30 minutes x 60 seconds = 1800 - 40 seconds = 1760. Am i right?
In order to test the code you propose to correct my wrong code i made this short version to read each minute:
sleepTime = (60000UL - ((now.second())*1000UL));
and this is the result:
22:8
52000
23:5
55000
24:4
56000
25:5
55000
26:4
56000
27:4
56000
28:5
55000
29:4
56000
and, when i try with the whole period (1 hour), using your code but substracting the seconds, it return correct values:
40:11
1211000
43:1
1021000
Note: Numbers are minutes and seconds, and below the, the miliseconds to reach the next minute (above) or o'clock time (below).
If the time is 21:59:58 then there's only two seconds to go before 22:00:00. The calculation is:
3600 - (59*60 + 58) = 2 seconds
If you do 3600-(59*60 - 58) you get 118 seconds left which is obviously wrong.
Pete
MY BAD. YOU ARE COMPLETELY RIGHT! SORRY.
I made a mixture between the present time and the remaining time. So, you are completely right!
Thanks so much for your piece of code. It works PERFECT!
DateTime now = RTC.now();
sleepTime = (3600000UL - (((now.minute()*60UL) + now.second())*1000UL));
Thanks!
Is anyone know how to run Arduino clock without RTC
You can use the Time library but don't expect the clock to be accurate over any reasonable period.