pleasedontcode

# Time Sync rev_09

Mar 15th, 2026
38
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Arduino 29.23 KB | None | 0 0
  1. /********* Pleasedontcode.com **********
  2.  
  3.     Pleasedontcode thanks you for automatic code generation! Enjoy your code!
  4.  
  5.     - Terms and Conditions:
  6.     You have a non-exclusive, revocable, worldwide, royalty-free license
  7.     for personal and commercial use. Attribution is optional; modifications
  8.     are allowed, but you're responsible for code maintenance. We're not
  9.     liable for any loss or damage. For full terms,
  10.     please visit pleasedontcode.com/termsandconditions.
  11.  
  12.     - Project: # Time Sync
  13.     - Version: 009
  14.     - Source Code NOT compiled for: ESP32S3 Dev Module
  15.     - Source Code created on: 2026-03-15 23:50:04
  16.  
  17. ********* Pleasedontcode.com **********/
  18.  
  19. /****** SYSTEM REQUIREMENTS *****/
  20. /****** SYSTEM REQUIREMENT 1 *****/
  21.     /* ESP32-S3 hard reset system clock to 2024-03-16 */
  22.     /* baseline before NTP sync to fix incorrect */
  23.     /* date/time issues, then synchronize with NTP server */
  24.     /* for accurate time */
  25. /****** SYSTEM REQUIREMENT 2 *****/
  26.     /* Connect to WiFi "二楼" with password "88888888" and */
  27.     /* display accurate HH:MM:SS on 1.8 inch ST7735S */
  28.     /* display in cyan color, updating every second */
  29. /****** SYSTEM REQUIREMENT 3 *****/
  30.     /* Output detailed time synchronization debug */
  31.     /* information to serial (9600 baud) showing system */
  32.     /* clock reset, NTP sync status, and synchronized */
  33.     /* time */
  34. /****** END SYSTEM REQUIREMENTS *****/
  35.  
  36.  
  37. /* START CODE */
  38.  
  39. // System Requirements:
  40. // 1. "ESP32-S3 hard reset system clock to 2024-03-16 baseline before NTP sync to fix incorrect date/time issues, then synchronize with NTP server for accurate time"
  41. // 2. "Connect to WiFi "二楼" with password "88888888" and display accurate HH:MM:SS on 1.8 inch ST7735S display in cyan color, updating every second"
  42. // 3. "Output detailed time synchronization debug information to serial (9600 baud) showing system clock reset, NTP sync status, and synchronized time"
  43.  
  44. // Include core Arduino WiFi and time libraries for network and NTP functionality
  45. #include <WiFi.h>
  46. #include <time.h>
  47. #include <sys/time.h>
  48.  
  49. // Include Adafruit graphics and ST7735S display libraries for display support
  50. #include <Adafruit_GFX.h>
  51. #include <Adafruit_ST7735.h>
  52.  
  53. // Include SPI library for hardware SPI communication with ST7735S display
  54. #include <SPI.h>
  55.  
  56. // WiFi Credentials - Configure with your WiFi network details
  57. const char* ssid = "二楼";
  58. const char* password = "88888888";
  59.  
  60. // NTP Server Configuration for time synchronization
  61. const char* ntpServer = "pool.ntp.org";
  62. const long gmtOffset_sec = 0;
  63. const long daylightOffset_sec = 0;
  64.  
  65. // Hard reset baseline date for system clock (2024-03-16 00:00:00 UTC)
  66. // This timestamp represents March 16, 2024 at midnight UTC
  67. // Used to set system clock before NTP sync to ensure valid baseline
  68. const time_t BASELINE_TIMESTAMP = 1710547200;  // 2024-03-16 00:00:00 UTC
  69.  
  70. // ST7735S 1.8 inch Display Configuration and pin definitions for ESP32-S3
  71. // Pin configuration for 1.8 inch ST7735S display with black tab
  72. // CS (Chip Select): GPIO 5 - Active low, selects the display for SPI communication
  73. // DC (Data/Command): GPIO 16 - High for data mode, low for command mode
  74. // RST (Reset): GPIO 15 - Active low reset signal to restart display controller
  75. // SCLK (Serial Clock): GPIO 18 - SPI clock signal for synchronizing data transfer
  76. // MOSI (Master Out Slave In): GPIO 11 - Data line from ESP32-S3 to display
  77. #define TFT_CS    5
  78. #define TFT_RST   15
  79. #define TFT_DC    16
  80. #define TFT_MOSI  11
  81. #define TFT_SCLK  18
  82.  
  83. // Create display object instance for ST7735S communication with proper ESP32-S3 SPI pins
  84. // Adafruit_ST7735 software SPI constructor takes: (CS, DC, MOSI, SCLK, RST)
  85. // This creates a 1.8 inch display object that will be initialized with INITR_18BLACKTAB
  86. Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCLK, TFT_RST);
  87.  
  88. // Global variables for time tracking and display updates
  89. // lastTimeUpdate: timestamp of last display refresh to control update rate
  90. // TIME_UPDATE_INTERVAL: milliseconds between display refreshes (1000ms = 1 second)
  91. unsigned long lastTimeUpdate = 0;
  92. const unsigned long TIME_UPDATE_INTERVAL = 1000;
  93.  
  94. // Function prototypes declaring all functions used in the sketch
  95. // Allows functions to be called in any order within the file
  96. void initializeDisplay();
  97. void resetSystemClock();
  98. void connectToWiFi();
  99. void syncTimeWithNTP();
  100. String getCurrentTimeString();
  101. String getFormattedTimeString();
  102. void displayCurrentTime();
  103. void displayInitializationUI();
  104. void displayWiFiStatusUI();
  105. void displayClockResetUI();
  106. void displayNTPSyncUI();
  107. void printDebugSeparator();
  108.  
  109. // Main setup function - runs once at power on or reset
  110. // Initializes all hardware, resets system clock, connects to WiFi, syncs time, and starts the main loop
  111. void setup() {
  112.   // Initialize serial communication for debugging at 9600 baud rate
  113.   // This allows the program to send diagnostic messages to the Serial Monitor
  114.   // Using 9600 baud for compatibility with most serial monitoring tools
  115.   // Delay ensures serial port is ready before sending first message
  116.   Serial.begin(9600);
  117.   delay(2000);
  118.  
  119.   // Print system startup message with separator for visibility
  120.   printDebugSeparator();
  121.   Serial.println("========== WEATHER STATION INITIALIZATION ==========");
  122.   Serial.println("System startup at: " + String(__TIME__) + " on " + String(__DATE__));
  123.   Serial.println("Target: 1.8\" ST7735S Display, 128x160 pixels");
  124.   Serial.println("WiFi SSID: 二楼");
  125.   Serial.println("NTP Server: pool.ntp.org (UTC+0)");
  126.   Serial.println("System Clock Reset Baseline: 2024-03-16 00:00:00 UTC");
  127.   printDebugSeparator();
  128.  
  129.   // Initialize SPI interface for ST7735S display communication on ESP32-S3
  130.   // SPI.begin(SCLK, MISO, MOSI, CS) configures the SPI bus with specified pins
  131.   // MISO is -1 because the display is write-only (no data read from display)
  132.   // This sets up VSPI with GPIO 18 (SCLK), GPIO 11 (MOSI), GPIO 5 (CS)
  133.   // ESP32-S3 uses GPIO matrix to dynamically assign pins to SPI peripheral
  134.   SPI.begin(TFT_SCLK, -1, TFT_MOSI, TFT_CS);
  135.  
  136.   // Initialize and configure ST7735S 1.8 inch display with proper hardware setup
  137.   // This function sets up the display controller with correct initialization sequence
  138.   initializeDisplay();
  139.  
  140.   // Display initialization message on screen during setup sequence
  141.   // Shows "CLOCK" title and "Initializing..." status to inform user device is starting
  142.   displayInitializationUI();
  143.  
  144.   // Perform hard reset of system clock to 2024-03-16 baseline before NTP sync
  145.   // This ensures system has valid time reference point for NTP synchronization
  146.   // Without baseline, NTP sync may fail or produce incorrect results
  147.   resetSystemClock();
  148.  
  149.   // Connect to WiFi network with provided SSID and password credentials
  150.   // Shows WiFi connection status on display and serial monitor
  151.   connectToWiFi();
  152.  
  153.   // Synchronize system time with NTP server via internet connection
  154.   // Contacts pool.ntp.org and updates ESP32-S3 internal RTC to network time
  155.   syncTimeWithNTP();
  156.  
  157.   // Display the initial time after all initialization is complete
  158.   // This clears previous setup messages and shows the current time
  159.   displayCurrentTime();
  160.  
  161.   // Send completion message to serial monitor for debugging
  162.   Serial.println();
  163.   printDebugSeparator();
  164.   Serial.println("Setup complete! System ready for time display.");
  165.   Serial.println("Time display updates every second on ST7735S in cyan color.");
  166.   printDebugSeparator();
  167. }
  168.  
  169. // Main loop function - runs repeatedly during normal operation
  170. // Continuously updates the time display every second using non-blocking timers
  171. void loop() {
  172.   // Get current system time in milliseconds since device startup (millis() overflows after ~49 days)
  173.   unsigned long currentMillis = millis();
  174.  
  175.   // Non-blocking timer check: has enough time elapsed for next update?
  176.   // This approach avoids blocking the loop with delays while still updating every second
  177.   // Only refreshes display when TIME_UPDATE_INTERVAL milliseconds have passed
  178.   if (currentMillis - lastTimeUpdate >= TIME_UPDATE_INTERVAL) {
  179.     // Update last time tracker to current time for next comparison
  180.     lastTimeUpdate = currentMillis;
  181.     // Get current time from system clock and display it on ST7735S
  182.     // This happens once per second due to the interval check above
  183.     displayCurrentTime();
  184.   }
  185.  
  186.   // Small delay to allow other tasks and prevent watchdog timer from resetting device
  187.   // 100ms delay is short enough to update display smoothly, long enough to save power
  188.   delay(100);
  189. }
  190.  
  191. // Initialize ST7735S 1.8 inch display with proper configuration for black tab variant
  192. // Sets up display controller with INITR_18BLACKTAB, configures rotation and clears screen
  193. // This function must be called before any display operations
  194. void initializeDisplay() {
  195.   // Initialize the ST7735S display controller with 1.8 inch black tab variant
  196.   // INITR_18BLACKTAB is the initialization routine for the specific 1.8 inch model
  197.   // This sends the correct command sequence to the ST7735 controller IC
  198.   // Configures display size to 128x160 pixels with black tab orientation
  199.   tft.initR(INITR_18BLACKTAB);
  200.  
  201.   // Set display rotation to landscape mode (rotation value 1)
  202.   // Rotation options: 0=portrait (height > width), 1=landscape (width > height)
  203.   //                 2=portrait inverted, 3=landscape inverted
  204.   // Rotation 1 gives us 160 pixels wide by 128 pixels tall on this 1.8 inch screen
  205.   tft.setRotation(1);
  206.  
  207.   // Fill entire display with black background color (RGB 0, 0, 0)
  208.   // This clears any residual data from previous power cycles or display operation
  209.   // Ensures clean, blank slate before displaying any content
  210.   tft.fillScreen(ST7735_BLACK);
  211.  
  212.   // Send initialization confirmation to serial monitor for debugging
  213.   // Helps verify display initialization succeeded during power-on diagnostics
  214.   Serial.println("[DISPLAY] Initialized: ST7735S 1.8\", 128x160 pixels, landscape mode");
  215.   Serial.println("[DISPLAY] Display rotation: landscape (1)");
  216.   Serial.println("[DISPLAY] Background color: black (0, 0, 0)");
  217.   Serial.println("[DISPLAY] Ready for content output");
  218. }
  219.  
  220. // Display initialization message on ST7735S screen
  221. // Shows "CLOCK" title and "Initializing..." message during device startup
  222. // Provides visual feedback to user that device is starting up
  223. void displayInitializationUI() {
  224.   // Fill screen with black background for clean, professional appearance
  225.   // Removes any previous content and provides contrast for text
  226.   tft.fillScreen(ST7735_BLACK);
  227.  
  228.   // Set text color to white for maximum contrast against black background
  229.   // White text is easy to read during startup sequence
  230.   tft.setTextColor(ST7735_WHITE);
  231.  
  232.   // Set text size to 2 (2x magnification from default size)
  233.   // Larger text is more visible and conveys importance of initialization message
  234.   tft.setTextSize(2);
  235.  
  236.   // Position text cursor at x=15, y=40 for centered title display
  237.   // Sets the starting position for the next text output
  238.   tft.setCursor(15, 40);
  239.   // Print "CLOCK" title on display to identify device function
  240.   tft.println("CLOCK");
  241.  
  242.   // Reduce text size to 1 for status message below title
  243.   tft.setTextSize(1);
  244.   // Position cursor for status message below the title
  245.   tft.setCursor(20, 75);
  246.   // Print "Initializing..." to show device is in startup process
  247.   tft.println("Initializing...");
  248.  
  249.   // Wait 1.5 seconds to allow user to see initialization message
  250.   // Prevents screen from changing too quickly during startup sequence
  251.   delay(1500);
  252.  
  253.   // Send debug message to serial monitor confirming initialization display
  254.   Serial.println("[UI] Initialization screen displayed on ST7735S");
  255. }
  256.  
  257. // Hard reset system clock to 2024-03-16 baseline before NTP synchronization
  258. // This ensures system has a valid time reference point for NTP sync to work correctly
  259. // Without this baseline, system clock may be too far in past/future for NTP to process
  260. void resetSystemClock() {
  261.   // Display clock reset UI on screen to show user what's happening
  262.   displayClockResetUI();
  263.  
  264.   // Send clock reset start message to serial monitor with timestamp details
  265.   Serial.println();
  266.   printDebugSeparator();
  267.   Serial.println("[CLOCK RESET] Starting hard reset of system clock...");
  268.   Serial.println("[CLOCK RESET] Setting baseline to: 2024-03-16 00:00:00 UTC");
  269.  
  270.   // Create timeval structure for system time setting
  271.   // timeval contains seconds and microseconds since Unix epoch
  272.   struct timeval tv;
  273.   // Set seconds to baseline timestamp (2024-03-16 00:00:00 UTC)
  274.   tv.tv_sec = BASELINE_TIMESTAMP;
  275.   // Set microseconds to zero for clean baseline
  276.   tv.tv_usec = 0;
  277.  
  278.   // Get current system time before reset for comparison in debug output
  279.   time_t timeBeforeReset = time(nullptr);
  280.   struct tm* tmBeforeReset = localtime(&timeBeforeReset);
  281.  
  282.   // Print current system time before reset
  283.   Serial.print("[CLOCK RESET] Time BEFORE reset: ");
  284.   Serial.println(asctime(tmBeforeReset));
  285.  
  286.   // Perform actual system clock reset using settimeofday()
  287.   // This sets the ESP32-S3 internal RTC to the baseline timestamp
  288.   // Returns 0 on success, -1 on failure (should always succeed on ESP32-S3)
  289.   int resetResult = settimeofday(&tv, NULL);
  290.  
  291.   // Check if clock reset was successful
  292.   if (resetResult == 0) {
  293.     // Clock reset succeeded - get new time and display it
  294.     Serial.println("[CLOCK RESET] System clock reset successful!");
  295.    
  296.     // Small delay to allow clock update to take effect
  297.     delay(100);
  298.    
  299.     // Get system time after reset for verification
  300.     time_t timeAfterReset = time(nullptr);
  301.     struct tm* tmAfterReset = localtime(&timeAfterReset);
  302.    
  303.     // Print system time after reset for verification
  304.     Serial.print("[CLOCK RESET] Time AFTER reset:  ");
  305.     Serial.println(asctime(tmAfterReset));
  306.    
  307.     // Calculate and display time difference for verification
  308.     long timeDifference = timeAfterReset - timeBeforeReset;
  309.     Serial.print("[CLOCK RESET] Time adjustment: ");
  310.     Serial.print(timeDifference);
  311.     Serial.println(" seconds");
  312.    
  313.   } else {
  314.     // Clock reset failed - send error message
  315.     Serial.println("[CLOCK RESET] ERROR: System clock reset failed!");
  316.     Serial.println("[CLOCK RESET] NTP sync may not work correctly");
  317.   }
  318.  
  319.   Serial.println("[CLOCK RESET] Baseline clock reset complete, ready for NTP sync");
  320.   printDebugSeparator();
  321. }
  322.  
  323. // Display clock reset status message on ST7735S screen
  324. // Shows user that system clock is being reset to baseline value
  325. // This UI appears during the clock reset operation before NTP sync
  326. void displayClockResetUI() {
  327.   // Fill screen with black background for clean display
  328.   tft.fillScreen(ST7735_BLACK);
  329.  
  330.   // Set text color to yellow to indicate reset operation in progress
  331.   // Yellow provides good visibility and indicates a state-change operation
  332.   tft.setTextColor(ST7735_YELLOW);
  333.  
  334.   // Set text size to 2 for prominent message
  335.   tft.setTextSize(2);
  336.   tft.setCursor(10, 40);
  337.   // Print "CLOCK" label on display
  338.   tft.println("CLOCK");
  339.  
  340.   // Reduce text size to 1 for status message below title
  341.   tft.setTextSize(1);
  342.   tft.setTextColor(ST7735_WHITE);
  343.   tft.setCursor(10, 75);
  344.   // Print "Resetting..." message
  345.   tft.println("Resetting to");;
  346.   tft.setCursor(10, 85);
  347.   tft.println("2024-03-16...");
  348.  
  349.   // Display reset message for visibility during operation
  350.   delay(1500);
  351.  
  352.   // Send debug message to serial monitor
  353.   Serial.println("[UI] Clock reset screen displayed on ST7735S");
  354. }
  355.  
  356. // Connect ESP32-S3 to WiFi network with credential verification
  357. // Attempts WiFi connection with timeout, displays status on screen and serial monitor
  358. // Handles both success and failure cases with appropriate visual feedback
  359. void connectToWiFi() {
  360.   // Clear screen with black background to prepare for WiFi connection display
  361.   tft.fillScreen(ST7735_BLACK);
  362.  
  363.   // Display WiFi connection attempt message and animation on screen
  364.   displayWiFiStatusUI();
  365.  
  366.   // Send WiFi connection attempt message to serial monitor for debugging
  367.   Serial.println();
  368.   printDebugSeparator();
  369.   Serial.println("[WiFi] Attempting WiFi connection...");
  370.   Serial.print("[WiFi] SSID: ");
  371.   Serial.println(ssid);
  372.   Serial.print("[WiFi] Password: ");
  373.   Serial.println(password);
  374.  
  375.   // Set WiFi mode to STA (Station) to enable connection to existing WiFi network
  376.   // STA mode allows ESP32-S3 to connect as a client to access point (router)
  377.   WiFi.mode(WIFI_STA);
  378.  
  379.   // Initiate WiFi connection with network SSID and password
  380.   // WiFi.begin() starts the connection process but does not wait for completion
  381.   WiFi.begin(ssid, password);
  382.  
  383.   // Wait for WiFi connection with timeout to prevent indefinite blocking
  384.   // Maximum wait: 40 attempts × 500ms = 20 seconds
  385.   // If connection fails after timeout, proceed to next step anyway
  386.   int attempts = 0;
  387.   Serial.print("[WiFi] Connection progress: ");
  388.   while (WiFi.status() != WL_CONNECTED && attempts < 40) {
  389.     delay(500);
  390.     // Print dot to serial monitor to show connection attempt progress
  391.     Serial.print(".");
  392.     attempts++;
  393.   }
  394.   Serial.println();
  395.  
  396.   // Check if WiFi connection succeeded by examining WiFi status
  397.   if (WiFi.status() == WL_CONNECTED) {
  398.     // WiFi connection successful - send detailed information to serial monitor
  399.     Serial.println("[WiFi] WiFi connected successfully!");
  400.     Serial.print("[WiFi] Connection attempts: ");
  401.     Serial.println(attempts);
  402.     Serial.print("[WiFi] Assigned IP address: ");
  403.     Serial.println(WiFi.localIP());
  404.     Serial.print("[WiFi] Signal strength (RSSI): ");
  405.     Serial.print(WiFi.RSSI());
  406.     Serial.println(" dBm");
  407.    
  408.     // Clear screen and display WiFi success message in green color
  409.     tft.fillScreen(ST7735_BLACK);
  410.     tft.setTextColor(ST7735_GREEN);
  411.     tft.setTextSize(2);
  412.     tft.setCursor(10, 50);
  413.     tft.println("WiFi OK");
  414.    
  415.     // Display assigned IP address on screen below success message
  416.     tft.setTextSize(1);
  417.     tft.setTextColor(ST7735_WHITE);
  418.     tft.setCursor(10, 80);
  419.     tft.print("IP:");
  420.     tft.setCursor(10, 90);
  421.     tft.println(WiFi.localIP());
  422.    
  423.     // Display WiFi success message for 2 seconds before proceeding to NTP sync
  424.     delay(2000);
  425.   } else {
  426.     // WiFi connection failed after timeout - send error message to serial monitor
  427.     Serial.println("[WiFi] ERROR: Failed to connect to WiFi network");
  428.     Serial.print("[WiFi] Connection attempts: ");
  429.     Serial.println(attempts);
  430.     Serial.print("[WiFi] WiFi status code: ");
  431.     Serial.println(WiFi.status());
  432.    
  433.     // Clear screen and display failure message in red color
  434.     tft.fillScreen(ST7735_BLACK);
  435.     tft.setTextColor(ST7735_RED);
  436.     tft.setTextSize(2);
  437.     tft.setCursor(10, 50);
  438.     tft.println("WiFi FAIL");
  439.    
  440.     // Display troubleshooting message below failure message
  441.     tft.setTextSize(1);
  442.     tft.setTextColor(ST7735_WHITE);
  443.     tft.setCursor(10, 80);
  444.     tft.println("Check SSID/PWD");
  445.    
  446.     // Display failure message for 2 seconds before proceeding
  447.     // Device continues to operate without WiFi connection if NTP sync not required
  448.     delay(2000);
  449.   }
  450.  
  451.   printDebugSeparator();
  452. }
  453.  
  454. // Display WiFi connection status message during connection attempt
  455. // Shows user that device is attempting to connect to WiFi network
  456. // This UI appears while the WiFi connection is in progress
  457. void displayWiFiStatusUI() {
  458.   // Set text color to white for good visibility against black background
  459.   tft.setTextColor(ST7735_WHITE);
  460.  
  461.   // Set larger text size (2) for title emphasis
  462.   // Size 2 provides 2x magnification from default character size
  463.   tft.setTextSize(2);
  464.   tft.setCursor(10, 40);
  465.   // Print "WiFi" label on display
  466.   tft.println("WiFi");
  467.  
  468.   // Reduce text size to 1 for status message below title
  469.   tft.setTextSize(1);
  470.   tft.setCursor(20, 75);
  471.   // Print "Connecting..." to show WiFi connection is in progress
  472.   tft.println("Connecting...");
  473. }
  474.  
  475. // Synchronize system time with NTP server via internet connection
  476. // Sets system clock to match NTP server time, displays status on screen
  477. // This ensures accurate time display synchronized with network time protocol
  478. void syncTimeWithNTP() {
  479.   // Display NTP synchronization status on screen to inform user
  480.   displayNTPSyncUI();
  481.  
  482.   // Send NTP sync start message to serial monitor for debugging
  483.   Serial.println();
  484.   printDebugSeparator();
  485.   Serial.println("[NTP] Starting NTP time synchronization...");
  486.   Serial.print("[NTP] NTP Server: ");
  487.   Serial.println(ntpServer);
  488.   Serial.print("[NTP] GMT Offset: ");
  489.   Serial.print(gmtOffset_sec);
  490.   Serial.println(" seconds");
  491.   Serial.print("[NTP] Daylight Offset: ");
  492.   Serial.print(daylightOffset_sec);
  493.   Serial.println(" seconds");
  494.  
  495.   // Get time before NTP sync for comparison
  496.   time_t timeBefore = time(nullptr);
  497.   struct tm* tmBefore = localtime(&timeBefore);
  498.   Serial.print("[NTP] Time BEFORE sync: ");
  499.   Serial.println(asctime(tmBefore));
  500.  
  501.   // Configure time synchronization with NTP server and timezone offset
  502.   // configTime() sets up time sync with specified NTP server
  503.   // gmtOffset_sec: offset from UTC in seconds (0 = UTC+0)
  504.   // daylightOffset_sec: daylight saving time offset in seconds (0 = none)
  505.   configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
  506.  
  507.   // Wait for time to be synchronized from NTP server with timeout
  508.   Serial.print("[NTP] Sync progress: ");
  509.   time_t now = time(nullptr);
  510.   int attempts = 0;
  511.  
  512.   // Poll system time until it's been set from NTP server
  513.   // time_t value > 86400 (24 hours) indicates time has been updated from network
  514.   // Wait maximum 50 attempts × 500ms = 25 seconds for NTP response
  515.   while (now < 24 * 3600 && attempts < 50) {
  516.     delay(500);
  517.     // Print dot to serial monitor showing sync attempt progress
  518.     Serial.print(".");
  519.     now = time(nullptr);
  520.     attempts++;
  521.   }
  522.  
  523.   // Print newline to complete serial monitor output formatting
  524.   Serial.println();
  525.  
  526.   // Check if NTP sync was successful
  527.   if (now > 24 * 3600) {
  528.     // NTP sync successful - get and display synchronized time
  529.     Serial.println("[NTP] NTP synchronization successful!");
  530.    
  531.     // Get current synchronized time and display in human-readable format
  532.     struct tm timeinfo = *localtime(&now);
  533.     Serial.print("[NTP] Time AFTER sync:  ");
  534.     Serial.println(asctime(&timeinfo));
  535.    
  536.     // Display detailed time breakdown
  537.     Serial.print("[NTP] Synced Date: ");
  538.     Serial.printf("%04d-%02d-%02d ",
  539.                   timeinfo.tm_year + 1900,
  540.                   timeinfo.tm_mon + 1,
  541.                   timeinfo.tm_mday);
  542.     Serial.printf("Time: %02d:%02d:%02d UTC\n",
  543.                   timeinfo.tm_hour,
  544.                   timeinfo.tm_min,
  545.                   timeinfo.tm_sec);
  546.    
  547.     // Calculate time difference between before and after
  548.     long timeDifference = now - timeBefore;
  549.     Serial.print("[NTP] Sync attempts needed: ");
  550.     Serial.println(attempts);
  551.     Serial.print("[NTP] Time difference: ");
  552.     Serial.print(timeDifference);
  553.     Serial.println(" seconds");
  554.    
  555.     // Display NTP sync success on ST7735S screen in green color
  556.     tft.fillScreen(ST7735_BLACK);
  557.     tft.setTextColor(ST7735_GREEN);
  558.     tft.setTextSize(2);
  559.     tft.setCursor(15, 50);
  560.     // Print "NTP SYNC" label on display
  561.     tft.println("NTP SYNC");
  562.    
  563.     // Display confirmation message below title in white text
  564.     tft.setTextSize(1);
  565.     tft.setTextColor(ST7735_WHITE);
  566.     tft.setCursor(20, 85);
  567.     // Print "Time acquired" message
  568.     tft.println("Time acquired");
  569.    
  570.   } else {
  571.     // NTP sync failed - send error message
  572.     Serial.println("[NTP] ERROR: NTP synchronization timeout!");
  573.     Serial.print("[NTP] Sync attempts made: ");
  574.     Serial.println(attempts);
  575.     Serial.println("[NTP] Current system time may be inaccurate");
  576.    
  577.     // Display NTP sync failure on screen in red color
  578.     tft.fillScreen(ST7735_BLACK);
  579.     tft.setTextColor(ST7735_RED);
  580.     tft.setTextSize(2);
  581.     tft.setCursor(20, 50);
  582.     // Print "NTP FAIL" label on display
  583.     tft.println("NTP FAIL");
  584.    
  585.     // Display error message below title
  586.     tft.setTextSize(1);
  587.     tft.setTextColor(ST7735_WHITE);
  588.     tft.setCursor(20, 85);
  589.     // Print failure reason
  590.     tft.println("Timeout");
  591.   }
  592.  
  593.   // Display NTP result message for 1.5 seconds before clearing to show time
  594.   delay(1500);
  595.  
  596.   Serial.println("[NTP] NTP synchronization phase complete");
  597.   printDebugSeparator();
  598. }
  599.  
  600. // Display NTP synchronization in progress message on screen
  601. // Shows user that device is synchronizing time with NTP server
  602. // This UI appears while waiting for NTP time synchronization to complete
  603. void displayNTPSyncUI() {
  604.   // Fill screen with black background for clean display appearance
  605.   tft.fillScreen(ST7735_BLACK);
  606.  
  607.   // Set text color to white for good contrast against black background
  608.   tft.setTextColor(ST7735_WHITE);
  609.  
  610.   // Set text size to 2 for larger, more visible title
  611.   tft.setTextSize(2);
  612.   tft.setCursor(15, 40);
  613.   // Print "NTP" label on display
  614.   tft.println("NTP");
  615.  
  616.   // Reduce text size to 1 for status message below title
  617.   tft.setTextSize(1);
  618.   tft.setCursor(20, 75);
  619.   // Print "Syncing time..." message to show NTP sync is in progress
  620.   tft.println("Syncing time...");
  621. }
  622.  
  623. // Get current time as formatted HH:MM:SS string from system clock
  624. // Returns time string synchronized via NTP from the system's internal RTC
  625. // Format produces zero-padded two-digit hours, minutes, and seconds (e.g., "09:05:03")
  626. String getCurrentTimeString() {
  627.   // Get current time from system clock (synchronized via NTP during setup)
  628.   // time(nullptr) returns seconds elapsed since Unix epoch (January 1, 1970 00:00:00 UTC)
  629.   // This value is updated continuously by system RTC after NTP sync
  630.   time_t now = time(nullptr);
  631.  
  632.   // Convert time_t value to local time structure with hour, minute, second fields
  633.   // localtime() applies configured timezone offsets to create local time representation
  634.   // Returns pointer to static tm structure containing breakdown of time
  635.   struct tm* timeinfo = localtime(&now);
  636.  
  637.   // Create character buffer to hold formatted time string
  638.   // Buffer size 9: 8 characters for "HH:MM:SS" + 1 null terminator
  639.   char timeString[9];
  640.  
  641.   // Format time as HH:MM:SS with zero-padding for single-digit values
  642.   // %02d ensures always two digits, padding with leading zero if needed
  643.   // Examples: 09:05:03 (correct), NOT 9:5:3 (would be without padding)
  644.   // sprintf safely formats the string into the buffer with conversion specifiers
  645.   sprintf(timeString, "%02d:%02d:%02d",
  646.           timeinfo->tm_hour,  // Hours (0-23): midnight=0, noon=12, 11PM=23
  647.           timeinfo->tm_min,   // Minutes (0-59): from 00 to 59
  648.           timeinfo->tm_sec);  // Seconds (0-59): from 00 to 59
  649.  
  650.   // Convert character array to String object for display compatibility
  651.   // String class provides convenient handling for display operations
  652.   return String(timeString);
  653. }
  654.  
  655. // Get current date and time as full formatted string with date and time details
  656. // Returns formatted string like "2024-03-16 12:34:56"
  657. String getFormattedTimeString() {
  658.   // Get current time from system clock
  659.   time_t now = time(nullptr);
  660.  
  661.   // Convert to local time structure
  662.   struct tm* timeinfo = localtime(&now);
  663.  
  664.   // Create character buffer for formatted date-time string
  665.   char buffer[20];
  666.  
  667.   // Format as YYYY-MM-DD HH:MM:SS for detailed display
  668.   sprintf(buffer, "%04d-%02d-%02d %02d:%02d:%02d",
  669.           timeinfo->tm_year + 1900,  // Year (add 1900 since tm stores years since 1900)
  670.           timeinfo->tm_mon + 1,      // Month (add 1 since tm stores months 0-11)
  671.           timeinfo->tm_mday,         // Day of month (1-31)
  672.           timeinfo->tm_hour,         // Hour (0-23)
  673.           timeinfo->tm_min,          // Minute (0-59)
  674.           timeinfo->tm_sec);         // Second (0-59)
  675.  
  676.   return String(buffer);
  677. }
  678.  
  679. // Update and display current time on ST7735S screen
  680. // Gets current time from system clock and displays it in cyan color
  681. // Called every second (via TIME_UPDATE_INTERVAL) to continuously show current time
  682. void displayCurrentTime() {
  683.   // Get formatted current time string in HH:MM:SS format from system clock
  684.   // This function calls getCurrentTimeString() to get properly formatted time
  685.   String timeStr = getCurrentTimeString();
  686.  
  687.   // Get full formatted time string for serial debug output
  688.   String fullTimeStr = getFormattedTimeString();
  689.  
  690.   // Clear only the time display area to avoid flickering entire screen
  691.   // fillRect(x, y, width, height, color) erases rectangular region
  692.   // Coordinates: x=0, y=0 (top-left), width=128 (full width), height=50 (top half)
  693.   // This preserves any content below the time display area
  694.   tft.fillRect(0, 0, 128, 50, ST7735_BLACK);
  695.  
  696.   // Set text color to cyan (bright blue-green, RGB: 0, 255, 255)
  697.   // Cyan provides excellent contrast against black background
  698.   // Creates modern, clean appearance for time display
  699.   tft.setTextColor(ST7735_CYAN);
  700.  
  701.   // Set large text size (2) for prominent time display
  702.   // Size 2 means 2x magnification of default character dimensions
  703.   // Each character becomes taller and wider for better visibility
  704.   tft.setTextSize(2);
  705.  
  706.   // Position time at top-center of display for maximum visibility
  707.   // setCursor(x, y) sets starting position for next text output
  708.   // X position 18 centers the 8-character time string horizontally
  709.   // Y position 15 places it near the top of display with small margin
  710.   tft.setCursor(18, 15);
  711.  
  712.   // Print the time string in HH:MM:SS format to the ST7735S display
  713.   // println() outputs the string and moves cursor to next line
  714.   tft.println(timeStr);
  715.  
  716.   // Send current time to serial monitor for debugging and verification
  717.   Serial.print("[DISPLAY] Time updated: ");
  718.   Serial.println(fullTimeStr);
  719. }
  720.  
  721. // Print debug separator line for serial output organization
  722. // Makes serial debug output more readable by separating sections with clear markers
  723. void printDebugSeparator() {
  724.   // Print a line of dashes to visually separate debug sections
  725.   Serial.println("====================================================");
  726. }
  727.  
  728. /* END CODE */
  729.  
Advertisement
Add Comment
Please, Sign In to add comment