Search Code

Dự án Đồng hồ thời gian Wi-Fi + NTP sử dụng ma trận LED RGB ESP32-S3 - 1 Đồng hồ cơ bản

Dự án Đồng hồ thời gian Wi-Fi + NTP sử dụng ma trận LED RGB ESP32-S3 - 1 Đồng hồ cơ bản

Đồng hồ Internet ESP32-S3 với NeoMatrix 8×8 (Wi-Fi + Giờ NTP)

Dự án này biến một ESP32-S3 và một NeoMatrix RGB 8×8 (NeoPixel/WS2812) thành một chiếc đồng hồ Internet nhỏ gọn. ESP32 kết nối Wi-Fi, đồng bộ giờ địa phương từ máy chủ NTP, sau đó cuộn giờ dưới dạng HH:MM trên màn hình 8×8.

Hoạt ảnh đồng hồ Internet ESP32-s3

 

Cách hoạt động (tổng quan)

1) ESP32-S3 kết nối với bộ định tuyến của bạn bằng <WiFi.h>.
2) Đồng bộ giờ từ máy chủ NTP bằng "time.h"configTime().
3) Giờ được định dạng thành HH:MM và lưu vào một bộ đệm văn bản nhỏ.
4) NeoMatrix hiển thị văn bản và cuộn nó trên bảng 8×8.

Màu RGB

Màu chữ của đồng hồ được điều khiển bằng giá trị RGB (Đỏ, Lục, Lam), trong đó mỗi kênh màu nằm trong khoảng từ 0 đến 255 và các tổ hợp khác nhau tạo ra các màu khác nhau trên NeoMatrix. Bằng cách điều chỉnh các biến color_RED, color_GREENcolor_BLUE, bạn có thể dễ dàng tùy chỉnh giao diện đồng hồ theo bất kỳ màu nào bạn thích. Để nhanh chóng tìm giá trị RGB chính xác cho một màu cụ thể, bạn có thể sử dụng Trình chọn màu RGB trực tuyến Trình chọn màu .

Thư viện được sử dụng

Các dòng include này cho bạn biết chính xác sketch phụ thuộc vào những gì:

#include <WiFi.h>
#include "time.h"
#include <Adafruit_GFX.h>
#include <Adafruit_NeoMatrix.h>
#include <Adafruit_NeoPixel.h>

Cài đặt Adafruit NeoMatrix bằng Arduino Library Manager. Nó cũng sẽ tự động kéo theo các thư viện phụ thuộc cần thiết như Adafruit GFX LibraryAdafruit NeoPixel.

Các cài đặt quan trọng của người dùng BẠN PHẢI chỉnh sửa

1) Màu chữ (RGB)

Đặt màu chữ đồng hồ của bạn bằng giá trị 0–255:

//đặt màu hiển thị gồm Đỏ, Lục và Lam 
unsigned int color_RED = 17;
unsigned int color_GREEN = 43;
unsigned int color_BLUE = 171;

Các giá trị này được sử dụng ở đây:

matrix.setTextColor(matrix.Color(color_RED, color_GREEN, color_BLUE));

Lưu ý: Nếu bạn đặt tất cả màu thành 0 (đen), chữ sẽ trở nên vô hình. Sketch bao gồm một kiểm tra an toàn:

// nếu người dùng đặt tất cả màu thành 0, màn hình sẽ tắt nên đặt nó thành màu lục
if (color_RED == 0 && color_GREEN == 0 && color_BLUE == 0) {
  color_GREEN = 200;
}

Điều này đảm bảo ma trận không bao giờ trông “chết” do cài đặt màu vô hình.

2) SSID và mật khẩu Wi-Fi

Thay thế những giá trị này bằng tên Wi-Fi và mật khẩu thực của bạn:

const char* WIFI_SSID     = "WiFi";
const char* WIFI_PASSWORD = "passW0rd";

Trong quá trình khởi động, ESP32 in tiến trình kết nối trong Serial Monitor và hết thời gian chờ sau khoảng 15 giây (30 lần thử × 500ms).

3) Máy chủ NTP

Máy chủ NTP mặc định là:

const char* ntpServer = "pool.ntp.org";

Bạn có thể giữ nguyên. Nếu bạn muốn sử dụng máy chủ cục bộ, hãy thay thế tên máy chủ bằng máy chủ NTP bạn muốn.

4) Độ lệch múi giờ và độ lệch giờ mùa hè

Hai cài đặt này điều khiển giờ địa phương:

// Gần Toronto: UTC-5, cộng thêm 1 giờ DST
const long  gmtOffset_sec      = -5 * 3600;  // -5 giờ
const int   daylightOffset_sec = 3600;       // +1 giờ cho DST

Cách đặt chúng:

  • gmtOffset_sec = (số giờ lệch UTC) × 3600. Ví dụ: UTC-5 → -5*3600, UTC+2 → 2*3600.
  • daylightOffset_sec = 0 nếu bạn không muốn điều chỉnh DST, hoặc 3600 nếu khu vực của bạn hiện đang áp dụng DST (+1 giờ).

Chúng được áp dụng ở đây:

configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);

Cấu hình màn hình

Chân dữ liệu ma trận

Chân dữ liệu được định nghĩa ở đây:

#define MATRIX_PIN 14

Nếu cách nối dây của bạn sử dụng GPIO khác, hãy thay đổi số này cho phù hợp.

Bố cục NeoMatrix + thứ tự màu

Ma trận của bạn được khởi tạo như sau:

Adafruit_NeoMatrix matrix(8, 8, MATRIX_PIN,
  NEO_MATRIX_TOP    + NEO_MATRIX_LEFT +
  NEO_MATRIX_ROWS   + NEO_MATRIX_PROGRESSIVE,
  NEO_RGB           + NEO_KHZ800);

Hai lý do phổ biến khiến màn hình trông “sai”:

  • Xoay / hướng nối dây: Nếu chữ xuất hiện lộn ngược hoặc bị phản chiếu, hãy điều chỉnh các cờ NEO_MATRIX_* (TOP/BOTTOM, LEFT/RIGHT, ROWS/COLUMNS, PROGRESSIVE/ZIGZAG).
  • Thứ tự màu: Mã này sử dụng NEO_RGB. Một số bảng là NEO_GRB. Nếu đỏ/lục/lam không khớp, hãy đổi NEO_RGB sang thứ tự đúng.

Độ sáng

Độ sáng được đặt trong initMatrix():

matrix.setBrightness(40);

Tăng để màn hình sáng hơn, giảm để giảm nhiệt và mức tiêu thụ điện.

Cách giờ được tạo dưới dạng HH:MM

Đồng hồ lưu giờ đã định dạng trong bộ đệm 6 ký tự:

char timeText[6] = "00:00";

Sau đó, updateTimeText() đọc thời gian cục bộ đã đồng bộ NTP và ghi văn bản:

// Định dạng HH:MM
snprintf(timeText, sizeof(timeText), "%02d:%02d",
         timeinfo.tm_hour,
         timeinfo.tm_min);

Điều này được cập nhật mỗi giây một lần trong vòng lặp chính.

Cách cuộn hoạt động trên màn hình 8×8

Ma trận 8×8 quá hẹp để hiển thị HH:MM cùng lúc, vì vậy sketch cuộn văn bản. Nó vẽ thời gian tại vị trí X thay đổi (scrollX), sau đó di chuyển sang trái một pixel mỗi lần cập nhật.

int16_t scrollX = 8;
const uint16_t scrollIntervalMs = 120;

Mỗi bước cuộn:

matrix.fillScreen(0);
matrix.setCursor(scrollX, 0);
matrix.print(timeText);
matrix.show();
scrollX--;

Khi văn bản hoàn toàn thoát khỏi phía bên trái, mã đặt lại để bắt đầu lại từ cạnh phải:

int16_t textWidth = 30;
if (scrollX < -textWidth) {
  scrollX = matrix.width();
}

Đầu ra Serial Monitor (gỡ lỗi)

Sketch này in các thông báo hữu ích:

  • Tiến trình kết nối Wi-Fi và địa chỉ IP
  • Liệu đồng bộ thời gian có thành công hay không
  • Chuỗi thời gian đã định dạng (ví dụ: Văn bản thời gian: 14:32)

Nếu màn hình trống, Serial Monitor là nơi đầu tiên cần kiểm tra để xác nhận Wi-Fi và NTP đang hoạt động.

Trình diễn dự án

Sau khi tải lên và đặt lại:

  • ESP32 kết nối Wi-Fi
  • Đồng bộ thời gian từ pool.ntp.org
  • Hiển thị OK ngắn gọn trên ma trận
  • Liên tục cuộn thời gian hiện tại dưới dạng HH:MM

Tải xuống và liên kết

Mã đầy đủ được cung cấp bên dưới bài viết này. Các bộ phận, công cụ và bảng dữ liệu cũng được liên kết bên dưới bài viết này.

Hình ảnh

ESP32 S3 Matrix
ESP32 S3 Matrix
ESP32 S3 Matrix  pin out
ESP32 S3 Matrix pin out
ESP32-S3_RGB_8x8_matrix-3
ESP32-S3_RGB_8x8_matrix-3
ESP32-S3_RGB_8x8_matrix1
ESP32-S3_RGB_8x8_matrix1
ESP32-S3_RGB_8x8_matrix-2
ESP32-S3_RGB_8x8_matrix-2
ESP32-s3_internet_clock_animation
ESP32-s3_internet_clock_animation
868-ESP32-S3 RGB LED Matrix Internte Clock Project 1 - Basic Clock
Ngôn ngữ: C++
/*
This is ESP32 sketch that connects to the internet, gets the time and displays it on the RGB matrix
you must set your WiFi correctly to make sure it gets connected. 
 watch video https://youtube.com/shorts/4iWjLiD7fS8
 📚⬇️ Download and resource page https://robojax.com/RJT838
 * Author:  Ahmad Shamshiri (Robojax.com)
 * Date: 07 Jan 2026
www.Robojax.com
https://youTube.com/@robojax


*/
#include <WiFi.h>
#include "time.h"
#include <Adafruit_GFX.h>
#include <Adafruit_NeoMatrix.h>
#include <Adafruit_NeoPixel.h>

//set the color of diplay make of Red, Green and Blue 
unsigned int color_RED = 17;
unsigned int color_GREEN = 43;
unsigned int color_BLUE = 171;

// 👇 REPLACE these with your real home WiFi name & password
const char* WIFI_SSID     = "WiFi";
const char* WIFI_PASSWORD = "passW0rd";



#define MATRIX_PIN 14

Adafruit_NeoMatrix matrix(8, 8, MATRIX_PIN,
  NEO_MATRIX_TOP    + NEO_MATRIX_LEFT +
  NEO_MATRIX_ROWS   + NEO_MATRIX_PROGRESSIVE,
  NEO_RGB           + NEO_KHZ800);

char timeText[6] = "00:00";
int16_t scrollX = 8;
unsigned long lastScrollMs = 0;
const uint16_t scrollIntervalMs = 120;

unsigned long lastTimeUpdateMs = 0;
const uint16_t timeUpdateIntervalMs = 1000;

//prototypes
bool updateTimeText();  // forward declaration
void scrollTime();      // forward declaration



// NTP (time) server
const char* ntpServer = "pool.ntp.org";

// Toronto-ish: UTC-5, plus 1 hour DST
const long  gmtOffset_sec     = -5 * 3600;  // -5 hours
const int   daylightOffset_sec = 3600;      // +1 hour for DST



bool updateTimeText() {
  struct tm timeinfo;
  if (!getLocalTime(&timeinfo)) {
    Serial.println("Failed to obtain time for display");
    return false;
  }

  // Format HH:MM
  snprintf(timeText, sizeof(timeText), "%02d:%02d",
           timeinfo.tm_hour,
           timeinfo.tm_min);

  Serial.print("Time text: ");
  Serial.println(timeText);
  return true;
}

void scrollTime() {
  matrix.fillScreen(0);
  matrix.setCursor(scrollX, 0);
  matrix.print(timeText);
  matrix.show();

  scrollX--;

  // Rough width: 5 characters ("HH:MM") × 6 pixels each ≈ 30 px
  int16_t textWidth = 30;
  if (scrollX < -textWidth) {
    scrollX = matrix.width();  // reset to right edge (8)
  }
}


void initMatrix() {
  matrix.begin();
  matrix.setBrightness(40);        // be careful with heat
  matrix.setTextWrap(false);
  matrix.setTextColor(matrix.Color(color_RED, color_GREEN, color_BLUE)); // color of text
}

void showMessage(const char* msg) {
  matrix.fillScreen(0);
  matrix.setCursor(0, 0);  // top-left
  matrix.print(msg);
  matrix.show();
}


void printLocalTime() {
  struct tm timeinfo;
  if (!getLocalTime(&timeinfo)) {
    Serial.println("Failed to obtain time");
    return;
  }
  // Format: 2025-11-18 14:35:12
  Serial.printf("%04d-%02d-%02d %02d:%02d:%02d\n",
                timeinfo.tm_year + 1900,
                timeinfo.tm_mon + 1,
                timeinfo.tm_mday,
                timeinfo.tm_hour,
                timeinfo.tm_min,
                timeinfo.tm_sec);
}

void setup() {
  Serial.begin(115200);
  delay(1000);
  Serial.println();
  Serial.println("ESP32-S3 Internet Clock - WiFi + NTP test");

  // Connect to WiFi
  Serial.print("Connecting to WiFi: ");
  Serial.println(WIFI_SSID);
  WiFi.mode(WIFI_STA);
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);

  int retries = 0;
  while (WiFi.status() != WL_CONNECTED && retries < 30) { // ~15s timeout
    delay(500);
    Serial.print(".");
    retries++;
  }
  Serial.println();

  if (WiFi.status() != WL_CONNECTED) {
    Serial.println("WiFi connection FAILED");
  } else {
    Serial.print("WiFi connected. IP: ");
    Serial.println(WiFi.localIP());
  }

// if user set all colors to 0, the dispaly will be turned off so set it green
  if(color_RED ==0 & color_GREEN ==0 && color_BLUE ==0)
  {
    color_GREEN = 200;
  }

  // Configure time via NTP
  configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
  Serial.println("Waiting for time...");
  delay(2000); // small wait for initial sync

  printLocalTime(); // print once at startup

    // NEW: init the LED matrix and show a test message
  initMatrix();
  showMessage("OK");
}

void loop() {
  unsigned long now = millis();

  // Update the time string "HH:MM" once per second
  if (now - lastTimeUpdateMs >= timeUpdateIntervalMs) {
    lastTimeUpdateMs = now;
    updateTimeText();  // fills timeText[], e.g. "14:32"
  }

  // Scroll the time across the 8×8 every scrollIntervalMs
  if (now - lastScrollMs >= scrollIntervalMs) {
    lastScrollMs = now;
    scrollTime();      // uses timeText and scrollX
  }
}

Nghĩ bạn có thể cần

Tài nguyên & tài liệu tham khảo

Tập tin📁

Tập tin Fritzing