Analog Clock OLED
Contents
- 1 Analog Clock 128X128 OLED 1
- 2 Analog Clock 128X128 OLED 2
- 3 Analog Clock 128X64 OLED 2.1 Tool
- 4 Analog Clock 128X128 OLED 2.2
- 5 Analog Clock 128X128 OLED 3
- 6 Analog Clock 128X128 OLED 4
- 7 Analog Clock 128X128 OLED 5 Tool
- 8 Analog Clock 128×64 OLED 6
- 9 Analog Clock 128×64 OLED 7
- 10 Analog Clock 128X64 OLED 7.1 Tool
- 11 Analog Clock 128X64 OLED 7.2
- 12 Analog Clock 128X64 OLED 8
Analog Clock 128X128 OLED 1[edit]
#include <Wire.h>
#include <WiFi.h>
#include "time.h"
#include "sntp.h"
#include <U8g2lib.h>
// ---- WiFi ----
const char* ssid = "TonSSID";
const char* password = "TonMotDePasse";
// ---- Serveurs NTP ----
const char* ntpServer1 = "pool.ntp.org";
const char* ntpServer2 = "time.nist.gov";
// ---- OLED Grove 1.12" SH1107 ----
// U8G2_SH1107_PIMAR_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
U8G2_SH1107_SEEED_128X128_1_SW_I2C u8g2(U8G2_R0, /* clock=*/ SCL, /* data=*/ SDA, /* reset=*/ U8X8_PIN_NONE);
// ---- Variables temps ----
int hrs, mins, secs;
int day, month, year, wday;
// ---- Tableau des jours (français) ----
const char* jours[] = {"Dimanche","Lundi","Mardi","Mercredi","Jeudi","Vendredi","Samedi"};
// ---- Cadran ----
const int CENTER_X = 64; // centre écran
const int CENTER_Y = 64;
const int RADIUS = 55; // grand rayon pour 128x128
void setup() {
Serial.begin(115200);
// Connexion WiFi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println(" CONNECTÉ");
// Fuseau CET/CEST (Suisse) avec gestion automatique du DST
configTzTime("CET-1CEST,M3.5.0/2,M10.5.0/3", ntpServer1, ntpServer2);
// Init OLED
u8g2.begin();
}
void loop() {
setLocalTime();
// ---- Calcul des angles ----
float secAngle = secs * 6;
float minAngle = mins * 6 + secs * 0.1;
float hrAngle = (hrs % 12) * 30 + mins * 0.5;
// ---- Positions des aiguilles ----
int hrX = CENTER_X + (RADIUS - 20) * cos((hrAngle - 90) * PI / 180);
int hrY = CENTER_Y + (RADIUS - 20) * sin((hrAngle - 90) * PI / 180);
int minX = CENTER_X + (RADIUS - 10) * cos((minAngle - 90) * PI / 180);
int minY = CENTER_Y + (RADIUS - 10) * sin((minAngle - 90) * PI / 180);
int secX = CENTER_X + (RADIUS - 2) * cos((secAngle - 90) * PI / 180);
int secY = CENTER_Y + (RADIUS - 2) * sin((secAngle - 90) * PI / 180);
// ---- Dessin ----
u8g2.clearBuffer();
// ---- Affichage jour + date en haut ----
char bufferDate[30];
sprintf(bufferDate, "%s %02d/%02d/%04d", jours[wday], day, month, year);
u8g2.setFont(u8g2_font_6x13_tr);
u8g2.drawStr(CENTER_X - 45, 12, bufferDate);
// Cadran principal
u8g2.drawCircle(CENTER_X, CENTER_Y, RADIUS);
// Chiffres 12-3-6-9
u8g2.setFont(u8g2_font_ncenB08_tr);
u8g2.drawStr(CENTER_X - 6, CENTER_Y - RADIUS - 5, "12");
u8g2.drawStr(CENTER_X + RADIUS - 10, CENTER_Y + 4, "3");
u8g2.drawStr(CENTER_X - 6, CENTER_Y + RADIUS + 12, "6");
u8g2.drawStr(CENTER_X - RADIUS - 12, CENTER_Y + 4, "9");
// Aiguilles
u8g2.drawLine(CENTER_X, CENTER_Y, hrX, hrY); // heures
u8g2.drawLine(CENTER_X, CENTER_Y, minX, minY); // minutes
u8g2.drawLine(CENTER_X, CENTER_Y, secX, secY); // secondes
// ---- Affichage digital en bas ----
char bufferTime[10];
sprintf(bufferTime, "%02d:%02d:%02d", hrs, mins, secs);
u8g2.setFont(u8g2_font_ncenB14_tr);
u8g2.drawStr(CENTER_X - 30, 120, bufferTime);
u8g2.sendBuffer();
delay(1000);
}
void setLocalTime() {
struct tm timeinfo;
if (!getLocalTime(&timeinfo)) {
Serial.println("Pas encore d'heure disponible");
return;
}
hrs = timeinfo.tm_hour;
mins = timeinfo.tm_min;
secs = timeinfo.tm_sec;
day = timeinfo.tm_mday;
month = timeinfo.tm_mon + 1; // tm_mon commence à 0
year = timeinfo.tm_year + 1900;
wday = timeinfo.tm_wday; // jour de la semaine (0 = dimanche)
Serial.printf("%s %02d/%02d/%04d %02d:%02d:%02d\n",
jours[wday], day, month, year, hrs, mins, secs);
}
Analog Clock 128X128 OLED 2[edit]
Ajout de const int Y_OFFSET = 16;
Application de + Y_OFFSET sur toutes les coordonnées Y (drawStr, drawLine, drawCircle, calcul des aiguilles).
pas vraiment, il semble avoir un problème avec l'offset négatif ou positif, on a légèrement un affichage.
#include <Wire.h>
#include <WiFi.h>
#include "time.h"
#include "sntp.h"
#include <U8g2lib.h>
// ---- WiFi ----
const char* ssid = "TonSSID";
const char* password = "TonMotDePasse";
// ---- Serveurs NTP ----
const char* ntpServer1 = "pool.ntp.org";
const char* ntpServer2 = "time.nist.gov";
// ---- OLED Grove 1.12" SH1107 ----
U8G2_SH1107_SEEED_128X128_1_SW_I2C u8g2(U8G2_R0, /* clock=*/ SCL, /* data=*/ SDA, /* reset=*/ U8X8_PIN_NONE);
// ---- Variables temps ----
int hrs, mins, secs;
int day, month, year, wday;
// ---- Tableau des jours (français) ----
const char* jours[] = {"Dimanche","Lundi","Mardi","Mercredi","Jeudi","Vendredi","Samedi"};
// ---- Cadran ----
const int CENTER_X = 64; // centre écran
const int CENTER_Y = 64;
const int RADIUS = 55; // grand rayon pour 128x128
// ---- Correction Y pour SH1107 ----
const int Y_OFFSET = 16;
void setup() {
Serial.begin(115200);
// Connexion WiFi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println(" CONNECTÉ");
// Fuseau CET/CEST (Suisse) avec gestion automatique du DST
configTzTime("CET-1CEST,M3.5.0/2,M10.5.0/3", ntpServer1, ntpServer2);
// Init OLED
u8g2.begin();
}
void loop() {
setLocalTime();
// ---- Calcul des angles ----
float secAngle = secs * 6;
float minAngle = mins * 6 + secs * 0.1;
float hrAngle = (hrs % 12) * 30 + mins * 0.5;
// ---- Positions des aiguilles ----
int hrX = CENTER_X + (RADIUS - 20) * cos((hrAngle - 90) * PI / 180);
int hrY = CENTER_Y + (RADIUS - 20) * sin((hrAngle - 90) * PI / 180) + Y_OFFSET;
int minX = CENTER_X + (RADIUS - 10) * cos((minAngle - 90) * PI / 180);
int minY = CENTER_Y + (RADIUS - 10) * sin((minAngle - 90) * PI / 180) + Y_OFFSET;
int secX = CENTER_X + (RADIUS - 2) * cos((secAngle - 90) * PI / 180);
int secY = CENTER_Y + (RADIUS - 2) * sin((secAngle - 90) * PI / 180) + Y_OFFSET;
// ---- Dessin ----
u8g2.clearBuffer();
// ---- Affichage jour + date en haut ----
char bufferDate[30];
sprintf(bufferDate, "%s %02d/%02d/%04d", jours[wday], day, month, year);
u8g2.setFont(u8g2_font_6x13_tr);
u8g2.drawStr(CENTER_X - 45, 12 + Y_OFFSET, bufferDate);
// Cadran principal
u8g2.drawCircle(CENTER_X, CENTER_Y + Y_OFFSET, RADIUS);
// Chiffres 12-3-6-9
u8g2.setFont(u8g2_font_ncenB08_tr);
u8g2.drawStr(CENTER_X - 6, CENTER_Y - RADIUS - 5 + Y_OFFSET, "12");
u8g2.drawStr(CENTER_X + RADIUS - 10, CENTER_Y + 4 + Y_OFFSET, "3");
u8g2.drawStr(CENTER_X - 6, CENTER_Y + RADIUS + 12 + Y_OFFSET, "6");
u8g2.drawStr(CENTER_X - RADIUS - 12, CENTER_Y + 4 + Y_OFFSET, "9");
// Aiguilles
u8g2.drawLine(CENTER_X, CENTER_Y + Y_OFFSET, hrX, hrY); // heures
u8g2.drawLine(CENTER_X, CENTER_Y + Y_OFFSET, minX, minY); // minutes
u8g2.drawLine(CENTER_X, CENTER_Y + Y_OFFSET, secX, secY); // secondes
// ---- Affichage digital en bas ----
char bufferTime[10];
sprintf(bufferTime, "%02d:%02d:%02d", hrs, mins, secs);
u8g2.setFont(u8g2_font_ncenB14_tr);
u8g2.drawStr(CENTER_X - 30, 120 + Y_OFFSET, bufferTime);
u8g2.sendBuffer();
delay(1000);
}
void setLocalTime() {
struct tm timeinfo;
if (!getLocalTime(&timeinfo)) {
Serial.println("Pas encore d'heure disponible");
return;
}
hrs = timeinfo.tm_hour;
mins = timeinfo.tm_min;
secs = timeinfo.tm_sec;
day = timeinfo.tm_mday;
month = timeinfo.tm_mon + 1; // tm_mon commence à 0
year = timeinfo.tm_year + 1900;
wday = timeinfo.tm_wday; // jour de la semaine (0 = dimanche)
Serial.printf("%s %02d/%02d/%04d %02d:%02d:%02d\n",
jours[wday], day, month, year, hrs, mins, secs);
}
Analog Clock 128X64 OLED 2.1 Tool[edit]
deux ovales ! pas bon !
#include <Wire.h>
#include <U8g2lib.h>
// ---- OLED 128x64 SSD1315 ----
//U8G2_SSD1315_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, /* clock=*/ SCL, /* data=*/ SDA, /* reset=*/ U8X8_PIN_NONE);
U8G2_SSD1306_128X64_ALT0_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
// ---- Variables temps ----
int hrs = 10, mins = 15, secs = 30; // exemple fixe pour test
// ---- Paramètres écran ----
const int LARGEUR_ECRAN = 128;
const int HAUTEUR_ECRAN = 64;
// ---- Marges en % ----
const float MARGE_HAUT_PCT = 0.10; // 10% haut
const float MARGE_BAS_PCT = 0.10; // 10% bas
const float MARGE_GAUCHE_PCT = 0.10; // 10% gauche
const float MARGE_DROITE_PCT = 0.10; // 10% droite
void setup() {
Serial.begin(115200);
u8g2.begin();
}
void loop() {
// ---- Calcul des marges en pixels ----
int margeHaut = (int)(HAUTEUR_ECRAN * MARGE_HAUT_PCT);
int margeBas = (int)(HAUTEUR_ECRAN * MARGE_BAS_PCT);
int margeGauche = (int)(LARGEUR_ECRAN * MARGE_GAUCHE_PCT);
int margeDroite = (int)(LARGEUR_ECRAN * MARGE_DROITE_PCT);
// ---- Dimensions utiles ----
int largeurUtile = LARGEUR_ECRAN - (margeGauche + margeDroite);
int hauteurUtile = HAUTEUR_ECRAN - (margeHaut + margeBas);
// ---- Centre du cercle ----
const int CENTER_X = margeGauche + largeurUtile / 2;
const int CENTER_Y = margeHaut + hauteurUtile / 2;
// ---- Rayon adapté (prendre le plus petit côté utile / 2) ----
const int RADIUS = min(largeurUtile, hauteurUtile) / 2 - 5;
// ---- Calcul des angles ----
float secAngle = secs * 6;
float minAngle = mins * 6 + secs * 0.1;
float hrAngle = (hrs % 12) * 30 + mins * 0.5;
// ---- Positions des aiguilles ----
int hrX = CENTER_X + (RADIUS - 8) * cos((hrAngle - 90) * PI / 180);
int hrY = CENTER_Y + (RADIUS - 8) * sin((hrAngle - 90) * PI / 180);
int minX = CENTER_X + (RADIUS - 4) * cos((minAngle - 90) * PI / 180);
int minY = CENTER_Y + (RADIUS - 4) * sin((minAngle - 90) * PI / 180);
int secX = CENTER_X + (RADIUS - 2) * cos((secAngle - 90) * PI / 180);
int secY = CENTER_Y + (RADIUS - 2) * sin((secAngle - 90) * PI / 180);
// ---- Dessin ----
u8g2.clearBuffer();
// Cercle principal
u8g2.drawCircle(CENTER_X, CENTER_Y, RADIUS);
// Chiffres 12-3-6-9
u8g2.setFont(u8g2_font_ncenB08_tr);
u8g2.drawStr(CENTER_X - 6, CENTER_Y - RADIUS - 2, "12");
u8g2.drawStr(CENTER_X + RADIUS - 6, CENTER_Y + 4, "3");
u8g2.drawStr(CENTER_X - 6, CENTER_Y + RADIUS + 10, "6");
u8g2.drawStr(CENTER_X - RADIUS - 10, CENTER_Y + 4, "9");
// Aiguilles
u8g2.drawLine(CENTER_X, CENTER_Y, hrX, hrY);
u8g2.drawLine(CENTER_X, CENTER_Y, minX, minY);
u8g2.drawLine(CENTER_X, CENTER_Y, secX, secY);
u8g2.sendBuffer();
delay(1000);
}
Analog Clock 128X128 OLED 2.2[edit]
Code pour SH1107 avec offset
#include <Wire.h>
#include <WiFi.h>
#include "time.h"
#include "sntp.h"
#include <U8g2lib.h>
// ---- WiFi ----
const char* ssid = "TonSSID";
const char* password = "TonMotDePasse";
// ---- Serveurs NTP ----
const char* ntpServer1 = "pool.ntp.org";
const char* ntpServer2 = "time.nist.gov";
// ---- OLED 128x128 SH1107 ----
U8G2_SH1107_SEEED_128X128_1_SW_I2C u8g2(U8G2_R0, /* clock=*/ SCL, /* data=*/ SDA, /* reset=*/ U8X8_PIN_NONE);
// ---- Variables temps ----
int hrs, mins, secs;
// ---- Paramètres écran ----
const int LARGEUR_ECRAN = 128;
const int HAUTEUR_ECRAN = 128;
// ---- Offset spécifique SH1107 ----
const int Y_OFFSET = 16; // décalage vertical typique
// ---- Marges en % ----
const float MARGE_HAUT_PCT = 0.10; // 10% haut
const float MARGE_BAS_PCT = 0.10; // 10% bas
const float MARGE_GAUCHE_PCT = 0.10; // 10% gauche
const float MARGE_DROITE_PCT = 0.10; // 10% droite
void setup() {
Serial.begin(115200);
// Connexion WiFi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println(" CONNECTÉ");
// Fuseau CET/CEST (Suisse)
configTzTime("CET-1CEST,M3.5.0/2,M10.5.0/3", ntpServer1, ntpServer2);
// Init OLED
u8g2.begin();
}
void loop() {
setLocalTime();
// ---- Calcul des marges en pixels ----
int margeHaut = (int)(HAUTEUR_ECRAN * MARGE_HAUT_PCT);
int margeBas = (int)(HAUTEUR_ECRAN * MARGE_BAS_PCT);
int margeGauche = (int)(LARGEUR_ECRAN * MARGE_GAUCHE_PCT);
int margeDroite = (int)(LARGEUR_ECRAN * MARGE_DROITE_PCT);
// ---- Dimensions utiles ----
int largeurUtile = LARGEUR_ECRAN - (margeGauche + margeDroite);
int hauteurUtile = HAUTEUR_ECRAN - (margeHaut + margeBas);
// ---- Centre du cercle (avec offset) ----
const int CENTER_X = margeGauche + largeurUtile / 2;
const int CENTER_Y = margeHaut + hauteurUtile / 2 + Y_OFFSET;
// ---- Rayon adapté ----
const int RADIUS = min(largeurUtile, hauteurUtile) / 2 - 5;
// ---- Calcul des angles ----
float secAngle = secs * 6;
float minAngle = mins * 6 + secs * 0.1;
float hrAngle = (hrs % 12) * 30 + mins * 0.5;
// ---- Positions des aiguilles ----
int hrX = CENTER_X + (RADIUS - 20) * cos((hrAngle - 90) * PI / 180);
int hrY = CENTER_Y + (RADIUS - 20) * sin((hrAngle - 90) * PI / 180);
int minX = CENTER_X + (RADIUS - 10) * cos((minAngle - 90) * PI / 180);
int minY = CENTER_Y + (RADIUS - 10) * sin((minAngle - 90) * PI / 180);
int secX = CENTER_X + (RADIUS - 2) * cos((secAngle - 90) * PI / 180);
int secY = CENTER_Y + (RADIUS - 2) * sin((secAngle - 90) * PI / 180);
// ---- Dessin ----
u8g2.clearBuffer();
// Cercle principal
u8g2.drawCircle(CENTER_X, CENTER_Y, RADIUS);
// Chiffres 12-3-6-9
u8g2.setFont(u8g2_font_ncenB08_tr);
u8g2.drawStr(CENTER_X - 6, CENTER_Y - RADIUS - 2, "12");
u8g2.drawStr(CENTER_X + RADIUS - 6, CENTER_Y + 4, "3");
u8g2.drawStr(CENTER_X - 6, CENTER_Y + RADIUS + 12, "6");
u8g2.drawStr(CENTER_X - RADIUS - 12, CENTER_Y + 4, "9");
// Aiguilles
u8g2.drawLine(CENTER_X, CENTER_Y, hrX, hrY);
u8g2.drawLine(CENTER_X, CENTER_Y, minX, minY);
u8g2.drawLine(CENTER_X, CENTER_Y, secX, secY);
u8g2.sendBuffer();
delay(1000);
}
void setLocalTime() {
struct tm timeinfo;
if (!getLocalTime(&timeinfo)) {
Serial.println("Pas encore d'heure disponible");
return;
}
hrs = timeinfo.tm_hour;
mins = timeinfo.tm_min;
secs = timeinfo.tm_sec;
Serial.printf("%02d:%02d:%02d\n", hrs, mins, secs);
}
Analog Clock 128X128 OLED 3[edit]
Si tu utilises SH1107, laisse #define SCREEN_SH1107 actif → offset = 16.
Si tu passes à SSD1327, commente SCREEN_SH1107 et décommente SCREEN_SSD1327 → offset = 0.
#include <Wire.h>
#include <WiFi.h>
#include "time.h"
#include "sntp.h"
#include <U8g2lib.h>
// ---- Sélection écran ----
// Décommente la ligne correspondant à ton écran
#define SCREEN_SH1107
// #define SCREEN_SSD1327
// ---- WiFi ----
const char* ssid = "TonSSID";
const char* password = "TonMotDePasse";
// ---- Serveurs NTP ----
const char* ntpServer1 = "pool.ntp.org";
const char* ntpServer2 = "time.nist.gov";
// ---- OLED Grove 1.12" SH1107 ----
// (Même constructeur pour SSD1327, mais offset différent)
U8G2_SH1107_SEEED_128X128_1_SW_I2C u8g2(U8G2_R0, /* clock=*/ SCL, /* data=*/ SDA, /* reset=*/ U8X8_PIN_NONE);
// ---- Variables temps ----
int hrs, mins, secs;
int day, month, year, wday;
// ---- Tableau des jours (français) ----
const char* jours[] = {"Dimanche","Lundi","Mardi","Mercredi","Jeudi","Vendredi","Samedi"};
// ---- Cadran ----
const int CENTER_X = 64; // centre écran
const int CENTER_Y = 64;
const int RADIUS = 55; // grand rayon pour 128x128
// ---- Correction Y selon écran ----
int Y_OFFSET = 0;
void setup() {
Serial.begin(115200);
// Choix offset selon écran
#ifdef SCREEN_SH1107
Y_OFFSET = 16; // correction typique pour SH1107
#endif
#ifdef SCREEN_SSD1327
Y_OFFSET = 0; // pas besoin de correction
#endif
// Connexion WiFi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println(" CONNECTÉ");
// Fuseau CET/CEST (Suisse) avec gestion automatique du DST
configTzTime("CET-1CEST,M3.5.0/2,M10.5.0/3", ntpServer1, ntpServer2);
// Init OLED
u8g2.begin();
}
void loop() {
setLocalTime();
// ---- Calcul des angles ----
float secAngle = secs * 6;
float minAngle = mins * 6 + secs * 0.1;
float hrAngle = (hrs % 12) * 30 + mins * 0.5;
// ---- Positions des aiguilles ----
int hrX = CENTER_X + (RADIUS - 20) * cos((hrAngle - 90) * PI / 180);
int hrY = CENTER_Y + (RADIUS - 20) * sin((hrAngle - 90) * PI / 180) + Y_OFFSET;
int minX = CENTER_X + (RADIUS - 10) * cos((minAngle - 90) * PI / 180);
int minY = CENTER_Y + (RADIUS - 10) * sin((minAngle - 90) * PI / 180) + Y_OFFSET;
int secX = CENTER_X + (RADIUS - 2) * cos((secAngle - 90) * PI / 180);
int secY = CENTER_Y + (RADIUS - 2) * sin((secAngle - 90) * PI / 180) + Y_OFFSET;
// ---- Dessin ----
u8g2.clearBuffer();
// ---- Affichage jour + date en haut ----
char bufferDate[30];
sprintf(bufferDate, "%s %02d/%02d/%04d", jours[wday], day, month, year);
u8g2.setFont(u8g2_font_6x13_tr);
u8g2.drawStr(CENTER_X - 45, 12 + Y_OFFSET, bufferDate);
// Cadran principal
u8g2.drawCircle(CENTER_X, CENTER_Y + Y_OFFSET, RADIUS);
// Chiffres 12-3-6-9
u8g2.setFont(u8g2_font_ncenB08_tr);
u8g2.drawStr(CENTER_X - 6, CENTER_Y - RADIUS - 5 + Y_OFFSET, "12");
u8g2.drawStr(CENTER_X + RADIUS - 10, CENTER_Y + 4 + Y_OFFSET, "3");
u8g2.drawStr(CENTER_X - 6, CENTER_Y + RADIUS + 12 + Y_OFFSET, "6");
u8g2.drawStr(CENTER_X - RADIUS - 12, CENTER_Y + 4 + Y_OFFSET, "9");
// Aiguilles
u8g2.drawLine(CENTER_X, CENTER_Y + Y_OFFSET, hrX, hrY); // heures
u8g2.drawLine(CENTER_X, CENTER_Y + Y_OFFSET, minX, minY); // minutes
u8g2.drawLine(CENTER_X, CENTER_Y + Y_OFFSET, secX, secY); // secondes
// ---- Affichage digital en bas ----
char bufferTime[10];
sprintf(bufferTime, "%02d:%02d:%02d", hrs, mins, secs);
u8g2.setFont(u8g2_font_ncenB14_tr);
u8g2.drawStr(CENTER_X - 30, 120 + Y_OFFSET, bufferTime);
u8g2.sendBuffer();
delay(1000);
}
void setLocalTime() {
struct tm timeinfo;
if (!getLocalTime(&timeinfo)) {
Serial.println("Pas encore d'heure disponible");
return;
}
hrs = timeinfo.tm_hour;
mins = timeinfo.tm_min;
secs = timeinfo.tm_sec;
day = timeinfo.tm_mday;
month = timeinfo.tm_mon + 1; // tm_mon commence à 0
year = timeinfo.tm_year + 1900;
wday = timeinfo.tm_wday; // jour de la semaine (0 = dimanche)
Serial.printf("%s %02d/%02d/%04d %02d:%02d:%02d\n",
jours[wday], day, month, year, hrs, mins, secs);
}
Analog Clock 128X128 OLED 4[edit]
Au démarrage → attend 10 secondes une commande série.
Si tu tapes t → mode test offset (lignes horizontales).
Si tu tapes h → mode horloge.
Si rien n’est tapé → après 10 secondes → mode horloge par défaut.
#include <Wire.h>
#include <WiFi.h>
#include "time.h"
#include "sntp.h"
#include <U8g2lib.h>
// ---- Sélection écran ----
#define SCREEN_SH1107
// #define SCREEN_SSD1327
// ---- WiFi ----
const char* ssid = "TonSSID";
const char* password = "TonMotDePasse";
// ---- Serveurs NTP ----
const char* ntpServer1 = "pool.ntp.org";
const char* ntpServer2 = "time.nist.gov";
// ---- OLED Grove 1.12" SH1107 ----
U8G2_SH1107_SEEED_128X128_1_SW_I2C u8g2(U8G2_R0, /* clock=*/ SCL, /* data=*/ SDA, /* reset=*/ U8X8_PIN_NONE);
// ---- Variables temps ----
int hrs, mins, secs;
int day, month, year, wday;
// ---- Tableau des jours (français) ----
const char* jours[] = {"Dimanche","Lundi","Mardi","Mercredi","Jeudi","Vendredi","Samedi"};
// ---- Cadran ----
const int CENTER_X = 64;
const int CENTER_Y = 64;
const int RADIUS = 55;
// ---- Correction Y selon écran ----
int Y_OFFSET = 0;
// ---- Mode ----
bool modeTest = false;
void setup() {
Serial.begin(115200);
// Choix offset selon écran
#ifdef SCREEN_SH1107
Y_OFFSET = 16;
#endif
#ifdef SCREEN_SSD1327
Y_OFFSET = 0;
#endif
// Connexion WiFi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println(" CONNECTÉ");
// Fuseau CET/CEST (Suisse)
configTzTime("CET-1CEST,M3.5.0/2,M10.5.0/3", ntpServer1, ntpServer2);
// Init OLED
u8g2.begin();
// ---- Attente commande série pendant 10s ----
Serial.println("Tapez 't' pour mode test offset, 'h' pour horloge. Sinon horloge par défaut après 10s.");
unsigned long start = millis();
while (millis() - start < 10000) {
if (Serial.available()) {
char c = Serial.read();
if (c == 't') {
modeTest = true;
break;
}
if (c == 'h') {
modeTest = false;
break;
}
}
}
}
void loop() {
if (modeTest) {
testOffset();
} else {
afficherHorloge();
}
}
// ---- Fonction horloge ----
void afficherHorloge() {
setLocalTime();
float secAngle = secs * 6;
float minAngle = mins * 6 + secs * 0.1;
float hrAngle = (hrs % 12) * 30 + mins * 0.5;
int hrX = CENTER_X + (RADIUS - 20) * cos((hrAngle - 90) * PI / 180);
int hrY = CENTER_Y + (RADIUS - 20) * sin((hrAngle - 90) * PI / 180) + Y_OFFSET;
int minX = CENTER_X + (RADIUS - 10) * cos((minAngle - 90) * PI / 180);
int minY = CENTER_Y + (RADIUS - 10) * sin((minAngle - 90) * PI / 180) + Y_OFFSET;
int secX = CENTER_X + (RADIUS - 2) * cos((secAngle - 90) * PI / 180);
int secY = CENTER_Y + (RADIUS - 2) * sin((secAngle - 90) * PI / 180) + Y_OFFSET;
u8g2.clearBuffer();
char bufferDate[30];
sprintf(bufferDate, "%s %02d/%02d/%04d", jours[wday], day, month, year);
u8g2.setFont(u8g2_font_6x13_tr);
u8g2.drawStr(CENTER_X - 45, 12 + Y_OFFSET, bufferDate);
u8g2.drawCircle(CENTER_X, CENTER_Y + Y_OFFSET, RADIUS);
u8g2.setFont(u8g2_font_ncenB08_tr);
u8g2.drawStr(CENTER_X - 6, CENTER_Y - RADIUS - 5 + Y_OFFSET, "12");
u8g2.drawStr(CENTER_X + RADIUS - 10, CENTER_Y + 4 + Y_OFFSET, "3");
u8g2.drawStr(CENTER_X - 6, CENTER_Y + RADIUS + 12 + Y_OFFSET, "6");
u8g2.drawStr(CENTER_X - RADIUS - 12, CENTER_Y + 4 + Y_OFFSET, "9");
u8g2.drawLine(CENTER_X, CENTER_Y + Y_OFFSET, hrX, hrY);
u8g2.drawLine(CENTER_X, CENTER_Y + Y_OFFSET, minX, minY);
u8g2.drawLine(CENTER_X, CENTER_Y + Y_OFFSET, secX, secY);
char bufferTime[10];
sprintf(bufferTime, "%02d:%02d:%02d", hrs, mins, secs);
u8g2.setFont(u8g2_font_ncenB14_tr);
u8g2.drawStr(CENTER_X - 30, 120 + Y_OFFSET, bufferTime);
u8g2.sendBuffer();
delay(1000);
}
// ---- Fonction utilitaire test offset ----
void testOffset() {
u8g2.clearBuffer();
u8g2.setFont(u8g2_font_6x13_tr);
u8g2.drawLine(0, CENTER_Y, 128, CENTER_Y); // sans offset
u8g2.drawLine(0, CENTER_Y + Y_OFFSET, 128, CENTER_Y + Y_OFFSET); // avec offset
u8g2.drawStr(10, CENTER_Y - 5, "Sans offset");
u8g2.drawStr(10, CENTER_Y + Y_OFFSET - 5, "Avec offset");
u8g2.sendBuffer();
delay(1000);
}
// ---- Récupération heure locale ----
void setLocalTime() {
struct tm timeinfo;
if (!getLocalTime(&timeinfo)) {
Serial.println("Pas encore d'heure disponible");
return;
}
hrs = timeinfo.tm_hour;
mins = timeinfo.tm_min;
secs = timeinfo.tm_sec;
day = timeinfo.tm_mday;
month = timeinfo.tm_mon + 1;
year = timeinfo.tm_year + 1900;
wday = timeinfo.tm_wday;
Serial.printf("%s %02d/%02d/%04d %02d:%02d:%02d\n",
jours[wday], day, month, year, hrs, mins, secs);
}
Analog Clock 128X128 OLED 5 Tool[edit]
Tu verras deux lignes horizontales sur ton écran :
Une ligne au centre (sans correction).
Une ligne décalée de Y_OFFSET pixels (avec correction).
Les textes « Sans offset » et « Avec offset » t’indiquent quelle ligne correspond à quoi.
Si la ligne corrigée est bien alignée avec ce que tu attends, tu sais que ton Y_OFFSET est correct.
#include <Wire.h>
#include <U8g2lib.h>
// ---- Sélection écran ----
#define SCREEN_SH1107
// #define SCREEN_SSD1327
// ---- OLED Grove 1.12" SH1107 ----
U8G2_SH1107_SEEED_128X128_1_SW_I2C u8g2(U8G2_R0, /* clock=*/ SCL, /* data=*/ SDA, /* reset=*/ U8X8_PIN_NONE);
// ---- Correction Y selon écran ----
int Y_OFFSET = 0;
// ---- Centre écran ----
const int CENTER_X = 64;
const int CENTER_Y = 64;
void setup() {
Serial.begin(115200);
// Choix offset selon écran
#ifdef SCREEN_SH1107
Y_OFFSET = 16; // correction typique pour SH1107
#endif
#ifdef SCREEN_SSD1327
Y_OFFSET = 0; // pas besoin de correction
#endif
// Init OLED
u8g2.begin();
}
void loop() {
u8g2.clearBuffer();
u8g2.setFont(u8g2_font_6x13_tr);
// Ligne horizontale sans offset
u8g2.drawLine(0, CENTER_Y, 128, CENTER_Y);
u8g2.drawStr(10, CENTER_Y - 5, "Sans offset");
// Ligne horizontale avec offset
u8g2.drawLine(0, CENTER_Y + Y_OFFSET, 128, CENTER_Y + Y_OFFSET);
u8g2.drawStr(10, CENTER_Y + Y_OFFSET - 5, "Avec offset");
u8g2.sendBuffer();
delay(1000);
}
Analog Clock 128×64 OLED 6[edit]
Centre déplacé à (64, 32) pour un écran 128×64.
Rayon réduit à 28 pour que le cadran tienne bien.
Positions des textes ajustées (y=10 pour la date, y=58 pour l’heure digitale).
Constructeur U8g2 changé pour SSD1308/SSD1315.
#include <Wire.h>
#include <WiFi.h>
#include "time.h"
#include "sntp.h"
#include <U8g2lib.h>
// ---- WiFi ----
const char* ssid = "TonSSID";
const char* password = "TonMotDePasse";
// ---- Serveurs NTP ----
const char* ntpServer1 = "pool.ntp.org";
const char* ntpServer2 = "time.nist.gov";
// ---- OLED 128x64 SSD1308/SSD1315 ----
// Choisis le constructeur selon ton écran
U8G2_SSD1315_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, /* clock=*/ SCL, /* data=*/ SDA, /* reset=*/ U8X8_PIN_NONE);
// ---- Variables temps ----
int hrs, mins, secs;
int day, month, year, wday;
// ---- Tableau des jours (français) ----
const char* jours[] = {"Dimanche","Lundi","Mardi","Mercredi","Jeudi","Vendredi","Samedi"};
// ---- Cadran ----
const int CENTER_X = 64; // centre écran
const int CENTER_Y = 32; // moitié de 64
const int RADIUS = 28; // adapté à la hauteur
void setup() {
Serial.begin(115200);
// Connexion WiFi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println(" CONNECTÉ");
// Fuseau CET/CEST (Suisse)
configTzTime("CET-1CEST,M3.5.0/2,M10.5.0/3", ntpServer1, ntpServer2);
// Init OLED
u8g2.begin();
}
void loop() {
setLocalTime();
// ---- Calcul des angles ----
float secAngle = secs * 6;
float minAngle = mins * 6 + secs * 0.1;
float hrAngle = (hrs % 12) * 30 + mins * 0.5;
// ---- Positions des aiguilles ----
int hrX = CENTER_X + (RADIUS - 8) * cos((hrAngle - 90) * PI / 180);
int hrY = CENTER_Y + (RADIUS - 8) * sin((hrAngle - 90) * PI / 180);
int minX = CENTER_X + (RADIUS - 4) * cos((minAngle - 90) * PI / 180);
int minY = CENTER_Y + (RADIUS - 4) * sin((minAngle - 90) * PI / 180);
int secX = CENTER_X + (RADIUS - 2) * cos((secAngle - 90) * PI / 180);
int secY = CENTER_Y + (RADIUS - 2) * sin((secAngle - 90) * PI / 180);
// ---- Dessin ----
u8g2.clearBuffer();
// ---- Affichage jour + date en haut ----
char bufferDate[30];
sprintf(bufferDate, "%s %02d/%02d/%04d", jours[wday], day, month, year);
u8g2.setFont(u8g2_font_6x13_tr);
u8g2.drawStr(5, 10, bufferDate);
// Cadran principal
u8g2.drawCircle(CENTER_X, CENTER_Y, RADIUS);
// Chiffres 12-3-6-9
u8g2.setFont(u8g2_font_ncenB08_tr);
u8g2.drawStr(CENTER_X - 6, CENTER_Y - RADIUS - 2, "12");
u8g2.drawStr(CENTER_X + RADIUS - 6, CENTER_Y + 4, "3");
u8g2.drawStr(CENTER_X - 6, CENTER_Y + RADIUS + 10, "6");
u8g2.drawStr(CENTER_X - RADIUS - 10, CENTER_Y + 4, "9");
// Aiguilles
u8g2.drawLine(CENTER_X, CENTER_Y, hrX, hrY);
u8g2.drawLine(CENTER_X, CENTER_Y, minX, minY);
u8g2.drawLine(CENTER_X, CENTER_Y, secX, secY);
// ---- Affichage digital en bas ----
char bufferTime[10];
sprintf(bufferTime, "%02d:%02d:%02d", hrs, mins, secs);
u8g2.setFont(u8g2_font_ncenB14_tr);
u8g2.drawStr(CENTER_X - 30, 58, bufferTime);
u8g2.sendBuffer();
delay(1000);
}
void setLocalTime() {
struct tm timeinfo;
if (!getLocalTime(&timeinfo)) {
Serial.println("Pas encore d'heure disponible");
return;
}
hrs = timeinfo.tm_hour;
mins = timeinfo.tm_min;
secs = timeinfo.tm_sec;
day = timeinfo.tm_mday;
month = timeinfo.tm_mon + 1;
year = timeinfo.tm_year + 1900;
wday = timeinfo.tm_wday;
Serial.printf("%s %02d/%02d/%04d %02d:%02d:%02d\n",
jours[wday], day, month, year, hrs, mins, secs);
}
Analog Clock 128×64 OLED 7[edit]
💻 Code compact (SSD1308/SSD1315, 128×64)
Dans cette version, on supprime le cadran analogique et on affiche uniquement la date en haut et l’heure digitale bien centrée en bas. Cela exploite mieux la petite hauteur de l’écran.
Date + jour en haut (petite police).
Heure digitale en bas, bien grande et centrée (u8g2_font_ncenB24_tr).
Pas de cadran analogique → affichage clair et lisible sur un petit écran.
ceci fonctionne mais le jours est superposé avec l'heure
#include <Wire.h>
#include <WiFi.h>
#include "time.h"
#include "sntp.h"
#include <U8g2lib.h>
// ---- WiFi ----
const char* ssid = "TonSSID";
const char* password = "TonMotDePasse";
// ---- Serveurs NTP ----
const char* ntpServer1 = "pool.ntp.org";
const char* ntpServer2 = "time.nist.gov";
// ---- OLED 128x64 SSD1308/SSD1315 ----
// Choisis le constructeur selon ton écran
U8G2_SSD1315_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, /* clock=*/ SCL, /* data=*/ SDA, /* reset=*/ U8X8_PIN_NONE);
// ---- Variables temps ----
int hrs, mins, secs;
int day, month, year, wday;
// ---- Tableau des jours (français) ----
const char* jours[] = {"Dimanche","Lundi","Mardi","Mercredi","Jeudi","Vendredi","Samedi"};
void setup() {
Serial.begin(115200);
// Connexion WiFi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println(" CONNECTÉ");
// Fuseau CET/CEST (Suisse)
configTzTime("CET-1CEST,M3.5.0/2,M10.5.0/3", ntpServer1, ntpServer2);
// Init OLED
u8g2.begin();
}
void loop() {
setLocalTime();
// ---- Dessin ----
u8g2.clearBuffer();
// Affichage jour + date en haut
char bufferDate[30];
sprintf(bufferDate, "%s %02d/%02d/%04d", jours[wday], day, month, year);
u8g2.setFont(u8g2_font_6x13_tr);
u8g2.drawStr(5, 12, bufferDate);
// Affichage digital centré en bas
char bufferTime[10];
sprintf(bufferTime, "%02d:%02d:%02d", hrs, mins, secs);
u8g2.setFont(u8g2_font_ncenB24_tr); // grande police pour l'heure
u8g2.drawStr(20, 55, bufferTime);
u8g2.sendBuffer();
delay(1000);
}
void setLocalTime() {
struct tm timeinfo;
if (!getLocalTime(&timeinfo)) {
Serial.println("Pas encore d'heure disponible");
return;
}
hrs = timeinfo.tm_hour;
mins = timeinfo.tm_min;
secs = timeinfo.tm_sec;
day = timeinfo.tm_mday;
month = timeinfo.tm_mon + 1;
year = timeinfo.tm_year + 1900;
wday = timeinfo.tm_wday;
Serial.printf("%s %02d/%02d/%04d %02d:%02d:%02d\n",
jours[wday], day, month, year, hrs, mins, secs);
}
Analog Clock 128X64 OLED 7.1 Tool[edit]
Calcul de la hauteur et largeur d'un texte avec une sortie du résultat sur le port série
Police 6x13 -> Hauteur=13 px, Largeur max char=6 px,
Largeur '12:34:56'=48 px, Largeur 'Vendredi, 14/11/2025'=114 px
Police ncenB14 -> Hauteur=14 px, Largeur max char=14 px,
Largeur '12:34:56'=84 px, Largeur 'Vendredi, 14/11/2025'=168 px
Police ncenB18 -> Hauteur=18 px, Largeur max char=18 px,
Largeur '12:34:56'=108 px, Largeur 'Vendredi, 14/11/2025'=216 px
Police ncenB24 -> Hauteur=24 px, Largeur max char=24 px,
Largeur '12:34:56'=144 px, Largeur 'Vendredi, 14/11/2025'=288 px
🖥️ Exemple de code de test (heure + date)
#include <Wire.h>
#include <U8g2lib.h>
//U8G2_SSD1315_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, /* clock=*/ SCL, /* data=*/ SDA, /* reset=*/ U8X8_PIN_NONE);
U8G2_SSD1306_128X64_ALT0_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
void setup() {
Serial.begin(115200);
u8g2.begin();
// Test avec plusieurs polices
testFont(u8g2_font_6x13_tr, "6x13");
testFont(u8g2_font_ncenB14_tr, "ncenB14");
testFont(u8g2_font_ncenB18_tr, "ncenB18");
testFont(u8g2_font_ncenB24_tr, "ncenB24");
}
void loop() {
// rien à faire en boucle
}
void testFont(const uint8_t* font, const char* name) {
u8g2.setFont(font);
// Hauteur et largeur max d’un caractère
int h = u8g2.getMaxCharHeight();
int wChar = u8g2.getMaxCharWidth();
// Largeur d’un exemple d’heure
int wTime = u8g2.getStrWidth("12:34:56");
// Largeur d’un exemple de jour + date
int wDate = u8g2.getStrWidth("Vendredi, 14/11/2025");
Serial.printf("Police %s -> Hauteur=%d px, Largeur max char=%d px, Largeur '12:34:56'=%d px, Largeur 'Vendredi, 14/11/2025'=%d px\n",
name, h, wChar, wTime, wDate);
}
Sorie uniquement sur le moniteur Serial
ESP-ROM:esp32s3-20210327
2025'=201 px
Police ncenB18 -> Hauteur=25 px, Largeur max char=29 px, Largeur '12:34:56'=99 px, Largeur 'Vendredi, 14/11/2025'=265 px
Police ncenB24 -> Hauteur=33 px, Largeur max char=35 px, Largeur '12:34:56'=134 px, Largeur 'Vendredi, 14/11/2025'=341 px
Analog Clock 128X64 OLED 7.2[edit]
Les marges hautes et basses en % de la hauteur de l’écran.
Le choix automatique de la police pour l’heure en fonction de l’espace disponible.
Le centrage horizontal de l’heure.
La date en haut avec une police adaptée.
#include <Wire.h>
#include <WiFi.h>
#include "time.h"
#include "sntp.h"
#include <U8g2lib.h>
// ---- WiFi ----
const char* ssid = "TonSSID";
const char* password = "TonMotDePasse";
// ---- Serveurs NTP ----
const char* ntpServer1 = "pool.ntp.org";
const char* ntpServer2 = "time.nist.gov";
// ---- OLED 128x64 SSD1308/SSD1315 ----
U8G2_SSD1315_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, /* clock=*/ SCL, /* data=*/ //SDA, /* reset=*/ U8X8_PIN_NONE);
U8G2_SSD1306_128X64_ALT0_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
// ---- Variables temps ----
int hrs, mins, secs;
int day, month, year, wday;
// ---- Tableau des jours (français) ----
const char* jours[] = {"Dimanche","Lundi","Mardi","Mercredi","Jeudi","Vendredi","Samedi"};
// ---- Paramètres écran ----
const int LARGEUR_ECRAN = 128;
const int HAUTEUR_ECRAN = 64;
// ---- Marges en % ----
const float MARGE_HAUT_PCT = 0.10; // 10%
const float MARGE_BAS_PCT = 0.10; // 10%
// ---- Polices disponibles pour l'heure ----
const uint8_t* FONT_SMALL = u8g2_font_ncenB14_tr; // ~14 px
const uint8_t* FONT_MEDIUM = u8g2_font_ncenB18_tr; // ~18 px
const uint8_t* FONT_LARGE = u8g2_font_ncenB24_tr; // ~24 px
void setup() {
Serial.begin(115200);
// Connexion WiFi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println(" CONNECTÉ");
// Fuseau CET/CEST (Suisse)
configTzTime("CET-1CEST,M3.5.0/2,M10.5.0/3", ntpServer1, ntpServer2);
// Init OLED
u8g2.begin();
}
void loop() {
setLocalTime();
u8g2.clearBuffer();
// Calcul des marges en pixels
int margeHaut = (int)(HAUTEUR_ECRAN * MARGE_HAUT_PCT);
int margeBas = (int)(HAUTEUR_ECRAN * MARGE_BAS_PCT);
int hauteurUtile = HAUTEUR_ECRAN - (margeHaut + margeBas);
// ---- Affichage jour + date en haut ----
char bufferDate[30];
sprintf(bufferDate, "%s %02d/%02d/%04d", jours[wday], day, month, year);
u8g2.setFont(u8g2_font_6x13_tr);
u8g2.drawStr(5, margeHaut + 12, bufferDate);
// ---- Choix automatique de la police pour l'heure ----
const uint8_t* fontChoisie;
if (hauteurUtile >= 24) {
fontChoisie = FONT_LARGE; // assez de place pour 24 px
} else if (hauteurUtile >= 18) {
fontChoisie = FONT_MEDIUM; // assez de place pour 18 px
} else {
fontChoisie = FONT_SMALL; // sinon police plus petite
}
// ---- Affichage digital centré en bas ----
char bufferTime[10];
sprintf(bufferTime, "%02d:%02d:%02d", hrs, mins, secs);
u8g2.setFont(fontChoisie);
// Centrage horizontal
int largeur = u8g2.getStrWidth(bufferTime);
int x = (LARGEUR_ECRAN - largeur) / 2;
// Ligne de base juste avant la marge basse
int y = HAUTEUR_ECRAN - margeBas;
u8g2.drawStr(x, y, bufferTime);
u8g2.sendBuffer();
delay(1000);
}
void setLocalTime() {
struct tm timeinfo;
if (!getLocalTime(&timeinfo)) {
Serial.println("Pas encore d'heure disponible");
return;
}
hrs = timeinfo.tm_hour;
mins = timeinfo.tm_min;
secs = timeinfo.tm_sec;
day = timeinfo.tm_mday;
month = timeinfo.tm_mon + 1;
year = timeinfo.tm_year + 1900;
wday = timeinfo.tm_wday;
Serial.printf("%s %02d/%02d/%04d %02d:%02d:%02d\n",
jours[wday], day, month, year, hrs, mins, secs);
}
Analog Clock 128X64 OLED 8[edit]
💻 Code : seulement le cadran analogique
fonctionne mais illisible on dirait 2 ovales ! mais on peut voir les aguilles
Un cadran analogique avec les chiffres 12‑3‑6‑9.
Trois aiguilles (heures, minutes, secondes).
Pas de date ni d’heure digitale → affichage épuré.
#include <Wire.h>
#include <WiFi.h>
#include "time.h"
#include "sntp.h"
#include <U8g2lib.h>
// ---- WiFi ----
const char* ssid = "TonSSID";
const char* password = "TonMotDePasse";
// ---- Serveurs NTP ----
const char* ntpServer1 = "pool.ntp.org";
const char* ntpServer2 = "time.nist.gov";
// ---- OLED 128x64 SSD1308/SSD1315 ----
U8G2_SSD1315_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, /* clock=*/ SCL, /* data=*/ SDA, /* reset=*/ U8X8_PIN_NONE);
// ---- Variables temps ----
int hrs, mins, secs;
// ---- Cadran ----
const int CENTER_X = 64; // centre écran
const int CENTER_Y = 32; // moitié de 64
const int RADIUS = 28; // adapté à la hauteur
void setup() {
Serial.begin(115200);
// Connexion WiFi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println(" CONNECTÉ");
// Fuseau CET/CEST (Suisse)
configTzTime("CET-1CEST,M3.5.0/2,M10.5.0/3", ntpServer1, ntpServer2);
// Init OLED
u8g2.begin();
}
void loop() {
setLocalTime();
// ---- Calcul des angles ----
float secAngle = secs * 6;
float minAngle = mins * 6 + secs * 0.1;
float hrAngle = (hrs % 12) * 30 + mins * 0.5;
// ---- Positions des aiguilles ----
int hrX = CENTER_X + (RADIUS - 8) * cos((hrAngle - 90) * PI / 180);
int hrY = CENTER_Y + (RADIUS - 8) * sin((hrAngle - 90) * PI / 180);
int minX = CENTER_X + (RADIUS - 4) * cos((minAngle - 90) * PI / 180);
int minY = CENTER_Y + (RADIUS - 4) * sin((minAngle - 90) * PI / 180);
int secX = CENTER_X + (RADIUS - 2) * cos((secAngle - 90) * PI / 180);
int secY = CENTER_Y + (RADIUS - 2) * sin((secAngle - 90) * PI / 180);
// ---- Dessin ----
u8g2.clearBuffer();
// Cadran principal
u8g2.drawCircle(CENTER_X, CENTER_Y, RADIUS);
// Chiffres 12-3-6-9
u8g2.setFont(u8g2_font_ncenB08_tr);
u8g2.drawStr(CENTER_X - 6, CENTER_Y - RADIUS - 2, "12");
u8g2.drawStr(CENTER_X + RADIUS - 6, CENTER_Y + 4, "3");
u8g2.drawStr(CENTER_X - 6, CENTER_Y + RADIUS + 10, "6");
u8g2.drawStr(CENTER_X - RADIUS - 10, CENTER_Y + 4, "9");
// Aiguilles
u8g2.drawLine(CENTER_X, CENTER_Y, hrX, hrY); // heures
u8g2.drawLine(CENTER_X, CENTER_Y, minX, minY); // minutes
u8g2.drawLine(CENTER_X, CENTER_Y, secX, secY); // secondes
u8g2.sendBuffer();
delay(1000);
}
void setLocalTime() {
struct tm timeinfo;
if (!getLocalTime(&timeinfo)) {
Serial.println("Pas encore d'heure disponible");
return;
}
hrs = timeinfo.tm_hour;
mins = timeinfo.tm_min;
secs = timeinfo.tm_sec;
Serial.printf("%02d:%02d:%02d\n", hrs, mins, secs);
}