Difference between revisions of "Analog Clock OLED"

From
Jump to: navigation, search
(Analog Clock OLED 5)
(Analog Clock 128X128 OLED 5)
Line 573: Line 573:
 
</pre>
 
</pre>
  
=== Analog Clock 128X128 OLED 5 ===
+
=== Analog Clock 128X128 OLED 5 Tool ===
  
 
Tu verras deux lignes horizontales sur ton écran :<br>
 
Tu verras deux lignes horizontales sur ton écran :<br>

Revision as of 23:11, 14 November 2025

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).

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 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 128X128 OLED 5 Tool

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

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

💻 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

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);

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);
}

Analog Clock 128X64 OLED 7.2

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);

// ---- 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

💻 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);
}