I have a program which measures temperatures every 30 minutes and sends them to a database. Immediately after running the program the first measurement is sent, however, the second (which should be sent after 30 min), is sent only after 1 hour. From then on the code works fine. The time is measured in millis. However, if I set the time difference to 28 minutes everything works fine from the beginning. What could be the reason for this? Is there a possibility that it goes to sleep mode? I don't understand why it works fine with 28 minutes and it stops working with 29 minutes?
Thanks in advance!
My code:
if (millis() - sendDataPrevMillis > 1740000)
{
sendDataPrevMillis = millis();
//other code
}
The only part I change, so it works is setting millis from 1740000 (29 minutes) to 1680000 (28 minutes).
1 Answer 1
- Although not strictly required, maybe use parentheses around
millis() - sendDataPrevMillis
for readability; - I guess you will have initialised
sendDataPrevMillis
to 0 but the first time you assignsendDataPrevMillis
tomillis()
some time will have elapsed since you evaluated. So callingmillis()
twice will give different results. That makes it less easy to see what is going on.
Suggestion to try:
long HALFHOUR = 30 * 60 * 1000L;
if ( (millis() % HALFHOUR ) == 0L ) {
//measure and send
//....
}
Hope this helps.
NB: %
is what is called the 'modulo operator' see: https://www.geeksforgeeks.org/modulo-operator-in-c-cpp-with-examples/
-
I don't quite understand, what you mean with your second point. Calling
millis()
multiple times will give different results, when between the calls at least one millisecond passed. When initializingsendDataPrevMillis
to zero, the time will be counted from startup (power cycle or reset). It is not very probable, that the code has run over half an hour before reaching the if statement the first time. So why should that matter?chrisl– chrisl03/31/2021 21:04:50Commented Mar 31, 2021 at 21:04 -
The prob. of that will of course be very small indeed. what I was trying to say was about style: when the condition of the loop refers to the actual progressed millis (the first call) I would suggest to store exactly that value. Assignment within the condition if ( (currentMillis = millis()) - sendDataPrevMillis > 1740000) { sendDataPrevMillis = currentMillis; in order to prevent that becomes a bit messy, don't you think?user75521– user7552103/31/2021 21:14:07Commented Mar 31, 2021 at 21:14
-
You can do that with the assigment in if condition, but I don't think that this is better readable. Though that is subjective. In your second point you don't talk about style. As I now understand you say, that the
millis()
calls in the if condition and in the following inner statement give different results. I don't think that. The code runs way too fast for that. Even if the code happens to accidentally hit the exact point, wheremillis()
increments, that will mean a max error of 1ms. Not important, when in this time range and also when you are usingmillis()
.chrisl– chrisl03/31/2021 21:42:16Commented Mar 31, 2021 at 21:42 -
what are the odds of hitting that at the exact ms out of thousands?dandavis– dandavis03/31/2021 22:51:19Commented Mar 31, 2021 at 22:51
-
1This has too much potential to go wrong in a real time environment and isn't better code than the one in the question. Besides, timers that depend on
millis()
should always beunsigned long
(oruint32_t
).StarCat– StarCat04/01/2021 07:50:10Commented Apr 1, 2021 at 7:50
unsigned long
as data type ofsendDataPrevMillis
millis()
returns 0 at startup? For debugging you could print the initial value and any following if the condition is met.