Tachymètre HO
Posté : 01 juin 2026, 20:17
Je commence un nouveau projet: un affichage de la vitesse d'un train façon radar routier.
Matériel: un Arduino Nano, un écran OLED de 0,91 pouces et deux capteur TTP223, un peu de fil électrique et quelques grammes de PLA soit un investissement d'environ 3,50€ en comptant large.
J'ai fait ça sous forme d'un panneau d'affichage à intégrer au décor:
Les connexions se font sur une plaque à bande qui s'enfiche sur les broches de l'Arduino
L'Arduino a une petite boite avec des oreilles de fixations
Et j'ai fait aussi une boite qui intègre l'Arduino et l'écran si on veut mettre ça à côté du réseau mais attention à la longueur du câblage de l'écran qui est en I2C ...
Pour le code, j'avais promis sur YouTube quelque chose de simple et j'ai fait une version 1 minimaliste qui tient en quelques lignes de code. Elle ne fait la mesure que dans un seul sens. Elle affiche la mesure pendant un temps définit, j'ai mis 5 secondes mais on peut mettre plus.
Inconvénient: ça utilise Delay, fonction bloquante si bien qu'aucune mesure ne peut se faire pendant que l'écran affiche quelque chose.
Il y a aussi une fonction de scrolling dans la procédure afficherPret() pour éviter de brûler l'écran, mais au final, j'ai supprimé cet affichage qui ne sert à rien et l'écran reste noir entre deux mesures. Il suffit de réactiver les lignes si on veut avoir un message défilant pour animer l'écran.
Et j'ai fait aussi une version 2 plus complète qui fait la mesure dans les deux sens, utilise une fonction de timer non bloquante si bien qu'une deuxième mesure meut se faire immédiatement si deux trains sont très près.
Je mettrai tous les fichiers un peu plus tard quand ils seront bien finalisés ainsi que le code complet quand j'aurai terminé car il y a encore quelques bricoles a finaliser.
Mais globalement, c'est quelque chose de très simple et vite fait.
Une petite vidéo du premier essai: Et le code de la Version 1:
Code : Tout sélectionner
/* =========================================
* Tachymètre pour train à l'échelle HO
* V1.00 (c) Ramasoft 2026
* Mesure dans un seul sens de circulation
* =========================================
* Matériel :
* - Arduino Nano
* - Écran OLED 0,91" 128x32 (SSD1306) en I2C
* - 2 capteurs tactiles TTP223 (utilisés comme détecteurs de passage)
*
* Câblage :
* - Capteur 1 (S1) → D2 fil bleu
* - Capteur 2 (S2) → D3 fil vert
* - OLED SDA → A4 fil blanc
* - OLED SCL → A5 fil jaune
* - OLED VCC → 5V
* - OLED GND → GND
*
* Note sur les TTP223 :
* Le TTP223 doit avoir ses plots A et B non shuntés = congiguration d'origine
* pour sortir un état HAUT (HIGH) quand il détecte quelque chose et fonctionner en mode impulsion
*
* Distance entre capteurs : 30 cm (réelle = 30 / 87 m à l'échelle 1)
*
* Bibliothèques requises (à charger par le Gestionnaire de bibliothèques Arduino) :
* - Adafruit SSD1306
* - Adafruit GFX Library
*/
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
// Configuration de l'écran OLED
#define SCREEN_WIDTH 128 // Largeur de l'écran en pixels
#define SCREEN_HEIGHT 32 // Hauteur de l'écran (Modifier à 64 si votre écran est un 128x64)
#define OLED_RESET -1 // // Pas de broche RESET dédiée = partagée avec le Nano.
#define SCREEN_ADDRESS 0x3C /// Adresse I2C typique des écrans OLED
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// Configuration des capteurs
const int pinCapteur1 = 2; // Premier capteur (Entrée de la zone)
const int pinCapteur2 = 3; // Second capteur (Sortie de la zone)
// Constantes pour le calcul (Échelle HO = 1/87)
const float distanceEntreCapteurs = 0.30; // Distance en mètres (30 cm)
const float echelle = 87.0;
// Variables de temps (volatile car utilisées dans les interruptions)
volatile unsigned long tempsDepart = 0;
volatile unsigned long tempsFin = 0;
volatile boolean trainEnCours = false; // Indique qu'un train est entré dans la zone
volatile boolean mesureDispo = false; // Indique que la mesure est prête
void setup() {
//Configurer la LED interne (broche 13 sur le Nano) en sortie
pinMode(LED_BUILTIN, OUTPUT);
// Initialisation de l'écran
// Si l'écran ne répond pas, on entre dans une boucle infinie de clignotement
// de la LED rouge de l'Arduino
if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
while(true) {
digitalWrite(LED_BUILTIN, HIGH); // Allume la LED
delay(200); // Attend 200 ms
digitalWrite(LED_BUILTIN, LOW); // Éteint la LED
delay(200); // Attend 200 ms (clignotement rapide d'erreur)
}
}
// Si l'écran fonctionne, le code continue normalement ici...
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(15, 10);
display.println(" Tachymetre HO");
display.println("(c) Ramasoft 2026");
display.display();
delay(2000);
// Configuration des broches des capteurs (TTP223 sort un signal HIGH quand touché/activé)
pinMode(pinCapteur1, INPUT);
pinMode(pinCapteur2, INPUT);
// Attachement des interruptions sur front montant (RISING)
attachInterrupt(digitalPinToInterrupt(pinCapteur1), capteur1Declenche, RISING);
attachInterrupt(digitalPinToInterrupt(pinCapteur2), capteur2Declenche, RISING);
afficherPret();
}
void loop() {
// Si une mesure est prête à être calculée
if (mesureDispo) {
// Calcul du temps mis par le train en secondes
float tempsMis = (tempsFin - tempsDepart) / 1000.0;
// Sécurité si le calcul donne un temps aberrant
if (tempsMis > 0.05) {
// Calcul de la vitesse réelle en m/s
float vitesseReelle = distanceEntreCapteurs / tempsMis;
// Conversion en km/h à l'échelle HO
float vitesseHO = vitesseReelle * echelle * 3.6;
// Affichage du résultat sur l'OLED
display.stopscroll();
display.clearDisplay();
display.setTextSize(1);
display.setCursor(0, 0);
display.print("Vitesse HO:");
display.setTextSize(2);
display.setCursor(0, 14); // Ajuster la position Y si écran 64px
display.print(vitesseHO, 1); // 1 chiffre après la virgule
display.print(" km/h");
display.display();
// Laisser le résultat affiché pendant 5 secondes avant de se remettre en attente
delay(5000);
}
// Réinitialisation pour le prochain train
trainEnCours = false;
mesureDispo = false;
display.clearDisplay();
afficherPret();
}
}
// Fonction d'interruption pour le premier capteur
void capteur1Declenche() {
if (!trainEnCours) {
tempsDepart = millis();
trainEnCours = true; // Le train est entré dans la zone
}
}
// Fonction d'interruption pour le second capteur
void capteur2Declenche() {
if (trainEnCours && !mesureDispo) {
tempsFin = millis();
mesureDispo = true; // La mesure est complète
}
}
void afficherPret() {
display.clearDisplay();
//display.setTextSize(2);
//display.setCursor(0, 10); // Centré verticalement pour un écran 32px
//display.print("En Attente");
display.display();
// Active le défilement horizontal vers la droite
// Paramètres : (première page, dernière page) -> 0 et 0X0F couvre tout l'écran
//display.startscrollright(0x00,0x0F);
}Je mettrai un peu plus d'explications demain.

