Clock on ESP12 and MAX7219 display - tutorial - part 1, ArduinoOTA, basics
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):
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.
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.
I had the 100nF decoupling capacitors in slightly smaller enclosures:
Almost ready, can be programmed:
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 :
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++
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.
Once you have searched for the library, you can select the version and click "Add to Project".
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++
We then initialise it via Begin:
Code: C / C++
And then, already in the loop we can control and animate it.
Code: C / C++
Below is my code with the library attached:
Code: C / C++
Effect:
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.
We include the client header:
Code: C / C++
We create the NTP client, it consists of two parts:
Code: C / C++
The address of the time server can be changed. We set the time zone and start NTP:
Code: C / C++
In a loop we update its operation:
Code: C / C++
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++
All I had to do was add a few lines of code and there you go - we have a time display:
Code: C / C++
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++
Code: C / C++
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++
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++
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.
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.
Binder jumpers for address selection:
I used surface-mounted S9014 transistors:
Almost done:
Observation of MCP23017
As before - we have the library ready.
https://github.com/adafruit/Adafruit-MCP23017-Arduino-Library
We install it:
We include the header:
Code: C / C++
We create the object:
Code: C / C++
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++
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...
Comments
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]
Nice project, but I have a question from another side - what are these SMD component feeders ? Can you elaborate ? ;-) [Read more]
@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]
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]
Can you elaborate on this thought? [Read more]
Try ElegantOTA. [Read more]
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]
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]
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]
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]
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]
Acceptable, ready to merge now? [Read more]
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]
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]
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]
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]
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]
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]
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]