Introduction: Simple LED Matrix Clock - Internet Time Synced - ESP32 Based

When my very old analog wall clock stopped working, I wanted to quickly buy a new digital one, but then --- a 8x8 LED Matrix board with four modules, laying on my desk for a while, caught my attention --- and this should become a new little project. I thought about very minimal number of components, a few lines of micro-python code......... interested, you are invited to read on.

Specifications first:

  • Time should be internet synchronized
  • As we get UTC from the internet, correction for local time zone is required
  • As LEDs can be very bright, a brightness control is needed
  • Idea: wouldn't it be nice to have an ambient light dependent automatic brightness control?
  • A switch to cater for daylight savings time change
  • A real time clock to operate independent for some time and reduce internet traffic

Matching these specifications with my electronic component stock on hand, I took an ESP32 node MCU board, a light dependent resistor (LDR) and the LED Matrix board with max7219 controller chips to build what I call the "Dclock".

The ESP32 has an internal real time clock (RTC), which is used for the Dclock, but the RTC is not very accurate. With synchronization of the RTC with the internet time two times a day, accuracy is within 1 to 3 seconds late - good enough I think. If you need to sync more often, this can be set up in the dclock software, see Step 3.

Supplies

There are only 5 components needed, plus a breadboard to build the Dclock.

  1. an ESP32 node MCU board (each ESP32 based Board with enough GPIO pins should actually be OK for this project and ESP8266 based boards, with some modifications in HW and SW, see Step3)
  2. the 4x 8 by 8 LED Matrix board with max7219 controllers
  3. a toggle switch
  4. a LDR-05 light dependent resistor
  5. a 10kOhm resistor

Well, I always like to filter the supply voltage, so lets add

  • a 10uF electrolyte or tantalum capacitor (alternatively a 1uF capacitor will do as well)
  • and a 100nF ceramic capacitor

All these parts are available on the web stores of the big internet sellers and the IoT stores.

Step 1: Building on a Bread Board

Drawing the schematics on a piece of paper was quickly done (see picture), then put the components on a bread board and make following connections:

ESP32: --- Component:

  1. Pin13 MOSI --- LED Matrix Pin3 Din
  2. Pin14 SCK---LED Matrix Pin5 CLK
  3. Pin27 CS---LED Matrix Pin4 CS
  4. Pin34 ADC---voltage divider with R1 10KOhm and the LDR (see schematic)
  5. Pin23 GPIO---day light savings switch, the other pin of the switch is connected to ground
  6. 5V Vin---5V rail of the bread board
  7. 3v3 --- 3.3V rail of the breadboard
  8. Gnd --- ground rail of the breadboard
  9. Connect the Vcc pin of the LED Matrix to the 5V rail
  10. Connect the Gnd pin of the LED Matrix to the ground rail
  11. Connect the free end of R1 to the 3.3V rail
  12. Connect the free end of the LDR to the ground rail

Few remarks:

  • The breadboard can be powered via the USB connector of the ESP32, which we need to connect anyway to download the software.
  • ESP32 pin numbers are the GPIO Pin numbers, depending on the board you use, they could have different names, but the GPIO pin numbers are the same.
  • on the breadboard just use a jumper wire instead of the switch for testing
  • To send commands and data to the LED matrix the SPI interface of the ESP32 is used. There is no communication back to the ESP32, thus the SPI MISO of the ESP32 is not used.

For later use of an external power supply, I did some power consumption testing. The max current of the circuit was 940mA with all LEDs on max brightness (brightness=15). As I display time and there is no case that all LEDs are on at the same time, it is safe to use a 5V 1A USB power supply.

Step 2: Loading the Software

The Dclock is implemented in micro-python. As a first step load micro-python onto the ESP32. I use version 1.17 for the Dclock, but any other (newer preferred) version should work. If you need assistance there is a nice Getting started... tutorial and resource to understand how micro-python works on an ESP32.


Next Download the files attached below to your computer:

Credits: I am using the max7219 python "driver" module for the LED matrix developed by Max Causer, please see his git-hub page for more information. The driver max9219.py used for the Dclock is attached below for your convenience.


Preparation and configuration:

As Dclock uses a ntp internet time server few steps are required:

  1. Open the file wlanConnect.py and add the credentials of the wlan you want to use. You will find two lines for SSID and passkey in the function connect(). Enter your SSID and enter your wlan-passkey. Remark: You need to enter both between the quotation marks "....." ,do not remove the quotation marks. Please refer to the picture.
  2. You should use the ntp time server of your geography to reduce latency (and internet traffic) by editing the line host= ... in the file ntptime.py. See picture.
  3. As we get UTC time from the internet, Dclock needs to correct the time for the local time zone. In the file dclock.py is one dictionary called "STATE" with all the important variables and constants (see picture). In the line with "UTCdiff" change the +1 to the time zone you are in.
  4. Hint: In the module dclock.py you will find multiple print statements commented out. For debugging remove the "#" in front of the print statements in functions you want to debug and you will see the output in your console window on your PC.


Finally download all files to the ESP32 using your favorite tool or IDE (mpfshell, rshell, thonny...). A brief description of the function of these files:

  • wlanConnect.py module to connect the ESP32 to your wlan network
  • ntptime.py module to fetch internet time
  • max7219.py module with LED matrix specific functions
  • main.py module which imports dclock and starts it
  • dclock.py main program to run the digital clock


Power on Dclock:

If all worked well Dclock should start in the following way:

  1. After power on for a blink of an eye some LEDs could be on randomly
  2. When Dclock connects to your access point the word "wlan" will be displayed and upon successful connection
  3. "sync" will be displayed, which shows that Dclock connects to the ntp server to get the internet time
  4. Local time will be displayed
  5. By default a life tick is active, two LEDs in the third LED matrix module will be switched on and off every approx. 1 second to show the clock is still running

Remark:

  • Windows users should have python installed to execute the "esptool" to download micropython to the ESP32. A nice "how to install python on windows" is here.

Step 3: Finalization and "Tuning"

As I wanted to use the project to create a wall clock I did solder all components to a prototype board with copper stripes. I added a pin-header to connect to the LED matrix using a custom made 5 lead flat ribbon cable.

Initially I wanted to add a housing, but eventually I decided to mount the board and the LED matrix on an acrylic plate, so both, board and LED matrix display, are nicely visible. (see title picture)

Final thoughts and improvements:

  • If your ESP32's RTC has too much time deviation with two syncs daily, just add extra times for sync. The dictionary STATE has the element "sync_at", with contains a list of hours to sync, default is [8,20]. Just add more hours here for more syncs a day. Syncing happens at the begin of the hours in that list.
  • An external I2C RTC module could be added such as the "Tiny RTC module". My tests showed that this will not add more precision for time, but there are versions with a temperature sensor, so temp display could be added. Many public clocks switch between temp and time.
  • As we get not only time but date from the internet as well, the program could be extended to (1) either switch between date and time automatically or by the press of a button, a touch button could be used for that or (2) add another LED Matrix or seven segment module to display date.
  • In the function set_brightness() I use brightness 0,1,2,3 only. The LED module has a range of 0...15 for brightness. If you need more brightness, feel free to adjust to your needs.
  • There are two life ticks implemented in module dclock, life_tick(), default - which shows two LEDs on and off and life_tick1() which has four LEDs flashing like lights on a rail road crossing. Feel free to play around, you could show hearts, leafs... :-) .
  • The implementation would as well work on ESP8266 based boards. R1 would need to change to 100k to adapt to the 0...1V range of the ESP8266's ADC. The ADC is on a dedicated pin. Small adjustments in the program are needed for that. Please refer to the ESP8266 tutorial.