// https://www.reddit.com/r/arduino/comments/1430d8i/calibrate_hours_minutes_and_seconds_from_compile/?rdt=45393&onetap_auto=true
// https://github.com/ripred/CompileTime
// Global values used at runtime
uint32_t startTime;
volatile int16_t second, hour, minute;
void setCompileTime();
void updateTime();
void setup() {
setCompileTime();
Serial.begin(115200);
// put your setup code here, to run once:
}
void loop() {
static uint16_t lasth = hour, lastm = minute, lasts = second;
updateTime();
if (lasts != second || lastm != minute || lasth != hour) {
lasts = second;
lastm = minute;
lasth = hour;
char buff[16];
sprintf(buff, "%02d:%02d:%02d", hour, minute, second);
Serial.println(buff);
}
// put your main code here, to run repeatedly:
}
enum MagicNumbers : uint32_t {
secsPerMin = 60UL,
minsPerHour = 60UL,
secsPerHour = 3600UL,
// The number of microseconds to calibrate the internal PLL
// generated clock source to (if in use and adjusted):
uSecAdjust = 1000000,
};
void updateTime() {
uint32_t now_secs = (micros() / uSecAdjust) + startTime;
uint16_t curHour = now_secs / secsPerHour;
now_secs -= curHour * secsPerHour;
uint16_t curMinute = now_secs / secsPerMin;
now_secs -= curMinute * secsPerMin;
noInterrupts();
hour = curHour;
minute = curMinute;
second = now_secs;
interrupts();
}
void setCompileTime() {
// convert the digits from the ascii __TIME__ string into binary values:
char const tm[9] = __TIME__;
uint16_t curHour = ((uint32_t)(tm[0] - '0') * 10UL) + (uint32_t)(tm[1] - '0');
uint16_t curMinute = ((uint32_t)(tm[3] - '0') * 10UL) + (uint32_t)(tm[4] - '0');
uint16_t curSecond = ((uint32_t)(tm[6] - '0') * 10UL) + (uint32_t)(tm[7] - '0');
// Adjust for the time it took to upload: (change time as needed)
uint32_t upload_time_seconds = 4UL;
curSecond += upload_time_seconds;
while (curSecond >= secsPerMin) {
curSecond -= secsPerMin;
if (++curMinute >= minsPerHour) {
curMinute -= minsPerHour;
if (++curHour >= 24UL) {
curHour -= 24UL;
}
}
}
noInterrupts();
hour = curHour;
minute = curMinute;
second = curSecond;
interrupts();
// Set the starting time in seconds since midnight:
startTime = curHour * secsPerHour + curMinute * secsPerMin + curSecond;
}