logo elektroda
logo elektroda
X
logo elektroda

Clock on ESP12 and MAX7219 display - tutorial - part 1, ArduinoOTA, basics

p.kaczmarek2  31 2937 Cool? (+11)
📢 Listen (AI):
ESP8266 Clock Project with MAX7219 Display
I will show here the design of a clock built on ESP8266 and MAX7219 based display, additionally enhanced with a relay module on MCP23017. The PCB under the ESP will come from the web, the relay module on the other hand I designed myself. I will assemble the firmware myself in PlatformIO from ready-made libraries. The time will be downloaded from the internet via NTP.
The main PCB for ESP12 used here is by "kbprogram" and was shared on his blog, and one of his pieces was sent to me by one of my readers (along with a bunch of other parts).
As a rule, ready-made kits (so-called kits) I never assemble and have never put together - even my first circuits made 6 or more years ago were DIY - including, for example, As a rule, I never put together a kit. with the TQFP tracing , or there with my PIC32 board , or with my Ethernet attempts on a PIC with everything I need built in .
In this case, however, since I had already received a PCB from a reader, I just decided to use it. Here are the contents of the whole package I received (I will try to describe something else from it in the future):
Set of electronic components and a blue PCB on a table. Cardboard box containing various electronic components, including a PCB board, relays, and a power plug.
Thank you for the package!
As for the relay module mentioned in turn, it was originally intended as an overlay for this project:
Home Assistant/Tasmota HTTP compatible relay controller + housing
But when ordering the boards I got 10 pieces, so there are some left over for other projects.
So much for the introduction, here we go.

Soldering the board
This board is a strange mix of THT and SMD. I don't know why exactly the author conceived it this way, maybe it was supposed to be a golden mean between size and soldering difficulty? You have the documentation of the project on the author's page given on the board. Basically, there is nothing to discuss here. Power block with a 3.3V LDO (I used a TC1264), ESP12, clock block with battery cage, I2C lines with pull up resistors, EEPROM also on I2C and basically that's it.
Blue PCB with electronic component markings for an LED clock. Blue PCB with etched traces and mounting holes.
Those SMD transistors on the bottom of the board are only needed if you want to reset the chip with lines from the UART. I myself reset and entered the programming state with buttons.
I soldered the WiFi module by making a drop of solder on one pad, grabbing that pad and then soldering the others.
PCB board with ESP8266 module and labeled connectors. PCB with mounted Wi-Fi module ESP12. WiFi module ESP mounted on a printed circuit board. PCB for LED matrix clock with labeled components on a blue background. PCB for LED matrix clock with labeled components on a blue background.
I had the 100nF decoupling capacitors in slightly smaller enclosures:
PCB with a soldered capacitor and placeholder for components. Electronic components for a clock project arranged on a table.
Almost ready, can be programmed:
Electronic kit consisting of a PCB with an ESP8266 module and a connected relay component. PCB for a clock project with ESP8266 and a TC1264 component
I still soldered the components, unfortunately the holes for the cage legs for the watch battery to hold the time were too small, I had to drill :
Close-up of a PCB with an ESP8266 module, resistors, and capacitors, and a slot for a clock battery.


ArduinoOTA, or convenient batch uploading via WiFi
For programming, I chose the PlatformIO platform. I have not been exposed to it before:
https://platformio.org/
Installation description for VSCode:
https://platformio.org/install/ide?install=vscode
The installation is done in two steps. First the VSCode and then the PlatformIO addon. It went without any problems.
For uploading the batch, I chose ArduinoOTA - that is, uploading the batch over WiFi.
Here is the platform.ini file used:

; PlatformIO Project Configuration File
;
;   Build options: build flags, source filter
;   Upload options: custom upload port, speed and extra flags
;   Library options: dependencies, extra library storages
;   Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html

[env:d1_mini]
platform = espressif8266
board = d1_mini
framework = arduino
monitor_speed = 115200
lib_deps = 
	me-no-dev/ESP Async WebServer@^1.2.3

[env:d1_mini_ota]
extends = env:d1_mini
upload_protocol = espota
upload_port = 192.168.0.124
lib_deps = 
	me-no-dev/ESP Async WebServer@^1.2.3

The skeleton of the OTA application with a wildly added LED blink on GPIO2, that is the LED on board the very WiFi module I had:
Code: C / C++
Log in, to see the code

This batch has to be uploaded once 'via cable', then it can be uploaded via WiFi.
The batch must be completed with the SSID and password of your WiFi network.
It is also important to set the IP as in the OTA configuration - in my case this is simply done by reserving an IP for the MAC of my ESP.

All without any problems. You can already program the ESP8266 over WiFi.

For a better configuration of our WIFi network the WiFiManager library could be plugged in:
https://www.arduino.cc/reference/en/libraries/wifimanager/
It would allow you to reset the WiFi configuration and roll back the device to AP configuration mode with a simple button, and then in AP mode enter our SSID and password, which is then remembered when switched off. A bit like the Tasmota.
But that's something I haven't implemented yet in this project.

Library MD_Parol
For the control of the MAX7219, I have chosen the MD_Parola library. It can be installed very easily via PlatformIO. Basically you just have to search for it and click through the installation process. Everything is automatic.
PlatformIO screenshot displaying the MD_Parola library.
Once you have searched for the library, you can select the version and click "Add to Project".
Screenshot of MD_Parola library registry on PlatformIO
PlatformIO libraries installation message
Using MD_Parol is really quite simple. The documentation is here:
https://github.com/MajicDesigns/MD_Parola
We define the type of display and its SPI pins (although this is truncated in his case, the communication is one way):
Code: C / C++
Log in, to see the code

We then initialise it via Begin:
Code: C / C++
Log in, to see the code

And then, already in the loop we can control and animate it.
Code: C / C++
Log in, to see the code


Below is my code with the library attached:
Code: C / C++
Log in, to see the code

Effect:
Clock based on ESP8266 with LED display MAX7219



NTP or internet time
I've written about my own NTP client here, among other things, but with PlatformIO and the ready-made Arduino libraries, you don't even need to know what UDP is - there's a ready-made one here too.
Adding NTPClient project dependency in PlatformIO.
We include the client header:
Code: C / C++
Log in, to see the code

We create the NTP client, it consists of two parts:
Code: C / C++
Log in, to see the code

The address of the time server can be changed. We set the time zone and start NTP:
Code: C / C++
Log in, to see the code

In a loop we update its operation:
Code: C / C++
Log in, to see the code

We still need to transfer the time to the display, but the Printf function already built into the Parola class will help us with this:
Code: C / C++
Log in, to see the code

All I had to do was add a few lines of code and there you go - we have a time display:
Code: C / C++
Log in, to see the code

NOTE: this hour one five will display what 1:5, there is no adding extra zeros here.
You can get the current date from NTP in a similar way, so it is very easy to expand on the previous example and get this effect:



Below is the full code for my date display, additionally relying on a helper function which formats the number by adding a preceding zero (so that, for example, 5 minutes past 10 is displayed as 10:05 rather than 10:5):
Code: C / C++
Log in, to see the code

Code: C / C++
Log in, to see the code

I haven't played around with checking the buffer size here, although it should be mentioned anyway. If the buffer given to sprintf is not of sufficient size then the sprintf operation has undefined effects, it will overwrite further memory contents. Consider using its safe counterpart, checking the size of the target buffer, for example sprintf_s.
It is worth noting that the text itself to the display is sent by this line:
Code: C / C++
Log in, to see the code

it also turns on the animation. Of course, there are other solutions, you can use a ready-made function to convert time to text:
Code: C / C++
Log in, to see the code

The advantage of this function is that it will not exceed the buffer size, so it is safer.

Relay board - MCP23017
As mentioned, this board is of my own making and on board it contains a port expander (16-bit) MCP23017 with I2C interface. For its control we need two lines - SDA and SCL. In addition, we need VDD - here 3.3V and relay supply - 5V. Some of the MCP23017 leads are brought out on goldpins, as I did not fit as many as 16 relays on the PCB. In addition, on the board there are pads allowing you to select the address of the expander (three address pins - A0, A1, A2), we can choose as many as 2^3 address combinations, so some of these expanders can be connected to the I2C bus.
Pinout diagram of the MCP23017 integrated circuit.
Time for soldering - I soldered the SMD in such a way that I first put the solder on one pad (with flux), then positioned the component with a pesette and melted this solder with a soldering tip, and then soldered its other leg.
Printed circuit board with markings and soldering points. Printed circuit board on wooden surface.
Binder jumpers for address selection:
Bottom of a green PCB with several SMD components.
Relay module PCB board
I used surface-mounted S9014 transistors:
Boxes labeled with electronic components.
Almost done:
Printed circuit board with relay components on a workbench
Circuit board with relay module and electronic components
Relay board based on MCP23017 on a wooden surface
Printed circuit board with four relays mounted on a workbench.


Observation of MCP23017
As before - we have the library ready.
https://github.com/adafruit/Adafruit-MCP23017-Arduino-Library
We install it:
Search results for MCP23017 libraries in PlatformIO.
We include the header:
Code: C / C++
Log in, to see the code

We create the object:
Code: C / C++
Log in, to see the code

The library assumes by default that we have connected all address pins to ground, as I also did, so you don't even need to specify the address.
It really surprised me too, here everything is simplified to the absolute minimum, it's so very friendly novice that a beginner doesn't even need to know about I2C addresses to use MCP....
It remains to modify my flashing condition in the main loop:
Code: C / C++
Log in, to see the code

Yes - that's really all it takes, just mcp.digitalWrite!
Result (need to include audio):



You can hear the relay working - blink works.


Web server
I then prepared a simple web server to configure the timer and relays based on AsyncWebServer, but.... i will put the details in the next section. The final plan is to develop a simple calendar on the web panel, where we can set when which relay switches on, preferably including the days of the week as well. Of course, there will also be an alarm clock based on a buzzer. But that is still some time away.

Summary
I basically started the project just out of curiosity, for a reader, because he just sent me parts for it. Even the board for this clock was not mine, but a ready-made one from the web. The whole thing went (or is going, as it is not ready yet) very smoothly and pleasantly. The ready-made libraries under ESP and the mass of examples make it all come together from ready-made components, without the need for any deep understanding of what works and how it works. This is very different from what I usually do, like the clock project on the PIC18F2550 . In that project I had to run most of the things myself, knowing more or less how they worked, while here you don't even need to know what protocol the MAX7219 uses to display text on it! Just whether this is good for beginners? Opinions are probably divided...

About Author
p.kaczmarek2
p.kaczmarek2 wrote 13353 posts with rating 11179 , helped 612 times. Been with us since 2014 year.

Comments

speedy9 30 Nov 2023 12:57

I'm probably going to look into this PlatformIO, because I find the Arduino a bit annoying, especially when it comes to libraries. And here and OTA easy. I look forward to the next part with the web s... [Read more]

Kuniarz 30 Nov 2023 13:48

Nice project, but I have a question from another side - what are these SMD component feeders ? Can you elaborate ? ;-) [Read more]

p.kaczmarek2 30 Nov 2023 14:08

@speedy9 PlatformIO is really convenient and easy to use. Additionally, it resides in VSCode, which I also use for purposes other than microcontroller programming. For example, it is convenient to write... [Read more]

khoam 30 Nov 2023 14:29

There is nothing stopping you from writing programs for the ESP8266 using the RTOS SDK directly, instead of the Arduino. PlatformIO also supports this toolchain: https://docs.platformio.org/en/stable/... [Read more]

krzbor 30 Nov 2023 20:08

Can you elaborate on this thought? [Read more]

pitsa 01 Dec 2023 18:41

Try ElegantOTA. [Read more]

Karol966 01 Dec 2023 21:50

I have a different opinion, my beginnings with it were difficult and because the trauma remained, today I probably wouldn't be able to create a new project, add libraries, etc. in a short time but would... [Read more]

p.kaczmarek2 22 Nov 2025 18:40

Update after two years - I am working on this project again: https://obrazki.elektroda.pl/3263592300_1763833201_thumb.jpg https://obrazki.elektroda.pl/2255219300_1763833201_thumb.jpg https://obrazki.elektroda.pl/3245452500_1763833201_thumb.jpg... [Read more]

max4elektroda 22 Nov 2025 19:00

Working - just synched today and fixed the berry part with NTP (since I changed to a general time source, using g_ntpTime directly is no longer possible (nor sensible), it's "Clock_GetCurrentTime()" now).... [Read more]

p.kaczmarek2 22 Nov 2025 21:13

No abnormal size increase on clock-disabled branches? What's current growth size for Beken and ... for BL602? And here is my preparation for running MAX7219 clock on Windows: https://obrazki.el... [Read more]

max4elektroda 22 Nov 2025 22:44

Please feel free to check yourself. https://github.com/openshwprojects/OpenBK7231T_App/pull/1792#issuecomment-3533382149 BL602 is 1.6k smaller, Beken most variants unchanged 0 bytes difference. [Read more]

p.kaczmarek2 22 Nov 2025 23:18

Acceptable, ready to merge now? [Read more]

max4elektroda 23 Nov 2025 09:57

Ready, though over the night I realized, DS3231 driver maybe should have a default behavior that setting device clock should also set RTC time automatically? Sure, this can be added later, will try in... [Read more]

p.kaczmarek2 23 Nov 2025 10:32

So you really want to match internal pin indexes with ESP indexes? Ok, I guess it's acceptable... we can bit the bullet and break configs on ESP8266 once. I didn't have time to to check whole code... [Read more]

max4elektroda 23 Nov 2025 12:33

It's no problem to leave setting RTC to the user or do a more sophisticated approach. In the end we only need to set the RTC if the new time differs. So maybe something like: set RTC regularly on every... [Read more]

p.kaczmarek2 23 Nov 2025 13:00

Any logic like "on every hour" seems to complicated, doesn't it? And timezone change should be outside RTC I think. RTC should always be in CET? I am not sure. I think the simplest is boolean bFirst to... [Read more]

max4elektroda 23 Nov 2025 15:25

checking (! g_secondsElapsed%3600) is easy, but that's not the point ;-) And you are of course right, timezone change is independent from UTC time - RTC like local clock will represent UTC.... [Read more]

p.kaczmarek2 23 Nov 2025 16:31

Ahh, okay, the module solution is also acceptable. You can do it that way. Just try to avoid too large code additions, as this feature seems to be mostly for us and more advanced users, so I think most... [Read more]

max4elektroda 23 Nov 2025 16:49

All "ntp_XY" commands are still present, calling the corresponding new "CLOCK_XY" commands to retain compatibility: $ find src/driver/ -name "*.[ch]" | xargs grep -i 'CMD_RegisterCommand("ntp_' src/driver/drv_ntp.c:... [Read more]

%}