Difference between revisions of "Analog Clock OLED"
| Line 627: | Line 627: | ||
delay(1000); | delay(1000); | ||
| + | } | ||
| + | </pre> | ||
| + | |||
| + | === Analog Clock OLED 6 === | ||
| + | |||
| + | Centre déplacé à (64, 32) pour un écran 128×64.<br> | ||
| + | Rayon réduit à 28 pour que le cadran tienne bien.<br> | ||
| + | Positions des textes ajustées (y=10 pour la date, y=58 pour l’heure digitale).<br> | ||
| + | Constructeur U8g2 changé pour SSD1308/SSD1315.<br> | ||
| + | |||
| + | <pre> | ||
| + | #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); | ||
} | } | ||
</pre> | </pre> | ||
Revision as of 00:05, 14 November 2025
Contents
Analog Clock OLED 1
#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 OLED 2
Ajout de const int Y_OFFSET = 16;
Application de + Y_OFFSET sur toutes les coordonnées Y (drawStr, drawLine, drawCircle, calcul des aiguilles).
#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 OLED 3
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 OLED 4
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 OLED 5
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 OLED 6
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);
}