I ran into this while trying to make a battery monitor and wondered where I went wrong. Using RTClib
available in the Arduino IDE or from adafruit github, I ran into problems when trying to call now
within a while
loop inside of loop
. Here is a simple example:
#include "RTClib.h"
#define ledPIN 13
RTC_PCF8523 rtc;
void setup() {
// put your setup code here, to run once:
pinMode(ledPIN, OUTPUT);
digitalWrite(ledPIN, LOW);
Serial.begin(9600);
while(!Serial) {/* wait for Serial */}
rtc.begin();
rtc.start();
digitalWrite(ledPIN, HIGH);
}
void loop() {
// put your main code here, to run repeatedly:
char fmt[] = "YYYY/MM/DD-hh:mm:ss\n";
while (millis() < 60000){
Serial.println((rtc.now()).toString(fmt));
delay(5000);
}
Serial.println("Finished");
digitalWrite(ledPIN, LOW);
while(1) { /* do nothing forever */ }
}
The output of this little test will be the same time repeated every 5ish seconds. If it matters I am using a Feather M0 with the FeatherLogger that has an RTC on it. Changing this loop
function to this:
void loop() {
// put your main code here, to run repeatedly:
char fmt[] = "YYYY/MM/DD-hh:mm:ss\n";
if (millis() < 60000){
Serial.println((rtc.now()).toString(fmt));
delay(5000);
} else {
Serial.println("Finished");
digitalWrite(ledPIN, LOW);
while(1) { /* do nothing forever */ }
}
}
shows that now
does in fact update the time every 5ish seconds. I looked at the code for now
and it appears to do very basic i2c commands to get the time and report it back. The only thing I can think of is that the compiler created a (not so) temporary DateTime
object for me within the while
loop and the RTC library does not provide a convenient constructor or operator to overwrite the existing object.
I tested my theory with this
void loop() {
// put your main code here, to run repeatedly:
char fmt[] = "YYYY/MM/DD-hh:mm:ss\n";
while (millis() < 60000){
DateTime t1 = rtc.now();
Serial.println(t1.toString(fmt));
delay(5000);
}
Serial.println("Finished");
digitalWrite(ledPIN, LOW);
while(1) { /* do nothing forever */ }
}
But again, the time did not change so clearly I don't understand what's happening here. Why doesn't the rtc now
function work as intended within a while
loop inside the loop
function?
if (! rtc.begin()) { Serial.println("Couldn't find RTC"); Serial.flush(); abort(); }
can you add this part to your code to check whether it is giving any error or notwhile (millis() < 60000){ volatile DateTime time = rtc.now(); Serial.println(time.toString(fmt)); delay(5000); }
If this works, your theory about a wrong compiler optimization is correct.