/*
╔═══════════════════════════════════════════════════════════╗
║ ESP32-C3 MINI × MAX7219 32×8 — WiFi INDIA CLOCK ║
║ IST — Indian Standard Time (UTC + 5:30) ║
║ By: Arvind Patil | AI Centre Nandurbar ║
╚═══════════════════════════════════════════════════════════╝
─── ARDUINO IDE BOARD SETTINGS ─────────────────────────────
Board : ESP32C3 Dev Module
USB CDC on Boot: ENABLED ← Serial Monitor जरूरी
Flash Mode : QIO
Flash Size : 4MB
CPU Freq : 160 MHz
Upload Speed : 921600
─── LIBRARIES (Library Manager में install करें) ────────────
1. MD_Parola by MajicDesigns ≥ 3.7.0
2. MD_MAX72XX by MajicDesigns ≥ 3.4.0
(SPI.h और WiFi.h — built-in हैं, install नहीं चाहिए)
─── WIRING — ESP32-C3 Mini → MAX7219 ──────────────────────
ESP32-C3 MAX7219 Module
────────── ─────────────
GPIO 6 → DIN (Data In / MOSI)
GPIO 4 → CLK (Clock)
GPIO 5 → CS (Chip Select / LOAD)
5V → VCC (5V power)
GND → GND
⚠️ Cascade: CLK/DIN shared, CS shared across all modules
⚠️ 4 modules cascaded = 32×8 display
─── FEATURES ────────────────────────────────────────────────
✅ WiFi NTP sync (auto-reconnect)
✅ IST = UTC + 5:30 (19800 sec offset)
✅ Time: HH:MM:SS with blinking colon
✅ Date scroll every 30 sec
✅ Day name scroll (Mon, Tue...)
✅ WiFi connect animation on startup
✅ Brightness: auto dim at night (22:00–06:00)
✅ NTP resync every hour
*/
#include <SPI.h>
#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <WiFi.h>
#include <time.h>
// ─── YOUR WiFi CREDENTIALS ─────────────────────────────────
#define WIFI_SSID "Airtel_arvi_3035" // ← अपना WiFi नाम
#define WIFI_PASS "air26289" // ← अपना Password
// ─── SPI PINS (ESP32-C3 safe pins) ─────────────────────────
#define PIN_MOSI 6 // DIN
#define PIN_CLK 4 // CLK
#define PIN_CS 5 // CS/LOAD
// ─── MAX7219 CONFIG ─────────────────────────────────────────
#define HARDWARE_TYPE MD_MAX72XX::FC16_HW // FC-16 module type
#define NUM_DEVICES 4 // 4 modules = 32 cols
// ─── NTP CONFIG ─────────────────────────────────────────────
#define NTP_SERVER1 "pool.ntp.org"
#define NTP_SERVER2 "time.google.com"
#define NTP_SERVER3 "in.pool.ntp.org"
#define TZ_OFFSET_SEC 19800 // IST = UTC + 5:30 = 5*3600 + 30*60
#define DST_SEC 0 // India has no DST
// ─── TIMING ─────────────────────────────────────────────────
#define DATE_SCROLL_EVERY_SEC 30 // Show date every N seconds
#define NTP_RESYNC_MIN 60 // Re-sync NTP every N minutes
#define SCROLL_SPEED_MS 40 // Scroll text speed (ms/frame)
// ─── BRIGHTNESS ─────────────────────────────────────────────
#define BRIGHT_DAY 5 // 0–15 (daytime: 06:00–21:59)
#define BRIGHT_NIGHT 1 // 0–15 (night: 22:00–05:59)
// ════════════════════════════════════════════════════════════
MD_Parola display = MD_Parola(HARDWARE_TYPE, PIN_MOSI, PIN_CLK, PIN_CS, NUM_DEVICES);
// State
bool timeSynced = false;
bool colonVisible = true;
uint32_t lastColonToggle = 0;
uint32_t lastDateScroll = 0;
uint32_t lastNTPSync = 0;
uint32_t lastSecond = 0;
bool scrolling = false;
char scrollBuf[64];
const char* dayNames[] = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
const char* monthNames[] = {"Jan","Feb","Mar","Apr","May","Jun",
"Jul","Aug","Sep","Oct","Nov","Dec"};
// ─── HELPERS ────────────────────────────────────────────────
void setAutoBrightness(int hour) {
if (hour >= 6 && hour < 22)
display.setIntensity(BRIGHT_DAY);
else
display.setIntensity(BRIGHT_NIGHT);
}
void showStatic(const char* txt) {
display.setTextAlignment(PA_CENTER);
display.print(txt);
}
void startScroll(const char* txt) {
strncpy(scrollBuf, txt, sizeof(scrollBuf) - 1);
scrollBuf[sizeof(scrollBuf) - 1] = '\0';
display.displayScroll(scrollBuf, PA_LEFT, PA_SCROLL_LEFT, SCROLL_SPEED_MS);
scrolling = true;
}
// ─── WiFi CONNECT ───────────────────────────────────────────
void connectWiFi() {
WiFi.mode(WIFI_STA);
WiFi.begin(WIFI_SSID, WIFI_PASS);
Serial.print("WiFi connecting");
startScroll("WiFi...");
uint8_t dots = 0;
uint32_t start = millis();
while (WiFi.status() != WL_CONNECTED) {
// Animate dots on display while connecting
if (display.displayAnimate()) {
display.displayReset();
}
if (millis() - start > 15000) {
Serial.println("\nWiFi timeout — will retry");
showStatic("ERR");
delay(2000);
return;
}
Serial.print(".");
delay(200);
}
Serial.println();
Serial.print("Connected! IP: ");
Serial.println(WiFi.localIP());
startScroll("WiFi OK!");
delay(1500);
}
// ─── NTP SYNC ───────────────────────────────────────────────
void syncNTP() {
if (WiFi.status() != WL_CONNECTED) return;
showStatic("SYNC");
Serial.println("NTP syncing...");
configTime(TZ_OFFSET_SEC, DST_SEC,
NTP_SERVER1, NTP_SERVER2, NTP_SERVER3);
// Wait for valid time (up to 10 sec)
struct tm ti;
uint32_t t0 = millis();
while (!getLocalTime(&ti)) {
if (millis() - t0 > 10000) {
Serial.println("NTP sync failed");
showStatic("Err");
delay(2000);
return;
}
delay(200);
}
timeSynced = true;
lastNTPSync = millis();
Serial.printf("NTP OK: %02d:%02d:%02d IST\n",
ti.tm_hour, ti.tm_min, ti.tm_sec);
// Show "IST OK" briefly
char msg[32];
sprintf(msg, "IST %02d:%02d", ti.tm_hour, ti.tm_min);
startScroll(msg);
delay(2000);
}
// ─── DRAW CLOCK FACE ────────────────────────────────────────
void drawTime(struct tm* ti) {
char buf[16];
// HH:MM — colon blinks every 500ms
if (colonVisible)
sprintf(buf, "%02d:%02d", ti->tm_hour, ti->tm_min);
else
sprintf(buf, "%02d %02d", ti->tm_hour, ti->tm_min);
display.setTextAlignment(PA_CENTER);
display.print(buf);
}
// ─── SCROLL DATE ────────────────────────────────────────────
void scrollDate(struct tm* ti) {
char msg[48];
sprintf(msg, " %s %02d %s %04d IST",
dayNames[ti->tm_wday],
ti->tm_mday,
monthNames[ti->tm_mon],
ti->tm_year + 1900);
startScroll(msg);
}
// ════════════════════════════════════════════════════════════
// SETUP
// ════════════════════════════════════════════════════════════
void setup() {
Serial.begin(115200);
delay(500);
// Init display
display.begin();
display.setIntensity(BRIGHT_DAY);
display.displayClear();
display.setTextAlignment(PA_CENTER);
display.print("INIT");
delay(800);
Serial.println("ESP32-C3 WiFi IST Clock | AI Centre Nandurbar");
// Show welcome scroll
startScroll("India Clock IST");
uint32_t t0 = millis();
while (millis() - t0 < 2000) {
if (display.displayAnimate()) display.displayReset();
}
// Connect WiFi + sync NTP
connectWiFi();
syncNTP();
lastDateScroll = millis();
lastColonToggle = millis();
lastSecond = millis();
}
// ════════════════════════════════════════════════════════════
// LOOP
// ════════════════════════════════════════════════════════════
void loop() {
uint32_t now = millis();
// ── If scrolling, handle animation ──
if (scrolling) {
if (display.displayAnimate()) {
display.displayReset();
scrolling = false;
}
return; // Don't update clock while scrolling
}
// ── WiFi watchdog ──
if (WiFi.status() != WL_CONNECTED) {
Serial.println("WiFi lost — reconnecting...");
showStatic("WiFi");
delay(500);
connectWiFi();
syncNTP();
return;
}
// ── NTP hourly resync ──
if (timeSynced && (now - lastNTPSync > (uint32_t)NTP_RESYNC_MIN * 60000UL)) {
syncNTP();
return;
}
// ── Get current IST time ──
struct tm ti;
if (!getLocalTime(&ti)) {
showStatic("--:--");
return;
}
// ── Auto brightness ──
setAutoBrightness(ti.tm_hour);
// ── Blink colon every 500ms ──
if (now - lastColonToggle >= 500) {
colonVisible = !colonVisible;
lastColonToggle = now;
}
// ── Scroll date every N seconds ──
if (now - lastDateScroll >= (uint32_t)DATE_SCROLL_EVERY_SEC * 1000UL) {
lastDateScroll = now;
scrollDate(&ti);
return;
}
// ── Draw time ──
drawTime(&ti);
// ── Serial debug every second ──
if (now - lastSecond >= 1000) {
lastSecond = now;
Serial.printf("IST: %02d:%02d:%02d | %s %02d %s | WiFi: %ddBm\n",
ti.tm_hour, ti.tm_min, ti.tm_sec,
dayNames[ti.tm_wday], ti.tm_mday,
monthNames[ti.tm_mon],
WiFi.RSSI());
}
delay(50);
}
Loading
esp32-c3-devkitm-1
esp32-c3-devkitm-1