Dans ce tutoriel, vous apprendrez comment implémenter une horloge numérique sur un CrowPanel 1.28″ Round Display avec un GC9A01 TFT en utilisant la bibliothèque Adafruit_GC9A01A. Le code exemple pour l’horloge vous montrera également comment utiliser l’écran tactile CST816D, le buzzer, le moteur de vibration, l’horloge temps réel (RTC) BM8563, le mode deep sleep et la synchronisation de l’heure via Internet.
Pièces requises
Évidemment, vous aurez besoin du module CrowPanel ESP32 1.28 pouces Round Display pour ce projet. À part un câble USB-C, généralement fourni avec le module d’affichage, aucune autre pièce n’est nécessaire.

CrowPanel ESP32 1.28″ Round Display
Caractéristiques du CrowPanel 1.28″ Round Display
Le module CrowPanel 1.28″ est composé d’un écran TFT rond (GC9A01) avec une résolution de 240×240 pixels, d’un écran tactile capacitif (CST816D) et d’un ESP32-C3 intégré. L’image ci-dessous montre la face avant du module :

En plus de l’ESP32, le module contient un buzzer, un moteur de vibration, une horloge temps réel (BM8563) avec batterie de secours, un support pour batterie LiPo avec chargeur et plusieurs boutons. L’image suivante montre l’arrière du module, où vous pouvez voir la plupart des composants :

Notez qu’il y a aussi un petit encodeur avec bouton (à gauche), qui permet essentiellement d’ajouter une couronne pour régler l’heure comme sur une montre mécanique – à condition d’écrire le code pour cela. Mais comme il est entièrement programmable, vous pouvez aussi contrôler toutes sortes d’autres fonctions ou interactions d’interface utilisateur avec lui.
Pour la programmation (et l’alimentation), il y a un port USB-C et des boutons Reset et Boot à l’arrière. Si une batterie LiPo est connectée, elle sera chargée via le port USB-C.
Le tableau suivant résume les principales caractéristiques du module d’affichage :
| Chip principal | ESP32-C3 |
| Processeur | Processeur RISC-V 32 bits monocœur, jusqu’à 160 MHz |
| Mémoire | 384 KB ROM, 400 KB SRAM (16 KB pour cache), 8 KB SRAM dans RTC |
| Taille | 1,28 pouce |
| Résolution | 240*240 |
| Interface de signal | SPI |
| Type de tactile | Tactile capacitif |
| Type de panneau | TFT LCD, panneau IPS |
| Profondeur de couleur | 262K |
| Luminosité | 350 cd/m² |
| Angle de vue | 178° |
| Boutons | Bouton Reset, Bouton Boot, Bouton personnalisé |
| Interface | Interface Type-C, interface batterie |
| Encodeur | Avec fonction bouton, sans broche (taille broche : 0,8mm*0,8mm) |
| Alimentation | Module : DC5V, Chip principal : 3,3V |
| Zone active | 32,51*32,51mm |
| Dimensions | 42*42*9,8mm |
| Poids net | 15g |
Horloge numérique sur CrowPanel 1.28″ Round Display
Dans cette section, nous allons implémenter une horloge numérique sur le CrowPanel 1.28″ Round Display. L’horloge affichera le nom du jour actuel, l’heure et la date. Nous pourrons aussi basculer entre le format 24h et 12h en touchant un bouton à l’écran. L’image ci-dessous montre le cadran de l’horloge avec ses fonctionnalités.

De plus, l’horloge peut être mise en mode deep sleep en appuyant sur le bouton physique à droite (à l’arrière) du module. Une seconde pression réveillera l’horloge. Ceci est essentiel si vous souhaitez faire fonctionner l’horloge sur batterie.
Nous ferons aussi sonner un ton toutes les heures et fournirons un retour tactile lors de l’appui sur le bouton tactile en activant le moteur de vibration.
Enfin, l’horloge synchronisera automatiquement l’horloge temps réel interne (RTC) avec un serveur de temps Internet (SNTP) si le WiFi est disponible.
Ainsi, nous aurons exploré la plupart des fonctionnalités techniques du CrowPanel Display – à l’exception du Bluetooth et de l’encodeur.
Code pour l’horloge numérique sur écran GC9A01
L’écran du CrowPanel 1.28″ est un écran GC9A01 avec un écran tactile CST816D. Nous utiliserons la bibliothèque Adafruit_GC9A01A pour dessiner sur l’écran, car elle est beaucoup plus simple que la bibliothèque LVGL utilisée pour le demo code fourni avec le CrowPanel.
Cependant, si vous souhaitez implémenter une interface utilisateur plus complexe avec des menus déroulants et d’autres fonctionnalités, la bibliothèque LVGL est la meilleure option.
Voici le code pour l’horloge numérique. C’est un morceau de code assez long, je vous suggère de le parcourir pour en avoir une vue d’ensemble. Nous discuterons des détails ensuite.
#include "WiFi.h"
#include "Adafruit_GFX.h"
#include "Adafruit_GC9A01A.h"
#include "I2C_BM8563.h"
#include "CST816D.h"
// I2C
#define SDA 4
#define SCL 5
#define PI4IO_I2C_ADDR 0x43
// TFT display
#define TFT_CS 10
#define TFT_DC 2
#define TFT_MOSI 7
#define TFT_SCLK 6
#define TFT_RST 4
#define TFT_BKL 2
#define DW 240
#define DH 240
// Touch panel
#define TP_INT 0
#define TP_RST 3
#define BUTTON 1
#define BUZZER 3
#define MOTOR 0
const char* SSID = "SSID";
const char* PWD = "PASSWORD";
bool is_24h = true;
const char* TIMEZONE = "AEST-10AEDT,M10.1.0,M4.1.0/3";
const char* DAYSTR[] = { "SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT" };
const char* MONTHSTR[] = { "Jan", "Feb", "Mar", "Apr", "May",
"Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
// touch button
const int bx = DW / 2;
const int by = DH - 30;
const int br = 10;
Adafruit_GC9A01A tft(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCLK);
I2C_BM8563 rtc(I2C_BM8563_DEFAULT_ADDRESS, Wire);
CST816D touch(SDA, SCL, TP_RST, TP_INT);
void init_ioex() {
Wire.begin(SDA, SCL);
Wire.beginTransmission(PI4IO_I2C_ADDR);
Wire.write(0x01); // test register
Wire.endTransmission();
Wire.requestFrom(PI4IO_I2C_ADDR, 1);
uint8_t rxdata = Wire.read();
Wire.beginTransmission(PI4IO_I2C_ADDR);
Wire.write(0x03);
Wire.write((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4));
Wire.endTransmission();
Wire.beginTransmission(PI4IO_I2C_ADDR);
Wire.write(0x07);
Wire.write(~((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4)));
Wire.endTransmission();
}
void write_ioex(uint8_t pin_number, bool value) {
Wire.beginTransmission(PI4IO_I2C_ADDR);
Wire.write(0x05); // test register
Wire.endTransmission();
Wire.requestFrom(PI4IO_I2C_ADDR, 1);
uint8_t rxdata = Wire.read();
Wire.beginTransmission(PI4IO_I2C_ADDR);
Wire.write(0x05); // Output register
if (!value)
Wire.write((~(1 << pin_number)) & rxdata);
else
Wire.write((1 << pin_number) | rxdata);
Wire.endTransmission();
Wire.beginTransmission(PI4IO_I2C_ADDR);
Wire.write(0x05); // test register
Wire.endTransmission();
Wire.requestFrom(PI4IO_I2C_ADDR, 1);
rxdata = Wire.read();
}
void set_rtc_time() {
rtc.begin();
struct tm t;
getLocalTime(&t);
I2C_BM8563_TimeTypeDef ts;
ts.hours = t.tm_hour;
ts.minutes = t.tm_min;
ts.seconds = t.tm_sec;
rtc.setTime(&ts);
I2C_BM8563_DateTypeDef ds;
ds.weekDay = t.tm_wday;
ds.month = t.tm_mon + 1;
ds.date = t.tm_mday;
ds.year = t.tm_year + 1900;
rtc.setDate(&ds);
}
void sync_time() {
WiFi.begin(SSID, PWD);
for (int i = 0; (i < 5) && (WiFi.status() != WL_CONNECTED); i++)
delay(100);
if (WiFi.status() == WL_CONNECTED) {
configTzTime(TIMEZONE, "pool.ntp.org");
set_rtc_time();
}
}
void display_time() {
static char buf[16];
static I2C_BM8563_DateTypeDef ds;
static I2C_BM8563_TimeTypeDef ts;
rtc.getDate(&ds);
rtc.getTime(&ts);
tft.setTextColor(GC9A01A_LIGHTGREY, GC9A01A_BLACK);
tft.setCursor(80, 60);
tft.setTextSize(4);
tft.print(DAYSTR[ds.weekDay]);
if (is_24h) {
sprintf(buf, "%02d:%02d:%02d", ts.hours, ts.minutes, ts.seconds);
} else {
int display_hours = ts.hours % 12;
display_hours = display_hours ? display_hours : 12;
const char* period = ts.hours >= 12 ? "pm" : "am";
sprintf(buf, "%02d:%02d %s", display_hours, ts.minutes, period);
}
tft.setTextColor(is_24h ? GC9A01A_WHITE : GC9A01A_YELLOW, GC9A01A_BLACK);
tft.setCursor(45, 110);
tft.setTextSize(3);
tft.print(buf);
sprintf(buf, "%2d %s %04d", ds.date, MONTHSTR[ds.month], ds.year);
tft.setTextColor(GC9A01A_WHITE, GC9A01A_BLACK);
tft.setCursor(45, 150);
tft.setTextSize(2);
tft.print(buf);
}
void sound_hour() {
static I2C_BM8563_TimeTypeDef ts;
rtc.getTime(&ts);
if (ts.minutes == 0 && ts.seconds == 0) {
tone(BUZZER, 1000);
delay(50);
tone(BUZZER, 0);
delay(500);
}
}
void check_touch() {
uint8_t gesture;
uint16_t x, y;
bool touched = touch.getTouch(&x, &y, &gesture);
if (touched) {
if (abs(x - bx) < 2*br && abs(y - by) < 2*br) {
write_ioex(MOTOR, true);
delay(50);
write_ioex(MOTOR, false);
is_24h = !is_24h;
display_touch();
delay(500);
}
}
}
void display_touch() {
if (is_24h) {
tft.fillCircle(bx, by, br, GC9A01A_BLACK);
tft.drawCircle(bx, by, br, GC9A01A_DARKGREY);
} else {
tft.fillCircle(bx, by, br, GC9A01A_DARKGREY);
}
}
void check_button() {
if (digitalRead(BUTTON) == LOW) {
tft.fillScreen(GC9A01A_BLACK);
write_ioex(TFT_BKL, false); // Switch off TFT backlight
delay(300);
esp_deep_sleep_start();
}
}
void init_deep_sleep() {
pinMode(BUTTON, INPUT);
esp_deep_sleep_enable_gpio_wakeup(1ULL << BUTTON, ESP_GPIO_WAKEUP_GPIO_LOW);
}
void init_buzzer() {
pinMode(BUZZER, OUTPUT);
digitalWrite(BUZZER, LOW);
}
void init_tft() {
tft.begin();
tft.setRotation(0);
tft.fillScreen(GC9A01A_BLACK);
display_touch();
}
void set_ioex_pins() {
write_ioex(TFT_RST, true); // TFT Reset
write_ioex(TP_RST, true); // Touch panel reset
write_ioex(TFT_BKL, true); // TFT backlight
}
void setup() {
Serial.begin(115200);
init_ioex();
set_ioex_pins();
touch.begin();
init_buzzer();
init_deep_sleep();
sync_time();
init_tft();
}
void loop() {
static unsigned long st = millis();
if (millis() - st > 300) {
display_time();
sound_hour();
st = millis();
}
check_touch();
check_button();
yield();
}
Décomposons le code en ses composants pour une meilleure compréhension.
Bibliothèques
Le code commence par inclure les bibliothèques nécessaires pour le WiFi, les graphismes, le contrôle de l’écran, l’horloge temps réel (RTC) et la fonctionnalité de l’écran tactile.
#include "WiFi.h" #include "Adafruit_GFX.h" #include "Adafruit_GC9A01A.h" #include "I2C_BM8563.h" #include "CST816D.h"
Vous devrez installer la bibliothèque Adafruit_GC9A01A. Ouvrez simplement le Library Manager, cherchez « Adafruit_GC9A01A » et cliquez sur « INSTALL ». L’image ci-dessous montre à quoi cela doit ressembler une fois installé :

De plus, vous aurez besoin des fichiers pour l’horloge temps réel I2C_BM8563 et l’écran tactile CST816D. Téléchargez le Arduino Demo Code, décompressez-le et allez dans le dossier ESP32_1.28_Arduino_Demo. Il doit contenir les sous-dossiers suivants :

Dans les sous-dossiers LvglWidgets et RTC vous trouverez les fichiers requis. Copiez-les dans le dossier de votre projet pour le code de l’horloge numérique. Le contenu du dossier projet devrait ressembler à ceci :

Comme vous pouvez le voir, j’ai nommé le sketch Arduino « CrowPanel-Digital-Clock-1-28-Inch.ino » et puisque le nom du dossier doit correspondre au sketch, il est « CrowPanel-Digital-Clock-1-28-Inch ». Mais vous pouvez le nommer différemment, assurez-vous juste que le nom du sketch et du dossier correspondent.
Cependant, pour simplifier, j’ai aussi compressé mon projet et vous pouvez le télécharger via le lien suivant :
Constantes
Ensuite, nous définissons des constantes pour la communication I2C, les broches de l’écran TFT et celles de l’écran tactile.
#define SDA 4 #define SCL 5 #define PI4IO_I2C_ADDR 0x43 #define TFT_CS 10 #define TFT_DC 2 #define TFT_MOSI 7 #define TFT_SCLK 6 #define TFT_RST 4 #define TFT_BKL 2 #define DW 240 #define DH 240 // Touch panel #define TP_INT 0 #define TP_RST 3 #define BUTTON 1 #define BUZZER 3 #define MOTOR 0
Vous pouvez trouver ces définitions de broches dans le code exemple et dans le Schematics of the CrowPanel 1.28″ Display. La section ci-dessous montre particulièrement le connecteur TFT et écran tactile :

Il est important de noter que le module CrowPanel contient un GPIO Expander (PI4IOE5V6408), car l’écran TFT utilise la plupart des broches de l’ESP32. Cela signifie que certaines broches sont des GPIO de l’ESP32, par exemple (BUZZER) et d’autres sont contrôlées via le GPIO Expander. Plus précisément, LCD_RESET (TFT_RST=4), TP_RESET (TP_RST=3), la LED de rétroéclairage LED_P2 (TFT_BKL=2) et le moteur de vibration MOTOR_P0 (MOTOR=0). Regardez le schéma du GPIO Expander ci-dessous :

Vous verrez plus tard dans le code que les broches ESP32 et celles du GPIO Expander doivent être contrôlées différemment.
Variables globales
Nous déclarons plusieurs variables globales, y compris les identifiants WiFi, les paramètres de fuseau horaire, et des tableaux pour les noms des jours et des mois. Nous définissons aussi une variable booléenne pour basculer entre les formats 12h et 24h.
const char* SSID = "SSID";
const char* PWD = "PASSWORD";
bool is_24h = true;
const char* TIMEZONE = "AEST-10AEDT,M10.1.0,M4.1.0/3";
const char* DAYSTR[] = { "SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT" };
const char* MONTHSTR[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
Notez que vous devrez remplacer les identifiants WiFi (SSID, PWD) par ceux de votre réseau WiFi.
Très probablement, vous voudrez aussi changer le TIMEZONE. J’utilise AEST-10AEDT,M10.1.0,M4.1.0/3, qui correspond à Melbourne, Australie. Cette chaîne indique le décalage horaire standard et les règles pour l’heure d’été.
Les parties de cette définition de fuseau horaire sont les suivantes :
- AEST : Heure normale de l’Est australien
- -10 : Décalage UTC de 10 heures en avance sur le Temps Universel Coordonné (UTC)
- AEDT : Heure d’été de l’Est australien
- M10.1.0 : Passage à l’heure d’été le premier dimanche d’octobre
- M4.1.0/3 : Retour à l’heure standard le premier dimanche d’avril, avec un décalage de 3 heures par rapport à l’UTC.
Pour d’autres définitions de fuseaux horaires, consultez le Posix Timezones Database. Copiez simplement la chaîne que vous y trouverez et modifiez la constante TIMEZONE en conséquence.
Les autres constantes sont simplement des chaînes pour les noms des jours et des mois. Vous pouvez les remplacer par des chaînes dans une autre langue, par exemple. Mais vous devrez garder des longueurs similaires.
Fonctions d’initialisation
Le code contient plusieurs fonctions pour initialiser différents composants. La fonction init_ioex() configure la communication I2C et le GPIO Expander.
void init_ioex() {
Wire.begin(SDA, SCL);
Wire.beginTransmission(PI4IO_I2C_ADDR);
Wire.write(0x01); // test register
...
}
Ce code provient du fichier de démonstration LvglWidgets.ino. J’ai légèrement changé le nom et supprimé quelques instructions d’impression, mais sinon c’est le même code.
Il en va de même pour la fonction write_ioex() ci-dessous, qui permet d’écrire sur les broches GPIO de l’IO Expander :
void write_ioex(uint8_t pin_number, bool value) {
Wire.beginTransmission(PI4IO_I2C_ADDR);
Wire.write(0x05); // test register
...
}
La fonction init_tft() définit les réglages par défaut pour le dessin sur l’écran TFT et dessine aussi le cercle blanc qui représente le bouton tactile en appelant display_touch() :
void init_tft() {
tft.begin();
tft.setRotation(0);
tft.fillScreen(GC9A01A_BLACK);
display_touch();
}
La fonction init_deep_sleep() configure le bouton qui réveille l’ESP32 du mode deep sleep :
void init_deep_sleep() {
pinMode(BUTTON, INPUT);
esp_deep_sleep_enable_gpio_wakeup(1ULL << BUTTON, ESP_GPIO_WAKEUP_GPIO_LOW);
}
Enfin, la fonction init_buzzer() configure la broche du buzzer.
void init_buzzer() {
pinMode(BUZZER, OUTPUT);
digitalWrite(BUZZER, LOW);
}
RTC et synchronisation de l’heure
La fonction set_rtc_time() initialise la RTC et règle l’heure et la date actuelles basées sur l’heure locale récupérée via la connexion WiFi.
void set_rtc_time() {
rtc.begin();
struct tm t;
getLocalTime(&t);
// Set RTC time and date...
}
Cette heure locale est synchronisée avec un fournisseur de temps Internet (serveur SNTP) via la fonction sync_time() :
void sync_time() {
WiFi.begin(SSID, PWD);
for (int i = 0; (i < 5) && (WiFi.status() != WL_CONNECTED); i++)
delay(100);
if (WiFi.status() == WL_CONNECTED) {
configTzTime(TIMEZONE, "pool.ntp.org");
set_rtc_time();
}
}
Notez que la fonction essaie 5 fois de se connecter au WiFi puis abandonne. C’est volontaire ! Si vous utilisez l’horloge hors de votre réseau WiFi, elle ne pourra pas se connecter ni se synchroniser au redémarrage. Ce n’est pas grave, car la RTC gardera la trace du temps.
Cependant, comme nous ne synchronisons qu’au redémarrage de l’ESP32 et que la RTC ne gère pas l’heure d’été, l’horloge ne prendra pas en compte le passage entre heure d’été et heure standard. Il existe des solutions pour cela. Consultez le tutoriel Real-Time-Clock DS3231 with ESP32.
Affichage de l’heure
La fonction display_time() récupère l’heure et la date actuelles de la RTC et les affiche à l’écran TFT aux emplacements appropriés. Selon l’état du drapeau is_24h, elle formate l’heure en 12h ou 24h.
void display_time() {
static char buf[16];
static I2C_BM8563_DateTypeDef ds;
static I2C_BM8563_TimeTypeDef ts;
...
if (is_24h) {
sprintf(buf, "%02d:%02d:%02d", ts.hours, ts.minutes, ts.seconds);
} else {
int display_hours = ts.hours % 12;
display_hours = display_hours ? display_hours : 12;
const char* period = ts.hours >= 12 ? "pm" : "am";
sprintf(buf, "%02d:%02d %s", display_hours, ts.minutes, period);
}
...
}
Notez que vous ne pouvez pas facilement utiliser une autre police pour afficher l’heure et la date. La bibliothèque Adafruit_GC9A01A permet de définir une couleur de fond lors de l’impression du texte, ce qui efface l’heure et la date précédemment affichées.
tft.setTextColor(GC9A01A_WHITE, GC9A01A_BLACK); ... tft.print(buf);
Cependant, cela ne fonctionne que pour la police par défaut et pas pour les polices proportionnelles. Pour plus d’informations, consultez le Adafruit GFX Graphics Library Documentation. Une solution serait d’utiliser un Canvas, mais c’est plus complexe et le rafraîchissement de l’écran TFT pourrait être lent.
Bouton tactile
La fonction check_touch() détecte les événements tactiles sur l’écran tactile. Si le toucher est proche de la zone définie pour le bouton (le cercle blanc), elle active le moteur de vibration pendant une courte période pour fournir un retour tactile.
void check_touch() {
uint8_t gesture;
uint16_t x, y;
bool touched = touch.getTouch(&x, &y, &gesture);
if (touched) {
if (abs(x - bx) < 2*br && abs(y - by) < 2*br) {
write_ioex(MOTOR, true);
delay(50);
write_ioex(MOTOR, false);
is_24h = !is_24h;
display_touch();
delay(500);
}
}
}
Elle bascule ensuite le format de l’heure et met à jour l’affichage. L’image suivante montre les deux états de l’affichage :

Le petit cercle blanc en bas de l’écran représente le bouton tactile et est dessiné par la fonction display_touch(). Selon son état, il est dessiné comme un cercle plein ou vide :
void display_touch() {
if (is_24h) {
tft.fillCircle(bx, by, br, GC9A01A_BLACK);
tft.drawCircle(bx, by, br, GC9A01A_DARKGREY);
} else {
tft.fillCircle(bx, by, br, GC9A01A_DARKGREY);
}
}
Bouton deep sleep
La fonction check_button() vérifie si le bouton physique sur le côté du module est pressé. Si oui, elle met l’appareil en mode deep sleep. Surtout, elle éteint aussi la LED de rétroéclairage de l’écran TFT pour économiser la batterie.
void check_button() {
if (digitalRead(BUTTON) == LOW) {
tft.fillScreen(GC9A01A_BLACK);
write_ioex(TFT_BKL, false); // Switch off TFT backlight
delay(300);
esp_deep_sleep_start();
}
}
Une seconde pression sur le bouton réveille l’ESP32. Notez que ce bouton a une résistance de tirage interne et passe donc à LOW lorsqu’il est pressé. Voir le schéma ci-dessous :

Fonctions de configuration
La fonction setup() initialise la communication série, le GPIO Expander, l’écran tactile, le buzzer et l’écran TFT, et synchronise l’heure.
void setup() {
Serial.begin(115200);
init_ioex();
...
}
Cela signifie que l’horloge ne se synchronise avec l’heure Internet qu’au redémarrage. Cela économise la batterie, car vous pouvez éteindre le WiFi après un redémarrage. Cependant, vous pourriez décider de synchroniser plus fréquemment, par exemple une fois par heure pour prendre en compte le passage à l’heure d’été.
Fonction loop
La fonction loop() met à jour en continu l’affichage de l’heure et de la date toutes les 300 millisecondes et vérifie les événements tactiles et l’état du bouton. Vous pourriez ajouter un court délai de 50 ms au lieu de l’appel à la fonction yield().
void loop() {
static unsigned long st = millis();
if (millis() - st > 300) {
display_time();
sound_hour();
st = millis();
}
check_touch();
check_button();
yield();
}
Démo de l’horloge numérique
Le court clip vidéo suivant montre l’horloge en action. Vous pouvez voir l’heure défiler, le basculement entre les formats 24h et 12h lorsque le bouton tactile est pressé, et le mode deep sleep :

Et voilà ! Nous avons exploré la plupart des fonctionnalités du CrowPanel 1.28″ Display et vous devriez maintenant être bien préparé pour implémenter votre propre horloge avec ses fonctionnalités uniques.
Conclusions
Dans ce tutoriel, vous avez appris à implémenter une horloge numérique sur un CrowPanel 1.28″ Display Module. Nous avons utilisé de nombreuses fonctionnalités du module d’affichage, y compris l’écran tactile, le buzzer, le moteur de vibration et la RTC. Nous avons aussi appris à synchroniser la RTC avec un fournisseur de temps Internet et à mettre l’horloge en mode deep sleep.
Si vous souhaitez en savoir plus sur la synchronisation de l’heure, consultez le tutoriel How to synchronize ESP32 clock with SNTP server, et le tutoriel Real-Time-Clock DS3231 with ESP32 vous aidera à implémenter la prise en charge de l’heure d’été.
Et, si vous voulez implémenter une horloge analogique, le Analog Clock on e-Paper Display contiendra des informations utiles, bien qu’il soit destiné à un écran E-Paper et non à un écran TFT.
Sinon, il y a beaucoup, beaucoup de fonctions que vous pourriez ajouter à votre horloge. Une évidente serait l’affichage des informations météo. Consultez le tutoriel Simple ESP32 Internet Weather Station pour un exemple. Il y a aussi des informations sur comment connect the CrowPanel Module vers Home Assistant.
Si vous avez des questions, n’hésitez pas à les laisser dans la section commentaires.
Amusez-vous bien et bon bricolage ; )
Liens
Voici quelques liens que j’ai trouvés utiles lors de la rédaction de ce tutoriel :

