NTP synchronised clocks with ESP32 and WS2812B LED matrix

WS2812B LED matrix showing time

Inspiration for the project

A primary reason for me doing this project is that I have a WS2812B LED matrix for an unrelated project and wanted to play around with it to get a better understanding of how addressable RGB LEDs work. I’ve bought the ESP32 development board which Andreas Spiess used to make a video demonstrating how to get NTP working. In addition, it handles all the annoying timezone and daylight savings time adjustments. This was very appealing to me as I’ve made my own clocks, but with Arduino Uno, RTC module, and matrix display from a networking switch. I thought that making another clock this time with different hardware should be somewhat interesting.

Hardware overview

ESP32 is an IoT development platform made by Espressif featuring both WiFi and Bluetooth of which only WiFi will be used. Other than that it’s a pretty nice and powerful MCU with many more great features like ultra low power co-processor and even RTC. It’s also supported by the Arduino IDE that I’ve used for programming.

The second piece of hardware is an 8x32 LED matrix with WS2812B addressable RGB LEDs that are snaked across it in a single long chain. These LEDs manufactured by WorldSemi and their derivatives can be found in many gaming PCs, and other gaming products all over the world, providing their characteristic RGB glow. They are sold under different names, like Neopixels, and are well supported by libraries made for the Arduino IDE such as FastLED which I’ve used for this project.

Code overview

The program I’ve made is very simple and consists of three main stages: connecting to WiFi, synchronising with a NTP server and finally displaying time.

The SSID and password of the network that the ESP32 will connect to are provided in a separate header file called wifi_credentials.h located in the root project directory. Implementation of WiFi protocols and all the associated logic is provided by a library within the Arduino IDE that is included with the WiFi.h header file. All I need to do in order to connect to a WiFi network is to include this header, call WiFi.begin with the network credentials, and wait until calling WiFi.status returns WL_CONNECTED after which the ESP32 proceeds to synchronise with the NTP server.

To synchronise time with the NTP server correctly, I’ve set my timezone data into environment variable TZ using the setenv call provided by the ESP32 kernel. The timezone strings for any country can be found at this website and contain the information for setting the time correctly, even if your country is using daylight savings. After setting the timezone I can now call configTime with the NTP pool that I want to use and wait for time to be set correctly. This part is somewhat tricky because I couldn’t find a way of figuring out when it’s synchronised, so I just used the lazy approach of checking if the year is above 1970. It’s not pretty at all, but it works most of the time and it saved me some headaches.

Anyways, now that the ESP32 knows what time it is it can display it on the WS2812B LED matrix for which I used the FastLED library. In order to do this, I first made it possible to use regular XY coordinates to address individual LEDs in the LED matrix because it’s made up of a single chain of LEDs. Thankfully it’s possible to express XY position of each LED just by its position in the chain thanks to its simple repeating pattern. Being able to draw on the LED matrix with XY coordinates means that we can use a raster font to display the time. The specific font that I’ve used comes from this GitHub repository and individual characters require use of simple bitwise operators to convert them to be used to draw on the matrix with XY coordinates. This is the last step to start displaying the time using the FastLED library.

You can download the source code using the link below:
esp32-clock.zip (2.7KB)