Short circuit Lab
Published © GPL3+

Dead Apple Watch to Matchbox Clock

In this project, we’ll repurpose an old, non-functional Apple Watch and build a fully functional clock that fits snugly inside a matchbox.

IntermediateFull instructions provided231
Dead Apple Watch to Matchbox Clock

Things used in this project

Story

Read more

Schematics

ESP32 connection with Oled

Code

ESP32 code

Arduino
// Made by @Short Circuit Lab


#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include "time.h"

// WiFi credentials
const char* ssid = "****";
const char* password = "****";

// OpenWeatherMap API details
const char* apiKey = "********";  // Your API key
const char* location = "Bengaluru,in";  // Bengaluru, India

// NTP Server details
const char* ntpServer = "pool.ntp.org";
const long gmtOffset_sec = 19800;  // Bengaluru is GMT +5:30 (5.5 hours = 19800 seconds)
const int daylightOffset_sec = 0;  // No daylight saving time in Bengaluru

// OLED display size
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

// Button pin for refreshing the display
#define BUTTON_PIN GPIO_NUM_10  // GPIO 10 as the button pin

// Variables to hold weather data
float temperature = 0.0;
float humidity = 0.0;

// To track blinking state
bool showColon = true;

void setup() {
  // Initialize Serial Monitor
  Serial.begin(115200);
  delay(1000);  // Take some time to open up the Serial Monitor

  // Configure the button pin
  pinMode(BUTTON_PIN, INPUT_PULLUP);  // Button as input with pullup

  // Connect to Wi-Fi
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected.");

  // Initialize OLED display
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println("SSD1306 allocation failed");
    for (;;);
  }

  // Set text color to white
  display.setTextColor(SSD1306_WHITE);

  // Clear the display
  display.clearDisplay();
  display.display();
  delay(5000);

  // Display the MatchBox animation on startup
  startupAnimation();

  // Initialize and fetch the time from the NTP server
  configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);

  // Fetch weather data once for Bengaluru
  getWeatherData();

  // Show the time, date, and weather on the display
  updateDisplay();
}

void loop() {
  // Check if the button is pressed to refresh the display
  if (digitalRead(BUTTON_PIN) == LOW) {
    delay(50);  // Debouncing the button
    if (digitalRead(BUTTON_PIN) == LOW) {
      Serial.println("Button pressed, refreshing display.");
      getWeatherData();
      updateDisplay();
    }
  }

  // Update the display every second
  updateDisplay();
  delay(1000);  // Update every second
}

// Function to fetch weather data from OpenWeatherMap
void getWeatherData() {
  if (WiFi.status() == WL_CONNECTED) {
    HTTPClient http;
    String url = "http://api.openweathermap.org/data/2.5/weather?q=" + String(location) + "&appid=" + String(apiKey) + "&units=metric";

    http.begin(url);
    int httpCode = http.GET();

    if (httpCode > 0) {
      String payload = http.getString();
      Serial.println(payload);

      // Parse JSON response
      DynamicJsonDocument doc(1024);
      deserializeJson(doc, payload);

      temperature = doc["main"]["temp"];
      humidity = doc["main"]["humidity"];
    } else {
      Serial.println("Failed to retrieve data");
    }
    http.end();
  } else {
    Serial.println("WiFi not connected");
  }
}

// Function to update the display with time, date, and weather
void updateDisplay() {
  // Clear display buffer
  display.clearDisplay();

  // Get current time from the system
  struct tm timeinfo;
  if (!getLocalTime(&timeinfo)) {
    Serial.println("Failed to obtain time");
    return;
  }

  // Display date at the top in the format: Day, DD Mon YYYY
  display.setTextSize(1);
  display.setCursor(10, 0);  // Start at top-left corner
  display.printf("%s, %02d %s %d", 
    getDayName(timeinfo.tm_wday), 
    timeinfo.tm_mday, 
    getMonthName(timeinfo.tm_mon), 
    timeinfo.tm_year + 1900);

  // Draw a box around the time
  display.drawRect(10, 18, 108, 24, SSD1306_WHITE);  // Box for time at position (10, 18)

  // Display the time inside the box with blinking colon and minutes
  display.setTextSize(2);
  display.setCursor(15, 22);  // Position for the hours
  display.printf("%02d", timeinfo.tm_hour);  // Display hours

  // Blink the colon every second
  display.print(":");

  display.printf("%02d", timeinfo.tm_min);  // Always display minutes
  if (showColon) {
    display.print(":");
  } else {
    display.print(" ");  // Replace colon with a space
  }
  // Display seconds on the right side of the time
  display.setCursor(85, 22);
  display.printf("%02d", timeinfo.tm_sec);  // Display seconds

  // Toggle the blinking colon state every second
  showColon = !showColon;

  // Display temperature and humidity at the bottom
  display.setTextSize(1);  // Smaller font for weather data
  display.setCursor(0, 50);
  display.printf("Temp:%.1fC", temperature);
  display.setCursor(70, 50);
  display.printf("Hum:%.1f%%", humidity);

  // Show the contents of the buffer
  display.display();
}

// Function to get the day of the week
const char* getDayName(int dayIndex) {
  const char* days[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
  return days[dayIndex];
}

// Function to get the month name
const char* getMonthName(int monthIndex) {
  const char* months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
  return months[monthIndex];
}

// MatchBox Clock animation function
void startupAnimation() {
  display.clearDisplay();

  // Scroll "MatchBox" from the top to the middle
  for (int y = -20; y <= 16; y += 2) {  // Scroll down from off-screen (-20) to position (16)
    display.clearDisplay();
    display.setTextSize(2);
    display.setCursor((SCREEN_WIDTH - 96) / 2, y);  // Center "MatchBox"
    display.print("MatchBox");
    display.display();
    delay(30);  // Smooth scrolling speed
  }

  // Scroll "Clock" from the bottom to the middle
  for (int y = SCREEN_HEIGHT; y >= 40; y -= 2) {  // Scroll up from off-screen (SCREEN_HEIGHT) to position (40)
    display.clearDisplay();
    display.setTextSize(2);
    display.setCursor((SCREEN_WIDTH - 96) / 2, 16);  // "MatchBox" stays in place
    display.print("MatchBox");
    display.setCursor((SCREEN_WIDTH - 55) / 2, y);  // Move "Clock"
    display.print("Clock");
    display.display();
    delay(30);  // Smooth scrolling speed
  }

  // Display "By Short Circuit Lab" at the bottom after the scrolling finishes
  display.setTextSize(1);
  display.setCursor((SCREEN_WIDTH - 108) / 2, 56);  
  display.print("By ShortCircuit Lab");
  display.display();
  delay(1000);  // Hold the screen for 2 seconds before switching to the main screen
}

Credits

Short circuit Lab
2 projects • 1 follower
At Short Circuit Lab, we dive into the exciting world of electronics, IoT, science, and automation through hands-on, DIY projects.
Contact

Comments

Please log in or sign up to comment.