//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 02_Digital_Clock_with_NTP_Server
//----------------------------------------Including the libraries.
#include <WiFi.h>
#include "time.h"
#include <ESP32-HUB75-MatrixPanel-I2S-DMA.h>
//----------------------------------------
//----------------------------------------Defines the connected PIN between RGB LED Matrix P5 and ESP32.
#define R1_PIN 19
#define G1_PIN 13
#define B1_PIN 18
#define R2_PIN 5
#define G2_PIN 12
#define B2_PIN 17
#define A_PIN 16
#define B_PIN 14
#define C_PIN 4
#define D_PIN 27
#define E_PIN -1 //--> required for 1/32 scan panels, like 64x64px. Any available pin would do, i.e. IO32
#define LAT_PIN 26
#define OE_PIN 15
#define CLK_PIN 2
//----------------------------------------
//----------------------------------------Defines the P5 Panel configuration.
#define PANEL_RES_X 64 // Number of pixels wide of each INDIVIDUAL panel module.
#define PANEL_RES_Y 32 // Number of pixels tall of each INDIVIDUAL panel module.
#define PANEL_CHAIN 1 // Total number of panels chained one to another
//----------------------------------------
// Initialize MatrixPanel_I2S_DMA as "dma_display".
MatrixPanel_I2S_DMA *dma_display = nullptr;
//----------------------------------------SSID and PASSWORD of your WiFi network.
const char* ssid = "REPLACE_WITH_YOUR_SSID"; //--> Your wifi name
const char* password = "REPLACE_WITH_YOUR_PASSWORD"; //--> Your wifi password
//----------------------------------------
//----------------------------------------Variable for color.
uint16_t myBLACK = dma_display->color565(0, 0, 0);
uint16_t myWHITE = dma_display->color565(255, 255, 255);
uint16_t myRED = dma_display->color565(255, 0, 0);
uint16_t myGREEN = dma_display->color565(0, 255, 0);
uint16_t myBLUE = dma_display->color565(0, 0, 255);
//----------------------------------------
//----------------------------------------
byte td_sec = 0;
byte td_min = 0;
byte td_hour = 0;
byte td_wday = 0;
byte td_mday = 0;
byte td_mon = 0;
int td_year = 0;
char daysOfTheWeek[7][12] = {"SUNDAY", "MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY", "SATURDAY"};
char monthName[12][4] = {"JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"};
//----------------------------------------
//----------------------------------------
String str_td_sec = "";
String str_td_min = "";
String str_td_hour = "";
String str_td_mday = "";
//----------------------------------------
//----------------------------------------
String str_last_td_sec = "";
String str_last_td_min = "";
String str_last_td_hour = "";
//----------------------------------------
byte last_td_mday;
//----------------------------------------Timer/Millis to update and display Time, Date and more.
unsigned long previousMillis_Show = 0;
const long interval_Show = 1000;
//----------------------------------------
//----------------------------------------NTP Server and Time Settings.
// Source : https://lastminuteengineers.com/esp32-ntp-server-date-time-tutorial/
const char* ntpServer = "pool.ntp.org";
// Example setting for "gmtOffset_sec".
// - For UTC -5.00 : -5 * 60 * 60 = -18000
// - For UTC +1.00 : 1 * 60 * 60 = 3600
// - For UTC +0.00 : 0 * 60 * 60 = 0
// Check the UTC list here: https://en.wikipedia.org/wiki/List_of_UTC_offsets
// Where I live uses UTC+07:00, so : 7 * 60 * 60 = 25200
// or 3600 * 7 = 25200
const long gmtOffset_sec = 3600 * 7;
// Set it to 3600 if your country observes Daylight saving time. Otherwise, set it to 0.
// https://en.wikipedia.org/wiki/Daylight_saving_time
const int daylightOffset_sec = 0;
//----------------------------------------
//________________________________________________________________________________Connecting_To_The_Network()
void Connecting_To_The_Network() {
dma_display->clearScreen();
delay(1000);
dma_display->setTextSize(1);
dma_display->setTextWrap(false);
dma_display->setTextColor(dma_display->color565(255, 255, 255));
dma_display->setCursor(0, 0);
dma_display->print("Connecting");
dma_display->setCursor(0, 9);
dma_display->print("to");
dma_display->setCursor(0, 18);
dma_display->print("the network");
delay(1500);
dma_display->clearScreen();
delay(1000);
Serial.println();
Serial.print("Connecting to : ");
WiFi.mode(WIFI_STA);
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(500);
}
//----------------------------------------
Serial.println();
Serial.println("WiFi connected.");
//Serial.print("IP address : ");
//Serial.println(WiFi.localIP());
dma_display->setCursor(0, 0);
dma_display->setTextColor(dma_display->color565(102, 255, 102));
dma_display->print("Connected.");
delay(1500);
dma_display->clearScreen();
delay(1000);
}
//________________________________________________________________________________
//________________________________________________________________________________Disconnect_From_Network()
void Disconnect_From_Network() {
Serial.println();
Serial.println("WiFi Disconnected.");
WiFi.disconnect(true);
WiFi.mode(WIFI_OFF);
delay(1000);
dma_display->clearScreen();
delay(1000);
dma_display->setTextSize(1);
dma_display->setTextWrap(false);
dma_display->setTextColor(dma_display->color565(255, 255, 255));
dma_display->setCursor(0, 0);
dma_display->print("Disconnect");
dma_display->setCursor(0, 9);
dma_display->print("from");
dma_display->setCursor(0, 18);
dma_display->print("the network");
delay(1500);
}
//________________________________________________________________________________
//________________________________________________________________________________Set_Get_NTP_Server()
void Set_Get_NTP_Server() {
dma_display->clearScreen();
delay(1000);
dma_display->setTextSize(1);
dma_display->setTextWrap(false);
dma_display->setTextColor(dma_display->color565(255, 255, 255));
dma_display->setCursor(0, 0);
dma_display->print("Get Data");
dma_display->setCursor(0, 9);
dma_display->print("from");
dma_display->setCursor(0, 18);
dma_display->print("NTP server");
delay(1500);
dma_display->clearScreen();
delay(1000);
// Init and get the time and date.
Serial.println();
Serial.println("Get Time and Date from NTP server.");
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
delay(1000);
dma_display->setTextSize(1);
dma_display->setTextWrap(false);
dma_display->setTextColor(dma_display->color565(255, 255, 255));
dma_display->setCursor(0, 0);
dma_display->print("Getting");
dma_display->setCursor(0, 9);
dma_display->print("the data");
dma_display->setCursor(0, 18);
dma_display->print("is done.");
delay(1500);
dma_display->clearScreen();
delay(1000);
}
//________________________________________________________________________________
//________________________________________________________________________________update_Time_Date()
// Source : https://cplusplus.com/reference/ctime/tm/
// |----------------------------------------------------------|
// | Member | Type | Meaning | Range |
// |----------|-------|---------------------------|-----------|
// | tm_sec | int | seconds after the minute | 0-61* |
// | tm_min | int | minutes after the hour | 0-59 |
// | tm_hour | int | hours since midnight | 0-23 |
// | tm_mday | int | day of the month | 1-31 |
// | tm_mon | int | months since January | 0-11 |
// | tm_year | int | years since 1900 | |
// | tm_wday | int | days since Sunday | 0-6 |
// | tm_yday | int | days since January 1 | 0-365 |
// | tm_isdst | int | Daylight Saving Time flag | |
// |----------------------------------------------------------|
//
// * tm_sec is generally 0-59. The extra range is to accommodate for leap seconds in certain systems.
void update_Time_Date() {
struct tm timeinfo;
if (!getLocalTime(&timeinfo)) {
Serial.println("Failed to obtain time");
dma_display->clearScreen();
delay(1000);
dma_display->setTextSize(1);
dma_display->setTextWrap(false);
dma_display->setTextColor(dma_display->color565(255, 255, 255));
dma_display->setCursor(0, 0);
dma_display->print("Failed to");
dma_display->setCursor(0, 9);
dma_display->print("obtain time");
delay(1000);
dma_display->clearScreen();
delay(1000);
}
td_mday = timeinfo.tm_mday;
td_mon = timeinfo.tm_mon+1;
td_year = timeinfo.tm_year+1900;
td_wday = timeinfo.tm_wday;
td_hour = timeinfo.tm_hour;
td_min = timeinfo.tm_min;
td_sec = timeinfo.tm_sec;
// Serial.println();
// Serial.print("Date : ");
// Serial.print(daysOfTheWeek[td_wday]);
// Serial.print(", ");
// Serial.print(td_mday);
// Serial.print("-");
// Serial.print(td_mon);
// Serial.print("(");
// Serial.print(monthName[td_mon-1]);
// Serial.print(")-");
// Serial.print(td_year);
// Serial.print(" | Time : ");
// Serial.print(td_hour);
// Serial.print(":");
// Serial.print(td_min);
// Serial.print(":");
// Serial.println(td_sec);
}
//________________________________________________________________________________
//________________________________________________________________________________VOID SETUP()
void setup() {
Serial.begin(115200);
Serial.println();
Serial.println("Start");
delay(1000);
str_td_sec.reserve(3);
str_td_min.reserve(3);
str_td_hour.reserve(3);
str_td_mday.reserve(3);
str_last_td_sec.reserve(3);
str_last_td_min.reserve(3);
str_last_td_hour.reserve(3);
// Initialize the connected PIN between RGB LED Matrix P5 and ESP32.
HUB75_I2S_CFG::i2s_pins _pins={R1_PIN, G1_PIN, B1_PIN, R2_PIN, G2_PIN, B2_PIN, A_PIN, B_PIN, C_PIN, D_PIN, E_PIN, LAT_PIN, OE_PIN, CLK_PIN};
delay(10);
//----------------------------------------Module configuration.
HUB75_I2S_CFG mxconfig(
PANEL_RES_X, // module width
PANEL_RES_Y, // module height
PANEL_CHAIN, // Chain length
_pins // pin mapping
);
//----------------------------------------
delay(10);
// Set I2S clock speed.
mxconfig.i2sspeed = HUB75_I2S_CFG::HZ_10M;// I2S clock speed, better leave as-is unless you want to experiment
delay(10);
//----------------------------------------Display Setup.
dma_display = new MatrixPanel_I2S_DMA(mxconfig);
dma_display->begin();
dma_display->setBrightness8(65); //--> 0-255.
//----------------------------------------
//----------------------------------------
dma_display->clearScreen();
dma_display->fillScreen(myWHITE);
delay(1000);
dma_display->fillScreen(myRED);
delay(1000);
dma_display->fillScreen(myGREEN);
delay(1000);
dma_display->fillScreen(myBLUE);
delay(1000);
//----------------------------------------
//----------------------------------------
dma_display->clearScreen();
delay(1000);
dma_display->setTextSize(1);
dma_display->setTextWrap(false);
dma_display->setCursor(16, 4);
dma_display->setTextColor(dma_display->color565(51, 153, 255));
dma_display->print("ESP");
dma_display->setCursor(36, 4);
dma_display->print("32");
dma_display->setCursor(5, 21);
dma_display->setTextColor(dma_display->color565(255, 153, 0));
dma_display->print("NTP Clock");
delay(3000);
//----------------------------------------
Connecting_To_The_Network();
delay(100);
Set_Get_NTP_Server();
delay(100);
Disconnect_From_Network();
delay(100);
dma_display->clearScreen();
delay(1000);
}
//________________________________________________________________________________
//________________________________________________________________________________VOID LOOP()
void loop() {
//----------------------------------------
unsigned long currentMillis_Show = millis();
if (currentMillis_Show - previousMillis_Show >= interval_Show) {
previousMillis_Show = currentMillis_Show;
update_Time_Date();
//::::::::::::::::::
if (td_sec < 10) {
str_td_sec = "0" + String(td_sec);
} else {
str_td_sec = String(td_sec);
}
if (td_min < 10) {
str_td_min = "0" + String(td_min);
} else {
str_td_min = String(td_min);
}
if (td_hour < 10) {
str_td_hour = "0" + String(td_hour);
} else {
str_td_hour = String(td_hour);
}
//::::::::::::::::::
//::::::::::::::::::
if (td_mday < 10) {
str_td_mday = "0" + String(td_mday);
} else {
str_td_mday = String(td_mday);
}
//::::::::::::::::::
// As the day changes, clean the P5 display.
if (last_td_mday != td_mday) dma_display->clearScreen();
dma_display->setTextSize(1);
dma_display->setTextWrap(false);
//::::::::::::::::::Displays time.
if (str_last_td_hour != str_td_hour) {
// If the "hour" changes, refresh the hour section display to display the new "hour". If not refreshed, the old "hour" and the new "hour" will show together.
// The background color is black, so for refreshing, use black (color565(0, 0, 0)).
// The same applies to the "minutes", "seconds" and other displays.
dma_display->setCursor(8, 0);
dma_display->setTextColor(dma_display->color565(0, 0, 0));
dma_display->print(str_last_td_hour);
dma_display->setCursor(8, 0);
dma_display->setTextColor(dma_display->color565(255, 255, 255));
dma_display->print(str_td_hour);
} else {
dma_display->setCursor(8, 0);
dma_display->setTextColor(dma_display->color565(255, 255, 255));
dma_display->print(str_td_hour);
}
dma_display->setCursor(20, 0);
dma_display->setTextColor(dma_display->color565(255, 0, 0));
dma_display->print(":");
if (str_last_td_min != str_td_min) {
dma_display->setCursor(26, 0);
dma_display->setTextColor(dma_display->color565(0, 0, 0));
dma_display->print(str_last_td_min);
dma_display->setCursor(26, 0);
dma_display->setTextColor(dma_display->color565(255, 255, 255));
dma_display->print(str_td_min);
} else {
dma_display->setCursor(26, 0);
dma_display->setTextColor(dma_display->color565(255, 255, 255));
dma_display->print(str_td_min);
}
dma_display->setCursor(38, 0);
dma_display->setTextColor(dma_display->color565(255, 0, 0));
dma_display->print(":");
if (str_last_td_sec != str_td_sec) {
dma_display->setCursor(44, 0);
dma_display->setTextColor(dma_display->color565(0, 0, 0));
dma_display->print(str_last_td_sec);
dma_display->setCursor(44, 0);
dma_display->setTextColor(dma_display->color565(255, 255, 255));
dma_display->print(str_td_sec);
} else {
dma_display->setCursor(44, 0);
dma_display->setTextColor(dma_display->color565(255, 255, 255));
dma_display->print(str_td_sec);
}
str_last_td_hour = str_td_hour;
str_last_td_min = str_td_min;
str_last_td_sec = str_td_sec;
//::::::::::::::::::
//::::::::::::::::::Displays the day name.
if (td_wday == 0 || td_wday == 1 || td_wday == 5) { //--> 0 (sunday), 1 (monday), 5 (friday)
dma_display->setCursor(14, 8);
} else if (td_wday == 2) { //--> 2 (tuesday)
dma_display->setCursor(11, 8);
} else if (td_wday == 3) { //--> 3 (wednesday)
dma_display->setCursor(5, 8);
} else if (td_wday == 4 || td_wday == 6) { //--> 4 (thursday) and 6 (saturday)
dma_display->setCursor(8, 8);
}
dma_display->setTextColor(dma_display->color565(255, 0, 102));
dma_display->print(daysOfTheWeek[td_wday]);
//::::::::::::::::::
//::::::::::::::::::Displays the date.
dma_display->setCursor(3, 17);
dma_display->setTextColor(dma_display->color565(51, 153, 255));
dma_display->print(str_td_mday);
dma_display->setCursor(17, 17);
dma_display->setTextColor(dma_display->color565(255, 255, 0));
dma_display->print(monthName[td_mon-1]);
dma_display->setCursor(37, 17);
dma_display->setTextColor(dma_display->color565(102, 255, 102));
dma_display->print(td_year);
//::::::::::::::::::
//::::::::::::::::::
dma_display->setCursor(11, 25);
dma_display->setTextColor(dma_display->color565(255, 153, 0));
dma_display->print("UTEH");
dma_display->setTextColor(dma_display->color565(255, 0, 255));
dma_display->print("STR");
//::::::::::::::::::
last_td_mday = td_mday;
}
//----------------------------------------
}
//________________________________________________________________________________
//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<