IoT / Electronics - Tips & Tricks

ESP32 Clock using 8×32 LED panel

Items used:

  • Hardware:
    • ESP 32 (CP2102 Driver, 30 PIN)
    • Dot Matrix Display (MAX7219 – 8×32)
    • Jumper cables
  • Sofware
    • VSCode
    • PlatformIO extension
  • Programming
    • C++

Connector mapping:

ESP32MAX7219
VINVCC
GNDGND
D23DIN
D18CS
D19CLK

platformio.ini:

[env:esp32dev]
platform = espressif32
board = esp32dev
framework = arduino
monitor_speed = 115200

lib_deps =
  majicdesigns/MD_Parola @ ^3.7.1
  majicdesigns/MD_MAX72XX @ ^3.4.1

main.cpp:

#include <Arduino.h>
#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <SPI.h>
#include <WiFi.h>
#include <time.h>

#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
#define MAX_DEVICES 4
#define CS_PIN 5

constexpr char WIFI_SSID[] = "ABC";
constexpr char WIFI_PASSWORD[] = "ABC";
constexpr long GMT_OFFSET_SECONDS = 19800;
constexpr int DAYLIGHT_OFFSET_SECONDS = 0;
constexpr char NTP_SERVER_1[] = "pool.ntp.org";
constexpr char NTP_SERVER_2[] = "time.nist.gov";
constexpr char NTP_SERVER_3[] = "time.google.com";

char timeBuffer[6] = "00:00";
unsigned long lastDisplayUpdate = 0;
int lastShownSecond = -1;

// Create the display object
MD_Parola myDisplay = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);

void connectToWiFi() {
  WiFi.mode(WIFI_STA);
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
  }
}

bool syncTimeFromInternet() {
  configTime(GMT_OFFSET_SECONDS, DAYLIGHT_OFFSET_SECONDS, NTP_SERVER_1, NTP_SERVER_2, NTP_SERVER_3);

  struct tm timeInfo;
  for (int attempt = 0; attempt < 30; ++attempt) {
    if (getLocalTime(&timeInfo)) {
      return true;
    }
    delay(500);
  }

  return false;
}

void updateClockDisplay(const struct tm& timeInfo) {
  const char separator = (timeInfo.tm_sec % 2 == 0) ? ' ' : ':';
  snprintf(timeBuffer, sizeof(timeBuffer), "%02d%c%02d", timeInfo.tm_hour, separator, timeInfo.tm_min);
  myDisplay.displayText(timeBuffer, PA_CENTER, 0, 0, PA_PRINT, PA_NO_EFFECT);
  myDisplay.displayReset();
}

void setup() {
  Serial.begin(115200);

  myDisplay.begin();
  myDisplay.displayClear();

  // Set brightness level from 0 to 15
  myDisplay.setIntensity(5);

  connectToWiFi();

  if (!syncTimeFromInternet()) {
    snprintf(timeBuffer, sizeof(timeBuffer), "--:--");
    myDisplay.displayText(timeBuffer, PA_CENTER, 0, 0, PA_PRINT, PA_NO_EFFECT);
    myDisplay.displayReset();
  }
}

void loop() {
  struct tm timeInfo;
  if (getLocalTime(&timeInfo)) {
    if (timeInfo.tm_sec != lastShownSecond) {
      lastShownSecond = timeInfo.tm_sec;
      updateClockDisplay(timeInfo);
    }
  }

  if (millis() - lastDisplayUpdate >= 50) {
    lastDisplayUpdate = millis();
    myDisplay.displayAnimate();
  }
}

Leave a Reply