Previously my rdc ds3231 program was running with this code, I don't know why it suddenly became a problem like this
========================================
INITIALIZING DS3231 RTC
========================================
DS3231 detected!
RTC has battery backup - time will persist
RTC Current Time: 00:00:00 52/83/2045
RTC time is valid - using RTC time
System time set from RTC: 00:00:00 52/83/2045
Timestamp: -1463725696
========================================
AUTO NTP SYNC STARTED
========================================
Trying NTP server: pool.ntp.org
Using timezone: UTC+7 (25200 seconds)
NTP Sync successful!
Server: pool.ntp.org
Time: 19:39:29 15/12/2025
NTP time saved to RTC
(RTC overwritten from NTP)
RTC INVALID: Year out of range (2108)
RTC SUSPICIOUS: Time diff too large (1518316001 seconds)
System: 19:40:25 15/12/2025
RTC: 45:162:00 51/41/2108
Keeping system time (RTC probably corrupted)
RTC corrupted, resetting to system time...
code
bool initRTC() {
Serial.println("\n========================================");
Serial.println("INITIALIZING DS3231 RTC");
Serial.println("========================================");
Wire.begin();
Wire.beginTransmission(0x68);
Wire.endTransmission();
if (!rtc.begin(&Wire)) {
Serial.println(" DS3231 not found!");
Serial.println(" - SDA -> GPIO21");
Serial.println(" - SCL -> GPIO22");
Serial.println(" - VCC -> 3.3V");
Serial.println(" - GND -> GND");
Serial.println(" - BATTERY -> CR2032 (optional)");
Serial.println("\n Running without RTC");
Serial.println(" Time will reset to 00:00:00 01/01/2000 on power loss");
Serial.println("========================================\n");
if (xSemaphoreTake(timeMutex, portMAX_DELAY) == pdTRUE) {
setTime(0, 0, 0, 1, 1, 2000);
time_t tempTime = now();
if (tempTime < 946684800) {
timeConfig.currentTime = 946684800;
} else {
timeConfig.currentTime = tempTime;
}
xSemaphoreGive(timeMutex);
}
return false;
}
Serial.println(" DS3231 detected!");
if (rtc.lostPower()) {
Serial.println(" RTC lost power - battery may be dead or missing");
Serial.println(" Install CR2032 battery for time persistence");
} else {
Serial.println(" RTC has battery backup - time will persist");
}
DateTime rtcNow = rtc.now();
Serial.printf("\nRTC Current Time: %02d:%02d:%02d %02d/%02d/%04d\n",
rtcNow.hour(), rtcNow.minute(), rtcNow.second(),
rtcNow.day(), rtcNow.month(), rtcNow.year());
// ================================
// CHECK IF RTC TIME IS VALID
// ================================
if (rtcNow.year() >= 2000 && rtcNow.year() <= 2100) {
Serial.println("\n RTC time is valid - using RTC time");
if (xSemaphoreTake(timeMutex, portMAX_DELAY) == pdTRUE) {
time_t rtcUnix = rtcNow.unixtime();
setTime(rtcNow.hour(), rtcNow.minute(), rtcNow.second(),
rtcNow.day(), rtcNow.month(), rtcNow.year());
timeConfig.currentTime = rtcUnix;
Serial.printf(" System time set from RTC: %02d:%02d:%02d %02d/%02d/%04d\n",
rtcNow.hour(), rtcNow.minute(), rtcNow.second(),
rtcNow.day(), rtcNow.month(), rtcNow.year());
Serial.printf(" Timestamp: %ld\n", timeConfig.currentTime);
xSemaphoreGive(timeMutex);
if (displayQueue != NULL) {
DisplayUpdate update;
update.type = DisplayUpdate::TIME_UPDATE;
xQueueSend(displayQueue, &update, 0);
}
}
} else {
Serial.println("\n RTC time invalid (year out of range)");
Serial.println(" Resetting to default time: 00:00:00 01/01/2000");
DateTime defaultTime(2000, 1, 1, 0, 0, 0);
rtc.adjust(defaultTime);
if (xSemaphoreTake(timeMutex, portMAX_DELAY) == pdTRUE) {
setTime(0, 0, 0, 1, 1, 2000);
time_t tempTime = now();
if (tempTime < 946684800) {
timeConfig.currentTime = 946684800;
} else {
timeConfig.currentTime = tempTime;
}
Serial.println(" System time set to 00:00:00 01/01/2000");
Serial.printf(" Timestamp: %ld\n", timeConfig.currentTime);
Serial.println(" RTC will maintain this until NTP sync");
xSemaphoreGive(timeMutex);
if (displayQueue != NULL) {
DisplayUpdate update;
update.type = DisplayUpdate::TIME_UPDATE;
xQueueSend(displayQueue, &update, 0);
}
}
}
Serial.println("========================================\n");
return true;
}
code
void ntpTask(void *parameter) {
esp_task_wdt_add(NULL);
while (true) {
esp_task_wdt_reset();
uint32_t notifyValue = ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(30000));
if (notifyValue == 0) {
esp_task_wdt_reset();
continue;
}
ntpSyncInProgress = true;
ntpSyncCompleted = false;
Serial.println("\n========================================");
Serial.println("AUTO NTP SYNC STARTED");
Serial.println("========================================");
if (xSemaphoreTake(timeMutex, portMAX_DELAY) == pdTRUE) {
bool syncSuccess = false;
int serverIndex = 0;
while (!syncSuccess && serverIndex < NTP_SERVER_COUNT) {
esp_task_wdt_reset();
Serial.printf("Trying NTP server: %s\n", ntpServers[serverIndex]);
timeClient.setPoolServerName(ntpServers[serverIndex]);
int offsetSeconds = timezoneOffset * 3600;
timeClient.setTimeOffset(offsetSeconds);
Serial.printf(" Using timezone: UTC%s%d (%d seconds)\n",
timezoneOffset >= 0 ? "+" : "", timezoneOffset, offsetSeconds);
timeClient.begin();
unsigned long startTime = millis();
bool updateResult = false;
while (millis() - startTime < 5000) {
updateResult = timeClient.forceUpdate();
if (updateResult) break;
esp_task_wdt_reset();
vTaskDelay(pdMS_TO_TICKS(100));
}
if (updateResult) {
time_t ntpTime = timeClient.getEpochTime();
timeConfig.currentTime = ntpTime;
setTime(timeConfig.currentTime);
timeConfig.ntpSynced = true;
syncSuccess = true;
timeConfig.ntpServer = String(ntpServers[serverIndex]);
Serial.println("NTP Sync successful!");
Serial.printf(" Server: %s\n", ntpServers[serverIndex]);
Serial.printf(" Time: %02d:%02d:%02d %02d/%02d/%04d\n",
hour(ntpTime), minute(ntpTime), second(ntpTime),
day(ntpTime), month(ntpTime), year(ntpTime));
if (rtcAvailable) {
DateTime dt(year(ntpTime),
month(ntpTime),
day(ntpTime),
hour(ntpTime),
minute(ntpTime),
second(ntpTime));
rtc.adjust(dt);
Serial.println("NTP time saved to RTC");
Serial.println(" (RTC overwritten from NTP)");
}
DisplayUpdate update;
update.type = DisplayUpdate::TIME_UPDATE;
xQueueSend(displayQueue, &update, 0);
Serial.println("Post-NTP: Checking prayer times...");
if (prayerConfig.latitude.length() > 0 && prayerConfig.longitude.length() > 0) {
Serial.println(" City configured: " + prayerConfig.selectedCity);
Serial.println(" Updating prayer times with correct date...");
xSemaphoreGive(timeMutex);
esp_task_wdt_reset();
getPrayerTimesByCoordinates(
prayerConfig.latitude,
prayerConfig.longitude);
Serial.println("Prayer times updated post-NTP sync");
xSemaphoreTake(timeMutex, portMAX_DELAY);
} else {
Serial.println("No city coordinates - skipping prayer update");
xSemaphoreGive(timeMutex);
xSemaphoreTake(timeMutex, portMAX_DELAY);
}
Serial.println("========================================\n");
break;
}
serverIndex++;
esp_task_wdt_reset();
vTaskDelay(pdMS_TO_TICKS(500));
}
if (!syncSuccess) {
Serial.println("All NTP servers failed!");
Serial.println(" Keeping current time");
Serial.println("========================================\n");
}
ntpSyncInProgress = false;
ntpSyncCompleted = syncSuccess;
xSemaphoreGive(timeMutex);
} else {
Serial.println("Failed to acquire time mutex");
Serial.println("========================================\n");
ntpSyncInProgress = false;
ntpSyncCompleted = false;
}
esp_task_wdt_reset();
}
}
code
void rtcSyncTask(void *parameter) {
TickType_t xLastWakeTime = xTaskGetTickCount();
const TickType_t xFrequency = pdMS_TO_TICKS(60000); // Every 1 minute
while (true) {
if (rtcAvailable) {
DateTime rtcTime = rtc.now();
if (xSemaphoreTake(timeMutex, pdMS_TO_TICKS(100)) == pdTRUE) {
time_t systemTime = timeConfig.currentTime;
time_t rtcUnix = rtcTime.unixtime();
// ========================================
// VALIDASI KETAT
// ========================================
bool rtcValid = true;
if (rtcTime.year() < 2000 || rtcTime.year() > 2100) {
Serial.println("RTC INVALID: Year out of range (" + String(rtcTime.year()) + ")");
rtcValid = false;
}
long timeDiff = abs(systemTime - rtcUnix);
if (systemTime >= 946684800 && timeDiff > 3600) {
Serial.printf("RTC SUSPICIOUS: Time diff too large (%ld seconds)\n", timeDiff);
Serial.printf(" System: %02d:%02d:%02d %02d/%02d/%04d\n",
hour(systemTime), minute(systemTime), second(systemTime),
day(systemTime), month(systemTime), year(systemTime));
Serial.printf(" RTC: %02d:%02d:%02d %02d/%02d/%04d\n",
rtcTime.hour(), rtcTime.minute(), rtcTime.second(),
rtcTime.day(), rtcTime.month(), rtcTime.year());
Serial.println("Keeping system time (RTC probably corrupted)");
rtcValid = false;
}
// ========================================
// Hanya update jika RTC valid DAN selisih kecil
// ========================================
if (rtcValid && timeDiff > 2) {
timeConfig.currentTime = rtcUnix;
setTime(rtcUnix);
Serial.println("System time synced from RTC");
Serial.printf(" RTC: %02d:%02d:%02d %02d/%02d/%04d\n",
rtcTime.hour(), rtcTime.minute(), rtcTime.second(),
rtcTime.day(), rtcTime.month(), rtcTime.year());
DisplayUpdate update;
update.type = DisplayUpdate::TIME_UPDATE;
xQueueSend(displayQueue, &update, 0);
} else if (!rtcValid) {
Serial.println("RTC corrupted, resetting to system time...");
DateTime fixedTime(
year(systemTime),
month(systemTime),
day(systemTime),
hour(systemTime),
minute(systemTime),
second(systemTime));
rtc.adjust(fixedTime);
Serial.println("RTC reset to system time");
}
xSemaphoreGive(timeMutex);
}
}
vTaskDelayUntil(&xLastWakeTime, xFrequency);
}
}