Page 1 sur 1

Panneau d'affichgage de gare

Posté : 24 juil. 2026, 22:26
par ramasoft
J'ai commencé ce projet et je vous mets juste une photo pour avoir une idée.
C'est le premier jet et il y a pas mal de choses à revoir mais ces petits écrans de 1,14 pouces OLED sont formidables.
https://fr.aliexpress.com/item/1005010444597930.html
J'avoue avoir un peu galéré pour la mise en page de mon affichage car ce truc est tout nouveau pour moi, mais je commence à comprendre le fonctionnement...

Donc c'est un écran IPS en RGB. Il est en 3,3V et donc ne convient pas directement avec un Arduino qui travaille en 5V
Il se connecte en SPI, donc un peu plus de fils que l'I2C, mais avec les bibliothèques, ça reste transparent. Merci aux auteurs de ces bibliothèques car ça enlève pas mal boulot, s'il fallait gérer ça en direct.
Pour la petite histoire, du temps du MS-DOS, il fallait tout gérer dans le logiciel, y compris la souris et avec une interface graphique un peu chiadée il y avait souvent plus de boulot que pour "la cuisine" qui se faisait derrière. Heureusement que Windows, Visual Basic et Visual C++ sont arrivés ...

Là, j'ai pris un ESP32 en Dev Module = avec carte complète et port USB
Pareil, c'est un monde que je découvre et j'ai un peu galéré avec la bibliothèque TFT_eSPI.h qui a un bug mais j'expliquerai ça plus tard.

J'ai un module horloge RTC pour afficher l'heure et l'affichage change aussi évidement en fonction de l'heure.
Là, comme il est 22h11, il affiche le prochain train, c'est à dire celui de 7h15 demain matin car il n'y a pas de circulation la nuit sauf fret...

Pour l'intégration, j'ai vu ce que Didier en impression 3Davait fait et je vais m'en inspirer car le connecteur à l'arrière m'embête. Donc soit je plie les pattes mais ça va faire un peu épais quand même soit je fais un pied avec le connecteur comme Didier avait fait.
IMG_20260724_221050.jpg

J'en mettrai un peu plus demain.

:a_suivre:

Re: Panneau d'affichgage de gare

Posté : 24 juil. 2026, 22:28
par bunny94
:PetitPoucejpg:

Re: Panneau d'affichgage de gare

Posté : 25 juil. 2026, 00:49
par clbesson
:cooooool: :PetitPoucejpg: :PetitPoucejpg:

Re: Panneau d'affichgage de gare

Posté : 25 juil. 2026, 05:57
par NANAR
:bienv: :PetitPoucejpg:

Re: Panneau d'affichgage de gare

Posté : 25 juil. 2026, 07:36
par Bud_fr
ramasoft a écrit : 24 juil. 2026, 22:26 .....

Pour l'intégration, j'ai vu ce que Didier en impression 3Davait fait et je vais m'en inspirer car le connecteur à l'arrière m'embête. Donc soit je plie les pattes mais ça va faire un peu épais quand même soit je fais un pied avec le connecteur comme Didier avait fait.
...
Pour mémoire et pour ceux qui n'ont pas suivi, voici comment j'ai fait:
pied afficheur quai.jpg
Mon problème était de faire un pied assez gros pour faire passer 4 fils, qui soit imprimable, mais pas trop gros quand même...
connection afficheur quai.jpg
Le connecteur mâle étant intégré derrière l'afficheur, j'ai inséré le connecteur femelle (barrette sécable) dans le pied.

:a_suivre:

Re: Panneau d'affichgage de gare

Posté : 25 juil. 2026, 07:50
par Amigorl
:bienv:

Projet très intéressant d'une part par le résultat qui s'avère être au top mais aussi pour l'intégration de la bibliothèque de gestion de cet écran RGB.
Jusqu'à présent je ne savais utiliser que les écrans monochromes 0.96 pouces.

Ce sera très instructif et à ajouter à la boîte à outils Arduino/Esp32.

:PetitPoucejpg:

Re: Panneau d'affichgage de gare

Posté : 25 juil. 2026, 09:06
par likiki
Voilà encore un sujet a suivre avec le plus grand intérêt.


:PetitPoucejpg:

Re: Panneau d'affichgage de gare

Posté : 25 juil. 2026, 09:34
par C2Vues-BricoTrain
:bienv: :bienv:

Superbe réalisation en coopération collégiale. :cooooool:

:PetitPoucejpg: :PetitPoucejpg: :PetitPoucejpg:

Re: Panneau d'affichgage de gare

Posté : 25 juil. 2026, 10:24
par ramasoft
Pour le pied, mon écran a un connecteur à 8 broches, donc ça fait large.
Je vais certainement faire un pied cylindrique, plus facile à poser et qui fait aussi un coude à 90° en haut, comme Didier, mais qui s'évase en rectangle pour accueillir le connecteur 8 broches.
L'écran sera embroché dessus.
Il y a aussi le wifi que j'aimerai explorer avec par exemple une interface smartphone pour refaire la mise à l'heure (été/hiver), régler la luminosité et pouvoir utiliser l'écran pour afficher autre chose. (je ne sais pas encore quoi...)
La définition est de 135 x 240 et je l'ai piloté avec une fréquence de rafraichissement de 27MHz (je crois que c'est le maxi) donc on peut envisager pas mal d'applications graphiques, au delà du simple texte, comme des bitmap animés.
Il faut que je me documente plus sur ces écrans.
C'est dommage que je n'en ai acheté qu'un seul à l'époque ...

Re: Panneau d'affichgage de gare

Posté : 25 juil. 2026, 10:51
par philippe017
:bienv: :bienv: :cooooool:

Re: Panneau d'affichgage de gare

Posté : 25 juil. 2026, 14:52
par ramasoft
On a la liste des trains qui doivent partir après l'heure affichée. Avec 6 lignes
Le dernier train de la journée étant à 20h25, le 6e est le premier du matin suivant à 7h15.
IMG_20260725_163155.jpg
Pour le montage je n'aime pas les breadboard et les Dupont et Durand, je préfère souder 😜
Donc j'ai fait un shield qui s'enfiche sur l'ESP et un sticker qui rappelle les couleurs des fils que je vais utiliser, et ainsi aucun risque d'erreur de branchement ni de faux contacts.
Sticker ESP32.docx
Et le shield servira dans le montage final que je ferai sur un support en impression 3D qui regroupera tous les éléments.

IMG_20260725_135216.jpg
Là, c'est le module RTC qui donne l'heure et qui est relié en I2C
https://fr.aliexpress.com/item/1005010120637681.html
IMG_20260725_135220.jpg

L’ESP est un 32D CH9102 38 pins Dev Modele avec interface USB
https://fr.aliexpress.com/item/1005006984793820.html

L’écran est un OLED IPS 1,14 pouces 135x240
https://fr.aliexpress.com/item/1005010444597930.html

Il y a 8 fils à connecter.
Attention il s'alimente en 3,3V et ses broches fonctionnent avec des niveaux logiques eux aussi en 3,3V donc si vous voulez le brancher sur un Arduino, qui envoie du 5V sur ses broches, il faudra utiliser un adaptateur de niveaux bidirectionnel comme celui-ci
https://fr.aliexpress.com/item/1005009377821005.html

VCC : sur le 3.3V de l'ESP32 (ne pas alimenter en 5V).
GND : sur GND (masse).
SCL / SCLK / SCK : brancher sur le GPIO d'horloge SPI matériel, par exemple GPIO 18 (VSPI SCK).
SDA / MOSI / SDI : brancher sur le GPIO de données SPI matériel, par exemple GPIO 23 (VSPI MOSI).
RES / RST : brancher sur un GPIO de votre choix, par exemple GPIO 04.
DC / AO : brancher sur un GPIO de votre choix, par exemple GPIO 02 (Data/Command).
CS : brancher sur un GPIO aussi quelconque GPIO 5
BLK / BL / LED rétroéclairage: peut être relié soit directement au 3.3V et on aura un rétroéclairage fixe , soit sur une broche pour le piloter en PWM par la bibliothèque.
J'ai choisi les broches pour qu'elles soient toutes du même côté.

La bibliothèque que j’ai prise est TFT_eSPI (Bodmer). Il faut l’installer dans l’IDE et il faut aussi reconfigurer son fichier User_Setup car les affectations de broches ne se font pas dans le code comme avec un Arduino mais dans ce fichier qui se situe dans le répertoire d’installation de la bibliothèque.
Il faut remplacer le fichier d’origine par celui-ci :

Code : Tout sélectionner

// ============================================================
// User_Setup.h pour écran ST7789 135x240 (1,14") - ESP32
// ============================================================
// A COPIER dans : <dossier_libraries>/TFT_eSPI/User_Setup.h
// (remplacer le contenu existant par un copier/coller)
// ============================================================

#define ST7789_DRIVER

#define TFT_WIDTH  135
#define TFT_HEIGHT 240

// --- Câblage SPI matériel ESP32 (VSPI) ---
#define TFT_MOSI 23   // SDA de l'écran
#define TFT_SCLK 18   // SCL de l'écran
#define TFT_CS   5   // CS
#define TFT_DC   2   // DC (Data/Command)
#define TFT_RST  4   // RES
#define TFT_BL   15   // BLK (rétroéclairage) - optionnel si câblé direct au 3.3V

// Décalage nécessaire sur beaucoup de modules 135x240
// (souvent basés sur un contrôleur pensé pour 240x240,
//  avec un offset de 40 px en Y et 52 px en X)
#define TFT_RGB_ORDER TFT_BGR   // à tester : TFT_RGB si couleurs inversées
#define TFT_BACKLIGHT_ON HIGH   // allume le rétroéclairage 

#define LOAD_GLCD
#define LOAD_FONT2
#define LOAD_FONT4
#define LOAD_FONT6
#define LOAD_FONT7
#define LOAD_FONT8
#define LOAD_GFXFF
#define SMOOTH_FONT

#define SPI_FREQUENCY  27000000
#define SPI_READ_FREQUENCY 20000000
Attention la définition des broches est celle que j’ai utilisé mais si vous voulez prendre d’autres broches (on peut mettre ce qu’on veut… ou presque) il faudra modifier la section
// --- Câblage SPI matériel ESP32 (VSPI) ---
Les broches 18 et 23 ne sont pas modifiables (enfin pas directement)

J’ai mis la fréquence au maxi = 27MHz mais on peut la descendre en cas d’anomalie d’affichage liée à un câble trop long. (50 cm environ, au-delà les problèmes peuvent commencer)

Petite vidéo d'essai qui montre le changement de l'affichage quand l'heure de départ du premier train est passée :
On voit que l'écran est très réactif et l'affichage est instantané.
Essai_Ecran_1.mp4
Au niveau du code, c’est une version 1, donc minimaliste et je vais certainement rajouter des fonctionnalités au fur et à mesure.
J'avais ajouté la gestion du rétroéclairage car ça ne marchait pas au début, mais c'est simplement que j'avais oublié la ligne "#define TFT_BACKLIGHT_ON HIGH " dans le User_Setup.h. (ce que j'avais pris pour un bug dans la bibliothèque et qui n'était qu'une erreur de configuration de ma part ...)


Il y a 4 colonnes, un affichage de l’heure et la liste des trains est mise à jour en fonction de l’heure.
On a 19 caractères pour les destinations : attention ce ne sont pas des polices proportionnelles donc les majuscules tiennent plus de place que les minuscules.
Le rafraichissement ne se fait que sur l’horloge pour éviter les clignotements.
Il n’y a rien d’extraordinaire et si vous voulez une explication sur une partie précise du code il suffit de demander.

Le code de cette toute première version qui peut servir de base pour essayer:
Panneau_Gare_V1_11.ino

Code : Tout sélectionner

/*
  ============================================================
  Panneau d'affichage de gare HO
  Version 1.11 © Ramasoft Juillet 2026
  - Affichage 4 colonnes : ARRIV / DEP / nom / V, horloge centrée
  - Bandeau d'en-tête et espacement des lignes calculés dynamiquement
  - Ligne séparatrice retracée à chaque rafraîchissement de l'horloge
  ESP32 + écran ST7789 135x240 (SPI) + RTC DS3231 (I2C)
  ============================================================

  Bibliothèques nécessaires :
   - TFT_eSPI          (Bodmer)  -> configurer User_Setup.h (fichier fourni à part)
   - RTClib            (Adafruit)
   - Wire              (incluse avec l'ESP32)

  Câblage :
   Écran ST7789        ESP32    couleur fil
   ------------------------------------------
   VCC        -> 3.3V           rouge
   GND        -> GND            noir
   SCL        -> GPIO18 (SCK)   jaune
   SDA        -> GPIO23 (MOSI)  blanc
   RES        -> GPIO04         bleu
   DC         -> GPIO02         gris
   CS         -> GPIO05         vert
   BLK        -> GPIO15         orange

   RTC DS3231         ESP32
   ---------------------------
   VCC        -> 3.3V           rouge (ou 5V selon module, la plupart acceptent les deux)
   GND        -> GND            noir
   SDA        -> GPIO21         blanc
   SCL        -> GPIO22         jaune
  ============================================================
*/

#include <SPI.h>
#include <TFT_eSPI.h>
#include <Wire.h>
#include <RTClib.h>

TFT_eSPI tft = TFT_eSPI();
RTC_DS3231 rtc;

// Broches I2C explicites (RTC DS3231)
// Ce sont déjà les valeurs par défaut de l'ESP32, mais les préciser
// ici rend le câblage lisible directement dans le sketch.
#define RTC_SDA 21
#define RTC_SCL 22

// Broche de rétroéclairage, pilotée explicitement
#define PIN_BACKLIGHT 15

// ---------- Structure d'un train ----------
struct Train {
  uint8_t heure;          // heure de départ de Châteauroux (0-23) 
  uint8_t minute;         // minute de départ (0-59) 
  const char* nom;        // destination affichée en colonne DEPART
  const char* arrivee;    // heure d'arrivée affichée en colonne ARRIVEE (texte libre, ex "7h12")
  const char* quai;       // voie affichée en colonne V
};

// ---------- Table d'horaires ----------
// A classer par heure croissante, ça simplifie le filtrage ...
Train horaires[] = {
  {  7, 15, "PARIS Austerlitz",     "7h12",  "1" },
  {  7, 42, "TOULOUSE Matabiau",    "7h39",  "3" },
  {  8,  5, "LIMOGES Benedictins",  "8h02",  "3" },
  {  8, 30, "PARIS Capitole",       "8h27",  "2" },
  {  9, 20, "TOULOUSE Capitole",    "9h17",  "1" },
  { 10, 10, "BRIVE Omnibus",        "10h07", "5" },
  { 10, 45, "LIMOGES Benedictins",  "10h42", "4" },
  { 11, 15, "VAL de L'INDRE",       "*****", "6" },
  { 12,  0, "ORLEANS",              "11h57", "2" },
  { 13, 30, "PARIS Austerlitz",     "13h27", "1" },
  { 14, 10, "MONTAUBAN Omnibus",    "14h07", "4" },
  { 14, 35, "VIERZON (NANTES)",     "14h32", "3" },
  { 16, 20, "LIMOGES Benedictins",  "16h17", "5" },
  { 17, 45, "TOULOUSE Matabiau",    "17h42", "3" },
  { 18, 30, "PARIS Austerlitz",     "18h27", "1" },
  { 19,  0, "ORLEANS",              "18h27", "2" },
  { 20, 15, "PARIS Capitole",       "20h12", "1" },
  { 20, 25, "TOULOUSE Capitole",    "20h22", "3" },
};
const int NB_TRAINS = sizeof(horaires) / sizeof(horaires[0]);

// Nombre de lignes de trains affichées simultanément à l'écran
const int LIGNES_AFFICHEES = 6;

// Nombre max de caractères affichés pour le nom de destination
// (au-delà, le nom est tronqué - à ajuster selon le rendu réel à l'écran)
const int NOM_MAX_CAR = 19;

// ---------- Couleurs (RGB565) ----------
#define COL_FOND       TFT_BLACK
#define COL_ENTETE_BG  TFT_NAVY
#define COL_ENTETE_TXT TFT_YELLOW
#define COL_TXT        TFT_WHITE
#define COL_DEPART     TFT_GREENYELLOW  // colonne DEPART (heure de départ locale)
#define COL_ARRIVEE    TFT_ORANGE   // colonne ARRIVEE dans une couleur distincte
#define COL_QUAI       TFT_CYAN
#define COL_HORLOGE    TFT_YELLOW

// ---------- Emplacements des colonnes (à ajuster si ça déborde chez toi) ----------
const int X_ARRIVEE  = 1;   // colonne ARRIVEE (heure d'arrivée)
const int X_NOM      = 46;  // colonne destination (juste après l'heure de départ)
const int X_DEPART   = 180; // colonne DEPART (heure de départ, ex "7h15")
const int X_VOIE     = 236; // colonne V (voie/quai), alignée à droite

const int HAUTEUR_MARGE_BASSE = 4; // marge sous le texte de l'horloge avant la ligne séparatrice

// Ces 3 valeurs ne sont plus des constantes figées : elles sont calculées
// dans setup(), une fois que tft.fontHeight() est utilisable, pour que le
// bandeau d'en-tête et l'espacement des lignes s'adaptent automatiquement
// à la vraie hauteur de la police de l'horloge (plus de débordement possible).
int HAUTEUR_ENTETE;     // hauteur de la bande d'en-tête
int Y_DEBUT_LISTE;      // position Y de la première ligne de train
int HAUTEUR_LIGNE;      // hauteur allouée à chaque ligne de train

const int Y_LABELS        = 10;  // position verticale des libellés d'en-tête
const int Y_HORLOGE_CENTRE = 3; // position verticale de l'horloge (police plus grande)

unsigned long derniereMAJ = 0;
const unsigned long INTERVALLE_MAJ = 1000; // vérifier/rafraîchir l'horloge 1x/seconde

int dernierIndexTrain = -1;   // mémorise le 1er train affiché, pour ne redessiner
                               // la liste que si elle change réellement

void setup() {
  Serial.begin(115200);

  // --- Rétroéclairage piloté explicitement ---
  pinMode(PIN_BACKLIGHT, OUTPUT);
  digitalWrite(PIN_BACKLIGHT, HIGH);

  // --- Init écran ---
  tft.init();
  tft.setRotation(1);       // 1 = paysage (240x135). Essayer 3 si à l'envers => 270°
  tft.fillScreen(COL_FOND);

  // --- Calcul dynamique des hauteurs, à partir de la vraie hauteur de police ---
  int hPoliceHorloge = tft.fontHeight(4);
  HAUTEUR_ENTETE = Y_HORLOGE_CENTRE + hPoliceHorloge + HAUTEUR_MARGE_BASSE;
  Y_DEBUT_LISTE  = HAUTEUR_ENTETE + 3;
  HAUTEUR_LIGNE  = (tft.height() - Y_DEBUT_LISTE) / LIGNES_AFFICHEES;

  // --- Init RTC ---
  Wire.begin(RTC_SDA, RTC_SCL);   // explicite : SDA=GPIO21, SCL=GPIO22

  if (!rtc.begin()) {
    tft.setTextColor(TFT_RED, COL_FOND);
    tft.setTextSize(1);
    tft.drawString("Erreur RTC DS3231 !", 5, 5, 2);
    Serial.println("RTC DS3231 non détecté");
    while (1) delay(1000);
  }

  if (rtc.lostPower()) {
    Serial.println("RTC réinitialisée à l'heure de compilation");
    // Décommenter la ligne suivante UNE FOIS pour régler l'heure
    // (à l'heure de compilation du sketch), puis recommenter
    // l'heure est sauvegardée par la pile
    // rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  }

  // --- Dessin initial : tout l'écran une seule fois ---
  dessinerEnTeteStatique();
  DateTime maintenant = rtc.now();
  dessinerHorloge(maintenant);
  dernierIndexTrain = trouverPremierTrainFutur(maintenant);
  dessinerListeTrains(dernierIndexTrain);
}

void loop() {
  if (millis() - derniereMAJ >= INTERVALLE_MAJ) {
    derniereMAJ = millis();
    DateTime maintenant = rtc.now();

    // --- L'horloge est la seule chose repeinte chaque seconde ---
    dessinerHorloge(maintenant);

    // --- La liste des trains n'est repeinte QUE si elle change réellement ---
    int idx = trouverPremierTrainFutur(maintenant);
    if (idx != dernierIndexTrain) {
      dernierIndexTrain = idx;
      dessinerListeTrains(idx);
    }
  }
}

// ============================================================
// En-tête STATIQUE : libellés de colonnes + ligne séparatrice
// Dessiné une seule fois dans setup(), jamais réécrit ensuite
// ============================================================
void dessinerEnTeteStatique() {
  tft.fillRect(0, 0, tft.width(), HAUTEUR_ENTETE, COL_ENTETE_BG);
  tft.setTextColor(COL_ENTETE_TXT, COL_ENTETE_BG);

  tft.drawString("Arrivee", X_ARRIVEE, Y_LABELS, 2);
  tft.drawString("Depart", X_DEPART, Y_LABELS, 2);
  tft.drawRightString("V", X_VOIE, Y_LABELS, 2);

  // Ligne séparatrice horizontale, dessinée une seule fois
  tft.drawFastHLine(0, HAUTEUR_ENTETE, tft.width(), TFT_DARKGREY);
}

// ============================================================
// Horloge : SEULE zone repeinte chaque seconde (pas tout l'écran)
// HH:MM en grand (police 4), secondes en petit à côté (police 2,
// même taille que les colonnes DEPART/ARRIV)
// ============================================================
void dessinerHorloge(DateTime &maintenant) {
  char bufHeureMin[6];
  sprintf(bufHeureMin, "%02dh%02d", maintenant.hour(), maintenant.minute());

  char bufSec[4];
  sprintf(bufSec, "%02d", maintenant.second());

  // Zone élargie maintenant que ARRIV a été déplacé à x=180
  const int xZoneDebut = 56;
  const int xZoneFin   = 176;
  tft.fillRect(xZoneDebut, 0, xZoneFin - xZoneDebut, HAUTEUR_ENTETE, COL_ENTETE_BG);

  tft.setTextColor(COL_HORLOGE, COL_ENTETE_BG);

  // Largeurs réelles des deux textes, pour bien centrer l'ensemble
  int largeurGrand  = tft.textWidth(bufHeureMin, 4);
  int largeurPetit  = tft.textWidth(bufSec, 2);
  const int espace  = 5;
  int largeurTotale = largeurGrand + espace + largeurPetit;

  int xDebut = (xZoneDebut + xZoneFin) / 2 - largeurTotale / 2;

  // Heure:minute en grand
  tft.drawString(bufHeureMin, xDebut, Y_HORLOGE_CENTRE, 4);

  // Secondes en petit, alignées vers le bas du grand texte (effet "exposant")
  tft.drawString(bufSec, xDebut + largeurGrand + espace, Y_HORLOGE_CENTRE + 5, 2);

  // On retrace systématiquement la ligne séparatrice : par sécurité, au cas
  // où le texte de l'horloge déborderait légèrement de la zone repeinte
  tft.drawFastHLine(0, HAUTEUR_ENTETE, tft.width(), TFT_DARKGREY);
}

// ============================================================
// Liste des prochains trains - dessinée seulement quand elle change
// ============================================================
void dessinerListeTrains(int indexDepart) {
  // Efface uniquement la zone de la liste (pas l'en-tête)
  tft.fillRect(0, Y_DEBUT_LISTE, tft.width(), tft.height() - Y_DEBUT_LISTE, COL_FOND);

  for (int i = 0; i < LIGNES_AFFICHEES; i++) {
    int idx = (indexDepart + i) % NB_TRAINS;
    int y = Y_DEBUT_LISTE + i * HAUTEUR_LIGNE;

    Train &t = horaires[idx];

    // --- Colonne DEPART (heure de départ locale, ex "7h15") ---
    char bufDepart[6];
    sprintf(bufDepart, "%dh%02d", t.heure, t.minute);
    tft.setTextColor(COL_DEPART, COL_FOND);
    tft.drawString(bufDepart, X_DEPART, y, 2);

    // --- Colonne nom de destination (tronqué si trop long) ---
    tft.setTextColor(COL_TXT, COL_FOND);
    afficherTronque(t.nom, X_NOM, y, NOM_MAX_CAR, 2);

    // --- Colonne ARRIVEE (couleur distincte) ---
    tft.setTextColor(COL_ARRIVEE, COL_FOND);
    tft.drawString(t.arrivee, X_ARRIVEE, y, 2);

    // --- Colonne V (voie/quai) ---
    tft.setTextColor(COL_QUAI, COL_FOND);
    tft.drawRightString(t.quai, X_VOIE, y, 2);
  }
}

// ---------- Affiche une chaîne tronquée à maxLen caractères ----------
void afficherTronque(const char* texte, int x, int y, int maxLen, uint8_t font) {
  char buf[32];
  int len = strlen(texte);
  if (len > maxLen) len = maxLen;
  memcpy(buf, texte, len);
  buf[len] = '\0';
  tft.drawString(buf, x, y, font);
}

// ============================================================
// Trouve l'index du premier train dont l'heure de départ
// est >= à l'heure actuelle. Si aucun (fin de journée),
// reboucle sur le premier train du lendemain.
// ============================================================
int trouverPremierTrainFutur(DateTime &maintenant) {
  int minutesActuelles = maintenant.hour() * 60 + maintenant.minute();

  for (int i = 0; i < NB_TRAINS; i++) {
    int minutesTrain = horaires[i].heure * 60 + horaires[i].minute;
    if (minutesTrain >= minutesActuelles) {
      return i;
    }
  }
  // Tous les trains du jour sont passés -> on reboucle sur le premier
  return 0;
}

Reste à faire les supports en impression 3D.


:a_suivre:

Re: Panneau d'affichgage de gare

Posté : 25 juil. 2026, 16:28
par ramasoft
J'ai aussi demandé à Mr Claude (le mari de la bien connue Mme Claude ... :mdr3: ) s'il y avait des limitations en longueur en SPI:


Limitations SPI.jpg

Et si on doit dépasser les 30 cm:
1. Réduire la fréquence SPI dans User_Setup.h : #define SPI_FREQUENCY 10000000 // 10 MHz au lieu de 27
Ça réduit le risque d'erreurs (pixels qui clignotent, artefacts, écran qui "part en vrille") au prix d'un rafraîchissement un peu plus lent — totalement invisible pour un panneau d'affichage qui ne bouge pas vite.
2. Torsader les paires critiques : SCLK avec un fil de GND à côté, MOSI avec un autre fil de GND à côté. Ça limite les diaphonies et le rayonnement parasite.
3. Un seul GND commun bien dimensionné, pas un fil fin de 30 cm qui fait aussi tout le retour de l'alimentation.
4. RES et DC sont moins critiques en vitesse (ce sont des signaux "statiques" la plupart du temps) — on peut les allonger sans trop de souci même si SCLK/MOSI sont limités.
5. CS peut aussi être un peu plus tolérant, mais autant le garder dans le même faisceau que SCLK/MOSI par cohérence.

Re: Panneau d'affichgage de gare

Posté : 25 juil. 2026, 16:49
par clbesson
:bienv: :bienv:

Superbe réalisation une fois de plus Patrick !
Hâte de voir le résultat intégré à ton réseau ... Encore un projet intéressant à rajouter à une longue liste en attente :lunette: :tirechap:

Re: Panneau d'affichgage de gare

Posté : 25 juil. 2026, 16:53
par patrice_b
:bienv: :bienv:

Ces petits écran sont magnifiques, très net, je trouve.

Merci Patrick.

:merciiii:

Re: Panneau d'affichgage de gare

Posté : 25 juil. 2026, 16:56
par ramasoft
Oui, ils sont très jolis et avec une bonne définition.
La bibliothèque gère aussi les écrans tactiles et ça pourrait faire une bonne base pour se faire un TCO "High Tech" ... avec un écran plus grand évidemment.

Re: Panneau d'affichgage de gare

Posté : 25 juil. 2026, 17:05
par likiki
J'adore, je pense que je vais m'en faire un ou deux pour mettre sur le quais de ma gare.

J'ai des nano a plus savoir quoi en faire et j'ai les écrans. Y a plus qu'a.

:siffle:

Re: Panneau d'affichgage de gare

Posté : 25 juil. 2026, 17:09
par ramasoft
Oui, c'est aussi faisable avec un Nano.
Là, c'est surtout pour voir comment fonctionnent les ESP32 et aussi parce que je pourrais le faire évoluer en exploitant le wifi
Reste à trouver un écran qui permette suffisamment de texte mais ça devrait être jouable avec un 0,96 pouces
J'en ai d'ailleurs deux que j'utiliserai peut être en complément sur d'autres quai.