Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /********* Pleasedontcode.com **********
- Pleasedontcode thanks you for automatic code generation! Enjoy your code!
- - Terms and Conditions:
- You have a non-exclusive, revocable, worldwide, royalty-free license
- for personal and commercial use. Attribution is optional; modifications
- are allowed, but you're responsible for code maintenance. We're not
- liable for any loss or damage. For full terms,
- please visit pleasedontcode.com/termsandconditions.
- - Project: # Synchronized Timepiece
- - Version: 004
- - Source Code NOT compiled for: Board 20
- - Source Code created on: 2026-03-09 17:24:53
- ********* Pleasedontcode.com **********/
- /****** SYSTEM REQUIREMENTS *****/
- /****** SYSTEM REQUIREMENT 1 *****/
- /* Display an analog clock with moving hour/minute */
- /* hands synchronized via WiFi NTP (UTC+1 solar */
- /* time). Animate a pendulum that swings left-right */
- /* at 1 Hz natural frequency behind the clock face on */
- /* ST7789 display. */
- /****** SYSTEM REQUIREMENT 2 *****/
- /* Display analog clock with hour/minute hands */
- /* synchronized via WiFi NTP (UTC+1 solar time) on */
- /* ST7789 display */
- /****** SYSTEM REQUIREMENT 3 *****/
- /* Animate pendulum swinging left-right at 1 Hz */
- /* natural frequency behind clock face */
- /****** END SYSTEM REQUIREMENTS *****/
- /****** DEFINITION OF LIBRARIES *****/
- #include <WiFi.h>
- #include <time.h>
- #include <SPI.h>
- #include <TFT_eSPI.h>
- #include <math.h>
- /****** DISPLAY CONFIGURATION *****/
- /* ST7789 display instance - pin configuration done in User_Setup.h of TFT_eSPI */
- TFT_eSPI tft = TFT_eSPI();
- /****** NETWORK CONFIGURATION *****/
- /* WiFi credentials - User must modify these to actual network credentials */
- const char* ssid = "YOUR_SSID";
- const char* password = "YOUR_PASSWORD";
- /* NTP Server for time synchronization */
- const char* ntpServer = "pool.ntp.org";
- const long gmtOffset_sec = 3600; /* UTC+1 (1 hour = 3600 seconds) - System Requirement 2 */
- const int daylightOffset_sec = 0; /* No daylight saving adjustment */
- /****** CLOCK PARAMETERS *****/
- /* Clock face center coordinates (adjust based on display resolution) */
- const int centerX = 160;
- const int centerY = 120;
- const int clockRadius = 80;
- /* Hand lengths (pixels) */
- const int hourHandLength = 40;
- const int minuteHandLength = 60;
- const int secondHandLength = 70;
- /****** PENDULUM PARAMETERS *****/
- /* System Requirement 1 and 3: Pendulum swing parameters */
- const float pendulumFrequency = 1.0; /* 1 Hz natural frequency (System Requirement 3) */
- const float pendulumAmplitude = 30.0; /* Swing amplitude in pixels */
- const int pendulumBaseY = centerY + 50; /* Base of pendulum below clock */
- const int pendulumLength = 60; /* Length of pendulum arm in pixels */
- /****** FUNCTION PROTOTYPES *****/
- void setup(void);
- void loop(void);
- void initializeWiFi(void);
- void synchronizeNTP(void);
- void drawClockFace(void);
- void drawClockHands(int hours, int minutes, int seconds);
- void drawPendulum(float phase);
- void drawHourHand(int hours, int minutes);
- void drawMinuteHand(int minutes, int seconds);
- void drawSecondHand(int seconds);
- void drawCircle(int x, int y, int radius, uint16_t color);
- void drawLine(int x0, int y0, int x1, int y1, uint16_t color, int thickness);
- void updateDisplay(void);
- float degreesToRadians(float degrees);
- /****** GLOBAL VARIABLES *****/
- /* Time variables for NTP synchronization */
- unsigned long lastNTPSync = 0;
- unsigned long ntpSyncInterval = 3600000; /* Sync every hour (3600000 ms) */
- /* Pendulum animation variables */
- float pendulumPhase = 0.0;
- unsigned long lastPendulumUpdate = 0;
- /* Time tracking variables */
- time_t lastDisplayTime = 0;
- /****** SETUP FUNCTION *****/
- void setup(void)
- {
- /* Initialize serial for debugging and communication */
- Serial.begin(115200);
- delay(1000);
- Serial.println("\n\nStarting Analog Clock with WiFi NTP and Pendulum Animation...");
- /* Initialize TFT display for ST7789 */
- tft.init();
- tft.setRotation(1); /* Set rotation to landscape mode (1 = 320x240 landscape) */
- tft.fillScreen(TFT_BLACK);
- /* Display initialization message on TFT */
- tft.setTextColor(TFT_WHITE, TFT_BLACK);
- tft.setTextSize(2);
- tft.drawCentreString("Initializing...", centerX, centerY - 20, 2);
- /* Initialize WiFi and synchronize with NTP server */
- initializeWiFi();
- synchronizeNTP();
- /* Mark the last NTP sync time */
- lastNTPSync = millis();
- lastPendulumUpdate = millis();
- Serial.println("Setup complete! Clock is now running.");
- }
- /****** MAIN LOOP FUNCTION *****/
- void loop(void)
- {
- /* Get current time from system clock - System Requirement 2 */
- time_t now = time(nullptr);
- struct tm* timeinfo = localtime(&now);
- /* Extract time components */
- int hours = timeinfo->tm_hour;
- int minutes = timeinfo->tm_min;
- int seconds = timeinfo->tm_sec;
- /* Synchronize with NTP periodically (every hour) */
- if (millis() - lastNTPSync > ntpSyncInterval)
- {
- synchronizeNTP();
- lastNTPSync = millis();
- }
- /* Clear the display area where clock is drawn */
- updateDisplay();
- /* Draw clock face and hands - System Requirement 2 */
- drawClockFace();
- drawClockHands(hours, minutes, seconds);
- /* Update pendulum phase for animation at 1 Hz - System Requirement 1 and 3 */
- unsigned long currentMillis = millis();
- if (currentMillis - lastPendulumUpdate >= 50) /* Update every 50ms for smooth animation */
- {
- /* Calculate phase increment: frequency * time elapsed * 2π */
- float timeElapsed = (currentMillis - lastPendulumUpdate) / 1000.0;
- pendulumPhase += (pendulumFrequency * timeElapsed) * 2.0 * 3.14159265359;
- /* Wrap phase to [0, 2π] range */
- if (pendulumPhase > 2.0 * 3.14159265359)
- pendulumPhase -= 2.0 * 3.14159265359;
- lastPendulumUpdate = currentMillis;
- }
- /* Draw animated pendulum behind clock face - System Requirement 1 and 3 */
- drawPendulum(pendulumPhase);
- /* Update display every 100ms for balanced CPU usage and visual smoothness */
- delay(100);
- }
- /****** INITIALIZE WIFI FUNCTION *****/
- void initializeWiFi(void)
- {
- Serial.print("Attempting to connect to WiFi network: ");
- Serial.println(ssid);
- /* Connect to WiFi network in station mode */
- WiFi.mode(WIFI_STA);
- WiFi.begin(ssid, password);
- int attempts = 0;
- const int maxAttempts = 20; /* Maximum 10 seconds (20 * 500ms) */
- /* Wait for WiFi connection with timeout */
- while (WiFi.status() != WL_CONNECTED && attempts < maxAttempts)
- {
- delay(500);
- Serial.print(".");
- attempts++;
- }
- /* Check if WiFi connection was successful */
- if (WiFi.status() == WL_CONNECTED)
- {
- Serial.println("\nWiFi connection established!");
- Serial.print("IP address: ");
- Serial.println(WiFi.localIP());
- /* Display WiFi connection success status on TFT */
- tft.setTextColor(TFT_GREEN, TFT_BLACK);
- tft.setTextSize(1);
- tft.drawCentreString("WiFi: Connected", centerX, centerY + 100, 1);
- delay(1000);
- }
- else
- {
- Serial.println("\nFailed to connect to WiFi network");
- Serial.println("System will continue with internal RTC if available");
- /* Display WiFi connection failure status on TFT */
- tft.setTextColor(TFT_RED, TFT_BLACK);
- tft.setTextSize(1);
- tft.drawCentreString("WiFi: Failed", centerX, centerY + 100, 1);
- delay(1000);
- }
- }
- /****** SYNCHRONIZE WITH NTP SERVER FUNCTION *****/
- void synchronizeNTP(void)
- {
- Serial.println("Attempting to synchronize time with NTP server...");
- /* Only proceed if WiFi is connected */
- if (WiFi.status() == WL_CONNECTED)
- {
- /* Configure time with NTP server using UTC+1 timezone - System Requirement 2 */
- configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
- /* Wait for time to be set by NTP */
- Serial.print("Waiting for NTP time synchronization: ");
- time_t now = time(nullptr);
- int attempts = 0;
- const int maxWaitAttempts = 20;
- /* Poll system time until it's set (unix epoch > 24 hours, i.e., > 86400) */
- while (now < 24 * 3600 && attempts < maxWaitAttempts)
- {
- delay(500);
- Serial.print(".");
- now = time(nullptr);
- attempts++;
- }
- Serial.println();
- /* Verify that time was successfully synchronized */
- if (now > 24 * 3600)
- {
- Serial.println("Time synchronized successfully!");
- Serial.print("Current UTC+1 time: ");
- Serial.println(ctime(&now));
- }
- else
- {
- Serial.println("NTP time synchronization failed - timeout");
- }
- }
- else
- {
- Serial.println("WiFi not connected - cannot synchronize with NTP server");
- Serial.println("Using system time (internal RTC if available)");
- }
- }
- /****** DRAW CLOCK FACE FUNCTION *****/
- void drawClockFace(void)
- {
- /* Draw clock circle outline - System Requirement 2 */
- drawCircle(centerX, centerY, clockRadius, TFT_WHITE);
- /* Draw 12 hour markers around the clock face */
- for (int i = 0; i < 12; i++)
- {
- /* Calculate angle for each hour marker (30 degrees apart = 360/12) */
- float angle = degreesToRadians(i * 30.0);
- /* Outer point of hour marker (near clock edge) */
- int x1 = centerX + (int)((clockRadius - 5) * sin(angle));
- int y1 = centerY - (int)((clockRadius - 5) * cos(angle));
- /* Inner point of hour marker (toward center) */
- int x2 = centerX + (int)((clockRadius - 12) * sin(angle));
- int y2 = centerY - (int)((clockRadius - 12) * cos(angle));
- /* Draw hour marker as a thick white line */
- drawLine(x1, y1, x2, y2, TFT_WHITE, 2);
- }
- /* Draw center pivot dot where clock hands meet */
- tft.fillCircle(centerX, centerY, 4, TFT_WHITE);
- }
- /****** DRAW CLOCK HANDS FUNCTION *****/
- void drawClockHands(int hours, int minutes, int seconds)
- {
- /* Convert to 12-hour format for clock display */
- hours = hours % 12;
- /* Draw all three clock hands */
- drawHourHand(hours, minutes);
- drawMinuteHand(minutes, seconds);
- drawSecondHand(seconds);
- }
- /****** DRAW HOUR HAND FUNCTION *****/
- void drawHourHand(int hours, int minutes)
- {
- /* System Requirement 2: Display hour hand synchronized via NTP */
- /* Hour hand angle calculation:
- - 360 degrees / 12 hours = 30 degrees per hour
- - 30 degrees / 60 minutes = 0.5 degrees per minute
- */
- float hourAngle = degreesToRadians(hours * 30.0 + minutes * 0.5);
- /* Calculate end point of hour hand using polar coordinates */
- int x = centerX + (int)(hourHandLength * sin(hourAngle));
- int y = centerY - (int)(hourHandLength * cos(hourAngle));
- /* Draw hour hand as a thick blue line */
- drawLine(centerX, centerY, x, y, TFT_BLUE, 4);
- }
- /****** DRAW MINUTE HAND FUNCTION *****/
- void drawMinuteHand(int minutes, int seconds)
- {
- /* System Requirement 2: Display minute hand synchronized via NTP */
- /* Minute hand angle calculation:
- - 360 degrees / 60 minutes = 6 degrees per minute
- - 6 degrees / 60 seconds = 0.1 degrees per second
- */
- float minuteAngle = degreesToRadians(minutes * 6.0 + seconds * 0.1);
- /* Calculate end point of minute hand using polar coordinates */
- int x = centerX + (int)(minuteHandLength * sin(minuteAngle));
- int y = centerY - (int)(minuteHandLength * cos(minuteAngle));
- /* Draw minute hand as a medium-thickness red line */
- drawLine(centerX, centerY, x, y, TFT_RED, 3);
- }
- /****** DRAW SECOND HAND FUNCTION *****/
- void drawSecondHand(int seconds)
- {
- /* Second hand angle calculation:
- - 360 degrees / 60 seconds = 6 degrees per second
- */
- float secondAngle = degreesToRadians(seconds * 6.0);
- /* Calculate end point of second hand using polar coordinates */
- int x = centerX + (int)(secondHandLength * sin(secondAngle));
- int y = centerY - (int)(secondHandLength * cos(secondAngle));
- /* Draw second hand as a thin yellow line */
- drawLine(centerX, centerY, x, y, TFT_YELLOW, 1);
- }
- /****** DRAW PENDULUM FUNCTION *****/
- void drawPendulum(float phase)
- {
- /* System Requirement 1 and 3: Pendulum swings left-right at 1 Hz natural frequency */
- /* The pendulum is drawn behind the clock face before clock hands are drawn */
- /* Calculate horizontal swing displacement using sinusoidal motion
- - phase ranges from 0 to 2π for one complete cycle
- - pendulumAmplitude controls maximum displacement
- - sin(phase) produces smooth oscillation
- */
- float swingDisplacement = pendulumAmplitude * sin(phase);
- /* Calculate pendulum bob position */
- int bobX = centerX + (int)swingDisplacement;
- int bobY = pendulumBaseY + pendulumLength;
- /* Draw pendulum arm (line from base to bob) in cyan color */
- drawLine(centerX, pendulumBaseY, bobX, bobY, TFT_CYAN, 1);
- /* Draw pendulum bob (small filled circle at the end of the arm) */
- tft.fillCircle(bobX, bobY, 4, TFT_CYAN);
- }
- /****** DRAW CIRCLE FUNCTION *****/
- void drawCircle(int x, int y, int radius, uint16_t color)
- {
- /* Draw a circle using TFT_eSPI built-in circle drawing function */
- tft.drawCircle(x, y, radius, color);
- }
- /****** DRAW LINE FUNCTION *****/
- void drawLine(int x0, int y0, int x1, int y1, uint16_t color, int thickness)
- {
- /* Draw a line with variable thickness
- - thickness = 1: thin line
- - thickness > 1: thick line created by drawing parallel offset lines
- */
- if (thickness == 1)
- {
- /* Simple case: draw a single thin line */
- tft.drawLine(x0, y0, x1, y1, color);
- }
- else
- {
- /* Thick line case: create thickness by drawing parallel lines */
- /* Calculate direction vector from start to end point */
- int dx = x1 - x0;
- int dy = y1 - y0;
- /* Calculate line length using Euclidean distance */
- float length = sqrt((float)(dx * dx + dy * dy));
- if (length > 0)
- {
- /* Calculate perpendicular unit vector (rotated 90 degrees) */
- float perpX = -dy / length;
- float perpY = dx / length;
- /* Draw multiple parallel lines to create thickness effect */
- int halfThickness = thickness / 2;
- for (int t = -halfThickness; t <= halfThickness; t++)
- {
- /* Calculate offset points perpendicular to the main line */
- int offset_x0 = x0 + (int)(perpX * t);
- int offset_y0 = y0 + (int)(perpY * t);
- int offset_x1 = x1 + (int)(perpX * t);
- int offset_y1 = y1 + (int)(perpY * t);
- /* Draw offset line */
- tft.drawLine(offset_x0, offset_y0, offset_x1, offset_y1, color);
- }
- }
- else
- {
- /* Special case: start and end points are the same */
- /* Draw a circle instead of a line */
- tft.fillCircle(x0, y0, thickness / 2, color);
- }
- }
- }
- /****** UPDATE DISPLAY FUNCTION *****/
- void updateDisplay(void)
- {
- /* Clear the display area where clock is drawn
- This prevents visual artifacts (trails) from moving hands and pendulum
- Clears a square region centered on the clock with extra margin
- */
- int clearRadius = clockRadius + 20;
- tft.fillRect(centerX - clearRadius, centerY - clearRadius,
- clearRadius * 2, clearRadius * 2 + 60, TFT_BLACK);
- }
- /****** HELPER MATH FUNCTION *****/
- float degreesToRadians(float degrees)
- {
- /* Convert angle from degrees to radians
- Used for trigonometric calculations in hand and pendulum positioning
- Formula: radians = degrees * π / 180
- */
- return degrees * 3.14159265359 / 180.0;
- }
- /* END CODE */
Advertisement
Add Comment
Please, Sign In to add comment