Une débutante dans le décor - Ep6 - Quelques automatismes (Arduino Nano)

Salut,

Ce tutoriel va présenter un système existant pour réaliser des automatismes en mode “lego” basé sur la plateforme Arduino Nano.

A la fin du tutoriel, nous aurons un montage simple pour détecter la présence d’un matériel roulant sur un rail contact et déclencher des automatismes en conséquence. Pour 11 €. Et une vidéo de démonstration.

Il est la brique de base que je vais utiliser ensuite pour mes automatismes, à commencer par celui de la fosse d’inspection.

Objectif : pas de fer à souder, pas de câblage compliqué, pas de résistance/condo/… à rajouter et bien sur un prix mini mini. Si tu sais brancher un M84, tu sais utiliser un Arduino à la sauce Julaye :wink: !

14 mai 2021 : simplification de certains tutoriels pour détecter le STOP + correction d’un branchement
17 mai 2021 : nouvelle version de Tuto6 avec une carte opto isolée type DST-1R4P-N ou DST-1R8P-N

Table des matières

  1. Tuto01 à Tuto05 : les bases (ci-après)
  2. Annexe A et B : schéma pour Tuto01 à Tuto05 et matériel nécessaire
  3. Add-on Tuto6 : Etat de la Voie : libre, occupée, STOP
  4. Add-on Tuto7 : un afficheur 4 x 7 segments optionnel
  5. Annexe C - Les fichiers téléchargeables des tutoriels 01 à 07
  6. Variante avec carte opto isolée type DST-1R4P-N ou DST-1R8P-N

Dans les épisodes précédents :

  1. Le carton plume
  2. Noyer la voie C
  3. Kitbashing d’un pont tournant
  4. Kitbashing d’une fosse d’inspection
  5. Un garde-corps en laiton

6.1 Le contexte

Pour mes réalisations, j’ai besoin d’automatismes qui sont basés sur des fonctionnalités de base :

  • détecter la présence d’un matériel roulant
  • détecter une ou plusieurs entrées
  • actionner une ou plusieurs sorties
  • utiliser des timers
  • combiner tout ça

J’ai donné par exemple le cahier des charges des lumières de la fosse d’inspection ici.

J’ai été déçu par une petite carte électronique YYC-2S sensée faire (une partie) du job, qui m’a quand même couté 11.69 euros, et qui s’est avérée incapable de détecter proprement la présence ou l’absence de la locomotive sur la fosse. il aurait fallut ajouter des trucs devant et derrière pour filtrer le signal, pour combiner deux entrées …

Une autre option est d’utiliser des logiciels comme iTrain pour réaliser ces automatismes. C’est une belle option mais je ne suis pas convaincue par cette approche. Si l’ordinateur est indisponible, plus d’automatisme.

Je vous rappelle que dans mon approche je souhaite pouvoir tout piloter depuis une simple MS2.

En discutant avec un ami, il me dit : il te faut un automate.

Mais je vais y rajouter une contrainte : je veux que tout soit simple et se connecte facilement comme lorsque l’on branche un M84.

Il me faut une solution “LEGO” et pas cher !

6.2 Cahier des charges

Il me faut un automate avec :

  • des entrées digitales et analogiques
  • des sorties relais
  • une entrée pour détecter l’occupation d’un rail
  • des timers
  • facile à programmer
  • facile à cabler
  • et pas cher

6.3 Solution retenue

Mon choix s’est fixé sur l’Arduino Nano que j’ai pris expressément chez AZ-Delivery. Le packaging est au top, la documentation à télécharger (en anglais) est limpide et le kit tombe littéralement en marche.

Les fonctions de base sont remplis par (de gauche à droite sur la photo) :

  • une carte entrée analogique 0-25V pour interfacer le rail contact : Capteur de tension DC0-25V pour Arduino chez Stemedu
  • une carte Arduino Nano : AZDelivery Mini Nano Card V3.0 Atmega328 CH340 version à puce soudée avec câble USB
  • une carte sortie relais (1 relais, 2 relais, 4 relais ou 8 relais selon les besoins) : AZDelivery 5 x 1 Canal KF-301 Module relais 5V Low-Level-Trigger

Chez AZ-Delivery, la carte Arduino est vendu par lot de 3 et les cartes relais par lot de 5. La carte analogique de Stemedu est vendue par lot de 5.

En prix de revient unitaire, il faut compter 1.70 € la sortie relais, 6.50 € le Nano et 2.40 € la carte analogique ! soit un total de 10.60 €, moins cher que la petite carte électronique YYC-2S !

Comme je ne veux rien souder et avoir un câblage simplifié, j’ai commandé un lot de câble avec des connecteurs mâle-male, femelle-mâle et femelle-femelle : 40 de chaque pour 10 € le lots de 140, soit 8 centimes la connexion.

Les câbles sont nappés mais chaque brin se détache très facilement. Et nous avons des couleurs comme le rouge, le brun, le jaune, le bleu et le noir, couleurs très utiles dans notre contexte :slight_smile:

Notre montage final du tutoriel utilise 7 brins ce qui fait un montage à 11.16 €, toujours moins cher que la petite carte électronique YYC-2S !

6.4 Montage pour le tutoriel

Pour réaliser ce tutoriel, il vous faut trois coupons voie C type 24188, celui du milieu étant transformé en rail à contact (avec un fil bleu et des isolations 74030), les deux autres étant alimentés par une Digibox et sa MS2 :

On peut faire l’équivalent avec de la voie M ou de la voie K bien évidemment, le principal étant d’isoler un rail du coupon central et d’y connecter un fil bleu qui nous servira de signal de présence/absence d’un matériel roulant.

6.5 Installation de l’Arduino Nano

Il faut ouvrir la documentation fournie avec l’Arduino Nano (à télécharger sur le site de AZ-Delivery) et l’installation est expliquée :

  • télécharger l’environnement de développement Arduino IDE à l’adresse suivante : https://www.arduino.cc/en/software (Windows, Linux et Mac sont supportés),

  • installer le logiciel et le lancer

  • choisir la carte “Arduino Nano”,

  • brancher le cable USB entre l’Arduino Nano et l’ordinateur, la led de mise sous tension verte doit s’allumer,

  • choisir le port USB qui est apparu (la mention sera différente en fonction de votre environnement),

  • choisir le processeur “ATmega328P (Old Bootloader)”

  • choisir l’application d’exemple “Blink” et la lancer en clichant sur le bouton → qui se trouve dans la fenêtre “Blink”

L’écran “Blink” doit afficher un message de réussite :

  • Et l’Arduino Nano doit faire clignoter sa led rouge correspondant à une sortie digitale 13

6.6 Tuto01

Notre premier tutoriel va consister à ouvrir et fermer notre relais à une fréquence d’une seconde.

Le branchement est archi simple :

  • L’arduino Nano est alimenté par son cable USB.
  • Connecter la pin GND de l’Arduino Nano avec la pin GND de la carte relais (cable femelle-femelle noir)
  • Connecter la pin +5V de l’Arduino Nano avec la pin VCC de la carte relais (cable femelle-femelle rouge)

A ce stade, la carte relais est alimentée.

  • Connecter la sortie D3 de l’Arduino avec l’entrée IN de la carte relais (cable femelle-femelle jaune)

Le fait de passer la sortie D3 à 1 (HIGH) commute le relais COMMON - NO et à 0 (LOW) commute le relais COMMON - NC. Tout simplement.

La carte relais étant munis d’une led rouge (carte alimentée) et d’une led verte (allumé si relais COMMON-NC, éteinte sinon), il va être facile de vérifier si notre programme fonctionne.

On fait menu Fichier → Nouveau et on copie le programme ci-après.

Le programme est simple et auto explicatif avec les commentaires que j’ai inséré :

// Tuto01 
// Exemple pour le forum 3rails / Julie Dumortier / Licence GPL
// 
// ouvre puis ferme un relais à la fréquence de 1 seconde
//
// Retrouvez ce tutoriel sur le lien : https://forum.3rails.fr/t/une-debutante-dans-le-decor-ep6-quelques-automatismes-arduino-nano/18361

// défini la broche (pin) utilisée pour commander le relais : D3
int relaisPin = 3;

// code executé une seule fois au démarrage du module (ou après un reset)
void setup() {

  // programme la sortie digitale D3 en sortie
  // le In du relais est connecté à cette sortie D3
  pinMode(relaisPin, OUTPUT);

}

// code executé en permanence (une boucle)
void loop() {
  
   // relais COMMON - NO (led verte éteinte)
  digitalWrite(relaisPin,HIGH);
  
  // attends une seconde (unité de temps : millisecondes)
  delay(1000);
  
  // relais COMMON - NC (led verte allumée)
  digitalWrite(relaisPin,LOW);

  // attends une seconde
  delay(1000);

}

On télécharge et on exécute le programme toujours avec la flèche → qui se trouve dans cette fenêtre Tuto01. Le relais doit s’ouvrir et se fermer une fois par seconde …

A ce stade, si vous voulez avoir une meilleure compréhension des commandes que j’ai utilisé pour ce petit exemple, vous pouvez allez sur l’aide en ligne :

6.7 Tuto02

Le second tutoriel va introduire un outil important pour la mise au point de vos petits programmes : la console, une fenêtre dans votre Arduino IDE qui peut afficher des messages en provenance de la carte via la connexion USB.

Vous pouvez ouvrir cette console par le menu Outils → Moniteur série. Elle ressemble à ça :

Il faut choisir une vitesse de communication - je préconise 57600 bauds - et il faudra parametrer la même vitesse dans la carte Arduino. Ce paramétrage se fait dans la fonction setup() qui porte bien son nom.

Là aussi le programme est assez simple et commenté, on écrit un X ou un O au rythme du relais qui se ferme et qui s’ouvre :

// Tuto02 
// Exemple pour le forum 3rails / Julie Dumortier / Licence GPL
// 
// ouvre puis ferme un relais à la fréquence de 1 seconde
// affiche O ou X dans la console
//
// Retrouvez ce tutoriel sur le lien : https://forum.3rails.fr/t/une-debutante-dans-le-decor-ep6-quelques-automatismes-arduino-nano/18361

// défini la broche (pin) utilisée pour commander le relais : D3
int relaisPin = 3;

// code executé une seule fois au démarrage du module (ou après un reset)
void setup() {

  // programme la sortie digitale D3 en sortie
  // le In du relais est connecté à cette sortie D3
  pinMode(relaisPin, OUTPUT);

  // ouvre le port série (console de l'outil) avec la vitesse 57600 bauds
  // attention que le paramètre sur la console soit bien 57600 !
  Serial.begin(57600);

}

// code executé en permanence (une boucle)
void loop() {
  
  // relais COMMON - NO (led verte éteinte)
  digitalWrite(relaisPin,HIGH);

  // envoie X sur la console
  Serial.println("X");
  
  // attends une seconde (unité de temps : millisecondes)
  delay(1000);
  
  // relais COMMON - NC (led verte allumée)
  digitalWrite(relaisPin,LOW);

  // envoie O sur la console
  Serial.println("O");

  // attends une seconde
  delay(1000);

}

Et le contenu de la console :

6.8 Tuto03

Au lieu d’afficher des X et des O, nous allons lire une valeur analogique sur l’entrée A3 et nous allons l’afficher au rythme d’un affichage par seconde. Et nous continuons à ouvrir et fermer le relais sur le même rythme.

Bien évidemment, la valeur affichée est totalement aléatoire puisque l’entrée analogique est en l’air, connectée à rien du tout.

Le programme se complique un tout petit peu avec la fonction de lecture analogique. Rien qui ne soit incompréhensible, les commentaires et les noms des fonctions parlent d’eux-même :

// Tuto03 
// Exemple pour le forum 3rails / Julie Dumortier / Licence GPL
// 
// ouvre puis ferme un relais à la fréquence de 1 seconde
// affiche la valeur analogique lue sur une entrée
//
// Retrouvez ce tutoriel sur le lien : https://forum.3rails.fr/t/une-debutante-dans-le-decor-ep6-quelques-automatismes-arduino-nano/18361

// défini la broche (pin) utilisée pour commander le relais : D3
int relaisPin = 3;

// défini la broche (pin) utilisée pour lire la valeur analogique : A3
int anaPin = 3;

// variable pour stocker la valeur lue
int val = 0;

// code executé une seule fois au démarrage du module (ou après un reset)
void setup() {

  // programme la sortie digitale D3 en sortie
  // le In du relais est connecté à cette sortie D3
  pinMode(relaisPin, OUTPUT);

  // ouvre le port série (console de l'outil) avec la vitesse 57600 bauds
  // attention que le paramètre sur la console soit bien 57600 !
  Serial.begin(57600);

}

int lectureAna()
{
  return analogRead(anaPin);
}

// code executé en permanence (une boucle)
void loop() {
  
  // relais COMMON - NO (led verte éteinte)
  digitalWrite(relaisPin,HIGH);

  // lis la valeur analogique
  val = lectureAna();

  // envoie la valeur sur la console
  Serial.println(val);
  
  // attends une seconde (unité de temps : millisecondes)
  delay(1000);
  
  // relais COMMON - NC (led verte allumée)
  digitalWrite(relaisPin,LOW);

  // lis la valeur analogique
  val = lectureAna();

  // envoie la valeur sur la console
  Serial.println(val);

  // attends une seconde
  delay(1000);

}

Et le contenu de la console (avec des valeurs aléatoires) :

6.9 Tuto04

Il est temps d’aller lire ce qui se passe sur notre rail de contact, sur notre fil bleu :slight_smile:

Nous allons brancher la carte analogique 0-25V de la manière suivante :

  • sortie S connectée à l’entrée A3 de l’Arduino (cable femelle-femelle jaune)

  • entrée + : non utilisée

  • entrée - connectée à l’autre sortie GND de l’Arduino (cable femelle-femelle noir)

  • entrée VCC - connectée au cable B de la voie (cable femelle-mâle rouge)

  • entrée GND - connectée au cable bleu du rail de contact

Le programme va consister à lire la valeur analogique en provenance du rail de contact (fil bleu), l’afficher, et en fonction d’un seuil de commander le relais.

// Tuto04 
// Exemple pour le forum 3rails / Julie Dumortier / Licence GPL
// 
// affiche la valeur analogique lue sur une entrée
// si elle est supérieur à un seuil : relais C - NO
// sinon relais C - NC
//
// Retrouvez ce tutoriel sur le lien : https://forum.3rails.fr/t/une-debutante-dans-le-decor-ep6-quelques-automatismes-arduino-nano/18361

// défini la broche (pin) utilisée pour commander le relais : D3
int relaisPin = 3;

// défini la broche (pin) utilisée pour lire la valeur analogique : A3
int anaPin = 3;

// variable pour stocker la valeur lue
int val = 0;

// variable pour stocker le seuil
int seuil = 500;

// code executé une seule fois au démarrage du module (ou après un reset)
void setup() {

  // programme la sortie digitale D3 en sortie
  // le In du relais est connecté à cette sortie D3
  pinMode(relaisPin, OUTPUT);

  // ouvre le port série (console de l'outil) avec la vitesse 57600 bauds
  // attention que le paramètre sur la console soit bien 57600 !
  Serial.begin(57600);

  // relais COMMON - NC (led verte allumée)
  digitalWrite(relaisPin,LOW);

}

int lectureAna()
{
  return analogRead(anaPin);
}

// code executé en permanence (une boucle)
void loop() {
  
  // lis la valeur analogique
  val = lectureAna();

  // envoie la valeur sur la console
  Serial.println(val);

  if (val > seuil) {
      // relais COMMON - NO (led verte éteinte)
      digitalWrite(relaisPin,HIGH);

  } else {
      // relais COMMON - NC (led verte allumée)
      digitalWrite(relaisPin,LOW);

  }
  
  // attends 100 ms
  delay(100);

}

L’exécution du programme permet de voir le comportement des valeurs en fonction de la position du wagon (attention, wagon avec des roues conductrices, je me suis faite avoir avec un wagon de @vincentlj avec un axe plastique :upside_down_face:) :

Désolée pour le bruit, Ryco déménage des trucs puis s’intéresse au relais qui claque …

On remarque avec cette vidéo que le rail inoccupé renvoi une valeur proche de 0. la rail occupé retourne une valeur qui correspond au fil rouge (courant de traction) mais parfois des 0 : il s’agit des shunts du signal numérique. Il va falloir filtrer !

6.10 Tuto05

Nous allons reprendre l’exemple précédent et réaliser une fonction qui nous dit si la voie est occupée ou libre. Pour ce faire, nous allons réaliser un filtre rudimentaire.

Le programme est commenté :

// Tuto05
// Exemple pour le forum 3rails / Julie Dumortier / Licence GPL
// 
// affiche la valeur analogique lue sur une entrée
// si elle est supérieur à un seuil : relais C - NC
// sinon relais C - NO si l'absence de contact est confirmé (filtre)
//
// Retrouvez ce tutoriel sur le lien : https://forum.3rails.fr/t/une-debutante-dans-le-decor-ep6-quelques-automatismes-arduino-nano/18361

// défini la broche (pin) utilisée pour commander le relais : D3
int relaisPin = 13;

// défini la broche (pin) utilisée pour lire la valeur analogique : A3
int anaPin = 3;

// variable pour stocker la valeur lue
int val = 0;

// variable pour stocker le seuil de déclenchement
int seuil = 384;

// variable pour compter les déclenchements
int nbFiltre = 16;

// on va filter le signal bas pendant 192 ms pour décider que la voie est libre
int msFiltre = 192;

// code executé une seule fois au démarrage du module (ou après un reset)
void setup() {

  // programme la sortie digitale D3 en sortie
  // le In du relais est connecté à cette sortie D3
  pinMode(relaisPin, OUTPUT);

  pinMode(anaPin,INPUT_PULLUP);

  // ouvre le port série (console de l'outil) avec la vitesse 57600 bauds
  // attention que le paramètre sur la console soit bien 57600 !
  Serial.begin(57600);

  // relais COMMON - NC (led verte allumée)
  digitalWrite(relaisPin,LOW);

}

// retourne 1 si la voie est libre
int voieLibre()
{
  int n = msFiltre;
  int c = 0;
  int v = 0;

  // tant que le signal est bas on continue
  while (n>0) {
    v = analogRead(anaPin);
    if (v>seuil) {
      c = c + 1;
    }

    if (c>nbFiltre) {
      // la voie est encore occupée

      // attends la fin du compteur
      delay(n);
      
      // et retourne l'état d'occupation
      return 0;
    }

    // attends 1 ms
    delay(1);

    // et boucle
    n = n - 1;
  }

  // il est resté bas --> la voie est libre
  return 1;
}

// code executé en permanence (une boucle)
void loop() {

  if (voieLibre()) {
      // relais COMMON - NC (led verte allumée)
      digitalWrite(relaisPin,LOW);
      Serial.println("voie libre");
  } else {
      // relais COMMON - NO (led verte éteinte)
      digitalWrite(relaisPin,HIGH);   
      Serial.println("voie occupée");
 }
 
  // attends 100 ms pour refaire un test
  delay(100);

}

La nouvelle vidéo montre la fonctionnalité mise en oeuvre :

Bilan : nous avons un montage simple à 11.16 € et un petit programme qui permet de détecter l’occupation d’une voie, pour allumer par exemple les lumières de notre fosse. Et ajouter tous les automatismes que nous voulons (lumière forcée, délais d’allumage, délais d’extinction, mode veille …). Nous aborderons cet automatisme complet dans la partie automatisme de l’épisode 4 à suivre very soon !

6.11 THAT’S ALL FOLKS !

Ce tutoriel est maintenant terminé. Vous pouvez explorer d’autres capacité de votre carte avec les tutoriels du site Arduino :

A vous de jouer !


Retrouvez tous les épisodes de la débutante en clickant ici !

2 « J'aime »

Annexe A - Le schéma logique / connection des éléments mis en oeuvre

Annexe B - Le matériel du tutoriel

Arduino Nano (AZ-Delivery) (lot de 3) :

Carte relais (AZ-Delivery) (lot de 5) :

Carte analogique capteur de tension 0-25V (Stemedu) (lot de 5) :

Connecteurs (AZ-Delivery) (lot de 3 x 40) :

Enjoy !

2 « J'aime »

Super intéressant ton tuto, j’ai des arduino uno, mais c’est pareil, je vais tester cela.
Jean-Luc

1 « J'aime »

Bonsoir Jean-Luc,

Oui ça doit marcher car qui peut le plus peut le moins. Si tu a déjà des sorties relais et un Arduino Uno, il te faut juste acheter la carte analogique 0-25 DC pour lire la voie.

Tu trouves ce composant sur Amazon :

https://www.amazon.fr/gp/product/B07L81QJ75/

En effet, je n’ai pas de capteur de tension et souvent les vendeurs d’Amazone ne livrent pas en Suisse, mais je vais en trouver sur Ebay ou Conrad.

Add-on Tuto06

La nuit a été courte, j’ai codé l’automatisme pour la fosse d’inspection. Je l’ai testé et ça marche au delà de mes espérances. Le temps de l’intégrer et je vous montre les branchements et le programme.

Lors de cette session de codage, j’ai mis au point la fonction qui retourne l’état de la voie sur le rail de contact, fonction déjà présentée dans une forme préliminaire dans le Tuto05.

J’ai amélioré le paramétrage et le réglage du filtre et j’ai introduit une fonctionnalité expérimentale qui permet de détecter si la voie est alimentée ou en STOP.

L’état de STOP est envoyé sur la console mais allume aussi la led interne rouge qui correspond sur l’Arduino Nano à la sortie D13 dite BUILTIN_LED.

24 mai 2021 : amélioration du filtre et suppression de la nécessité d’un second capteur de tension 0-25V, ce qui réduit la facture et simplifie le programme et les réglages.

==> On reprendra strictement le branchement du Tuto05

Ce nouveau programme va permettre de vérifier si un signal numérique est présent sur la voie.

// Tuto06
// Exemple pour le forum 3rails / Julie Dumortier / Licence GPL
// 
// extrait du programme Fosse v1.5
//   afficher l'état de la voie sur le rail contact : STOP, libre ou occupé
//    sortie D3 -> relais (LOW = voie libre, HIGH = voie occupée)
//    sortie D13 -> led interne (LOW = voie alimentée, HIGH = voie STOP) EXPERIMENTAL
//
// Retrouvez ce tutoriel sur le lien : https://forum.3rails.fr/t/une-debutante-dans-le-decor-ep6-quelques-automatismes-arduino-nano/18361
// version 14 mai 2021 : l'état de la voie est prise directement sur le signal

// défini la broche (pin) utilisée pour commander le relais : D3
int relaisPin = 3;

// défini la broche (pin) utilisée pour lire la valeur analogique du rail de contact : A3
int Pin_etatRail = 3;

// variable pour stocker le seuil de déclenchement
int seuilSignal = 384;

// variable pour compter les déclenchements
int nbFiltre = 16;

// on va filter le signal bas pendant 192 ms pour décider que la voie est libre
int msFiltre = 192;

// EtatVoie
// retourne l'état de la voie
//  voie_Occupee la voie est occupée
//  voie_Libre   la voie est libre
//  voie_STOP    la voie est en STOP (CSx ou MSII)
//
// la voie est déclarée occupée si au moins une valeur acquise sur A3 est supérieur au seuilSignal
// la voie est déclarée vide si aucune valeur acquise sur A3 n'est supérieure au seuilSignal
// dans ce cas, la voie est déclarée STOP si aucune détection de signalnumérique sur A2

#define voie_Occupee  0
#define voie_Libre    1
#define voie_STOP     99

int EtatVoie()
{
  int n = msFiltre;
  
  int vr = 0;
  int vt = 0;
  int c = 0;

  // flag pour savoir si on a recu un signal de traction
  boolean traction = false;
  
  // tant que le signal est bas on continue
  while (n>0) {
    // lit les deux entrées : rail contact et rail normal
    vr = analogRead(Pin_etatRail);
    vt = vr; //analogRead(Pin_etatTraction);

    //Serial.print(vr);
    //Serial.print(" ");

    if (vt>1) {
      traction = true;
    }
    
    if (vr>seuilSignal) {
      c = c + 1;
    }

    if (c>nbFiltre) {
      // la voie est encore occupée

      // attends la fin du compteur
      delay(n);
      
      // et retourne l'état d'occupation
      return voie_Occupee;
    }

    // attends 1 ms
    delay(1);

    // et boucle
    n = n - 1;
  }

  // on a eu un signal de traction
  if (traction) {

    // le rail contact est resté bas --> la voie est libre
    Serial.println("voie libre");

    return voie_Libre;
  }

  // pas de traction
  return voie_STOP;
} 

// code executé une seule fois au démarrage du module (ou après un reset)
void setup() {

  // programme la sortie digitale D3 en sortie
  // le In du relais est connecté à cette sortie D3
  pinMode(relaisPin, OUTPUT);

  pinMode(Pin_etatRail,INPUT_PULLUP);

  // Led 13 interne : rouge si STOP détecté, éteinte sinon
  pinMode(LED_BUILTIN, OUTPUT);

  // ouvre le port série (console de l'outil) avec la vitesse 57600 bauds
  // attention que le paramètre sur la console soit bien 57600 !
  Serial.begin(57600);

  // relais COMMON - NC (led verte allumée)
  digitalWrite(relaisPin,LOW);
}

// code executé en permanence (une boucle)
void loop() {

  int etat;

  etat = EtatVoie();

  switch (etat) {
    case voie_Libre:
      // relais COMMON - NC (led verte allumée)
      digitalWrite(relaisPin,LOW);
      
      // led 13 éteinte - voie alimentée
      digitalWrite(LED_BUILTIN,LOW);
      
      Serial.println("Voie libre");
      break;

    case voie_Occupee:
      // relais COMMON - NO (led verte eteinte)
      digitalWrite(relaisPin,HIGH);

      // led 13 éteinte - voie alimentée
      digitalWrite(LED_BUILTIN,HIGH);
      delay(25);
      digitalWrite(LED_BUILTIN,LOW);
      
      Serial.println("Voie occupée");
      break;

    case voie_STOP:
      // relais COMMON - NO (led verte eteinte)
     digitalWrite(relaisPin,HIGH);

      // led 13 allumée - voie STOP
      digitalWrite(LED_BUILTIN,HIGH);
      
      Serial.println("Voie STOP");
      break;

    default:
      Serial.print("Voie état inconnu = ");
      Serial.println(etat);
      break;
  }

  delay(250);
  Serial.println("");

}

Et comme précédemment, une petite vidéo qui montre les différentes combinaisons : voie alimentée et libre, voie alimentée et occupée, voie STOP (libre ou occupée) :

Pour info, fatigue aidant, en faisant des tests ce matin, j’ai fumé une carte Nano :face_with_symbols_over_mouth: en ramenant de la tension de la voie sur une entrée digitale VCC 5V … Processeur détruit en moins d’une seconde. Je comprends pourquoi les Nano sont livrés par trois :upside_down_face:

Enjoy !

Attention a ne pas se mettre Julie à dos, elle a des super pouvoirs ! Pauvre Atmega, il ne faisait de mal à personne…
Oui c’est fragile ces petites choses… Tu lui a envoyé 16 volt ?
Jean-Luc

Bonsoir Jean-Luc,

En gros oui … J’ai voulu tester la pin VREF sur l’Arduino, pour améliorer l’acquisition de l’entrée analogique. Sauf que ce VREF doit être dans les limites de l’alimentation de la carte. Je lui ai collé le fil rouge B …

Ensuite,

En testant Tuto06, j’ai ajouté une carte analogique pour lire la tension sur la voie mais j’ai inversé O et B … j’ai fumé mon deuxième Arduino Nano.

Enfin presque. L’USB marche mais n’alimente plus la carte. La carte fonctionne avec une alimentation externe et l’USB se met à fonctionner aussi :slight_smile: .

J’ai pu terminer mes essais directement au pied de la fosse de visite :slight_smile: avec cet Arduino légèrement handicapé, le Mac sur les genoux.

Et pour clôturer l’après-midi, en testant Tuto07 (pas encore publié), j’ai bien branché un fil rouge sur le VCC de l’afficheur à led 7 segments sauf que c’était pas le bon rouge (+12V et non pas +5V). J’en déduis que je devrais mettre un orange pour le +5V pour le repérer …

Effectivement j’ai des super pouvoirs :rofl:

Bonne soirée,

Oups, peut-être temps de lâcher l’arduino et de te vautrer dans ton canapé avec le dernier Guillaume Musso…
Belle fin de soirée…

Ceci dit, tes sketch sont beaux, j’attends le tuto 7 avec impatience…

Hello,

J’ai fait plutot canapé, vodka des bisons :wink: et U2 “Until the End of the World”

J’ai au moins un lecteur intéressé :star_struck: !

Oui j’ai voulu rajouter un afficheur (optionnel), ça permet d’afficher l’état en cours, c’est mieux pour s’assurer que l’automatisme est opérationnel que de ressortir le cable USB et le PC. C’est un afficheur à 2.16 € (par lot de 5), c’est pas un surcout inintéressant pour ma fosse et ultérieurement d’autres automatismes que j’envisage (portes des remises, pompe à eau, …).

Le temps de package ce tutoriel …

Add-on Tuto7

Toujours en prévision de l’automatisme pour la fosse d’inspection, j’ai décidé d’ajouter un petit afficheur 4 digits 7 segments avec un composant TM1637, toujours une référence chez AZ-Delivery, cout unitaire 2.16€, vendu par lot de 5 afficheurs.

https://www.amazon.fr/gp/product/B078S8SGW2/

Pour utiliser cet afficheur, il faut télécharger la documentation de AZ-Delivery sur leur site, lien ici.

Comme pour les autres composants, la documentation est extrêmement bien faite, et l’exemple permet de créer très rapidement sa propre application.

Le branchement de l’afficheur est facile :

  • broche GND vers la GND de l’Arduino
  • broche VCC vers le +5V de l’Arduino
  • broche DIO vers D8 de l’Arduino (on peut choisir un autre Dx que l’on paramètre)
  • broche CLK vers D9 de l’Arduino (on peut choisir un autre Dx que l’on paramètre)

Comme indiqué dans la documentation, Il faut aussi installer une librairie dans l’IDE Arduino pour le composant TM1637. Il en existe plusieurs, il faut choisir celle de Avishay Orpaz dans le menu Outils → Gérer les bibliothèques.

Ensuite on peut créer un objet display et utiliser trois fonctions principales :

  • setSegments() : pour allumer des segments particuliers pour chacun des digits
  • encodeDigit() : pour donner la liste des segments à allumer pour afficher un chiffre particulier
  • clear() : pour effacer l’afficheur

Pour mon exemple, j’ai dédié le premier digit à l’état de la voie :

  • o : occupée
  • L : libre
  • 5 : STOP

Et les trois digits suivant affichent la tension lue sur l’entrée analogique. Attention c’est la valeur ramenée dans la plage 0 - 5V sur une échelle de 0 à 1023. Il faudrait une règle de trois pour trouver la valeur réelle.

Cet affichage est réalisé par la fonction AfficheEtatVal() dans le source suivant. Le reste du programme est calqué sur le Tuto06 précédent.

Pour la définition des SEG_A … SEG_G, voici la matrice de mapping avec les 7 segments du digit :

Et le programme (ou sketch dans la terminologie Arduino) :

// Tuto07
// Exemple pour le forum 3rails / Julie Dumortier / Licence GPL
// 
// extrait du programme Fosse v1.5
//   afficher l'état de la voie sur le rail contact : STOP, libre ou occupé
//    sortie D3 -> relais (LOW = voie libre, HIGH = voie occupée)
//    sortie D13 -> led interne (LOW = voie alimentée, HIGH = voie STOP) EXPERIMENTAL
//   utiliser un afficheur 7 segments 4 digits
//
// Retrouvez ce tutoriel sur le lien : https://forum.3rails.fr/t/une-debutante-dans-le-decor-ep6-quelques-automatismes-arduino-nano/18361
// version 14 mai 2021 : l'état de la voie est prise directement sur le signal

// défini la broche (pin) utilisée pour commander le relais : D3
int relaisPin = 3;

// défini la broche (pin) utilisée pour lire la valeur analogique : A3
int Pin_etatRail = 3;

#include <Arduino.h>
#include <TM1637Display.h>

#define CLK   9
#define DIO   8

TM1637Display display(CLK, DIO);
uint8_t segments[] = {0xff, 0xff, 0xff, 0xff};

// variable pour stocker le seuil de déclenchement
int seuilSignal = 384;

// variable pour compter les déclenchements
int nbFiltre = 16;

// on va filter le signal bas pendant 192 ms pour décider que la voie est libre
int msFiltre = 192;

// Les différents états possibles pour la voie sur le rail contact
//  voie_Occupee la voie est occupée
//  voie_Libre   la voie est libre
//  voie_STOP    la voie est en STOP (CSx ou MSII)

#define voie_STOP    99
#define voie_Occupee  0
#define voie_Libre    1

// AfficheEtatVal
//  affiche l'état et une valeur
//

void AfficheEtatVal(int etat,int val)
{
  // 1er segment : Etat
  switch (etat) {
    case voie_Libre:
      segments[0] = SEG_F | SEG_E | SEG_D;
      break;

    case voie_Occupee:
      segments[0] = SEG_C | SEG_E | SEG_D | SEG_G;
      break;

    case voie_STOP:
      segments[0] = SEG_A | SEG_C | SEG_D | SEG_F | SEG_G;
      break;

    default:
      display.clear();
      break; 
  }
  segments[1] = display.encodeDigit((val / 100) % 10);
  segments[2] = display.encodeDigit((val / 10) % 10);
  segments[3] = display.encodeDigit(val % 10);
  display.setSegments(segments);  
}

// EtatVoie
// retourne l'état de la voie

int EtatVoie()
{
  int n = msFiltre;
  int c = 0;
  
  int vr = 0;
  int vt = 0;

  // flag pour savoir si on a recu un signal de traction
  int traction = 0;
  
  // tant que le signal est bas on continue
  while (n>0) {
    // lit les deux entrées : rail contact et rail normal
    vr = analogRead(Pin_etatRail);
    vt = vr; // analogRead(Pin_etatTraction);

    if (vt>1) {
      traction = vt;
    }
    
    if (vr>seuilSignal) {
      c = c + 1;
    }

    if (c>nbFiltre) {
      // la voie est encore occupée

      // attends la fin du compteur-> la fonction EtatVoie() est à temps d'exécution constant (ce délai peut être supprimé)
      delay(n);

      // met à jour l'afficheur
      AfficheEtatVal(voie_Occupee,vr);
      
      // et retourne l'état d'occupation
      return voie_Occupee;
    }

    // attends 1 ms
    delay(1);

    // et boucle
    n = n - 1;
  }

  // on a eu un signal de traction
  if (traction>0) {

    // le rail contact est resté bas --> la voie est libre
    Serial.println("voie libre");

    // met à jour l'afficheur
    AfficheEtatVal(voie_Libre,traction);
    return voie_Libre;
  }

  // pas de traction

  // met à jour l'afficheur
  AfficheEtatVal(voie_STOP,0);
  
  return voie_STOP;
} 

// code executé une seule fois au démarrage du module (ou après un reset)
void setup() {

  // programme la sortie digitale D3 en sortie
  // le In du relais est connecté à cette sortie D3
  pinMode(relaisPin, OUTPUT);

  // Led 13 interne : rouge si STOP détecté, éteinte sinon
  pinMode(LED_BUILTIN, OUTPUT);

  // ouvre le port série (console de l'outil) avec la vitesse 57600 bauds
  // attention que le paramètre sur la console soit bien 57600 !
  Serial.begin(57600);

  // relais COMMON - NC (led verte allumée)
  digitalWrite(relaisPin,LOW);

  // regle l'intensité de l'affichage
  display.setBrightness(0x0f);
  display.clear();
}

// code executé en permanence (une boucle)
void loop() {

  int etat;

  etat = EtatVoie();

  switch (etat) {
    case voie_Libre:
      // relais COMMON - NC (led verte allumée)
      digitalWrite(relaisPin,LOW);
      
      // led 13 éteinte - voie alimentée
      digitalWrite(LED_BUILTIN,LOW);
      
      Serial.println("Voie libre");
      break;

    case voie_Occupee:
      // relais COMMON - NO (led verte eteinte)
      digitalWrite(relaisPin,HIGH);

      // led 13 éteinte - voie alimentée
      digitalWrite(LED_BUILTIN,LOW);
      
      Serial.println("Voie occupée");
      break;

    case voie_STOP: // EXPERIMENTAL
      // relais COMMON - NO (led verte eteinte)
      digitalWrite(relaisPin,HIGH);

      // led 13 allumée - voie STOP
      digitalWrite(LED_BUILTIN,HIGH);

      Serial.println("Voie STOP");
      break;

    default:
      Serial.print("Voie état inconnu = ");
      Serial.println(etat);
      break;
  }

  delay(250);

}

A noter que le programme fonctionne parfaitement bien même en l’absence de l’afficheur.

Et comme à chaque fois, une petite vidéo pour illustrer ce tutoriel (vous remarquerez que ce tutoriel est réalisé directement sur la fosse de visite … mais il fonctionnera parfaitement avec le montage de voie C précédent) :

Un dernier mot : si vous voulez afficher la tension de la voie en dixième de volt, vous pouvez ajouter ces quelques lignes en tête de la fonction AfficheEtatVal :

void AfficheEtatVal(int etat,int val)
{
  // conversion de val en dixième de Volts (dV)
  float temp;

  temp = (250.0*val)/1024.0; // capteur de tension est sur une plage 0-25V
  val = (int)temp;
  ...

Ce dernier exemple clôture notre Episode 6 ! La suite côté fosse de visite.

Bonjour Julie,

C’est très obscur pour moi ces arduinos maisj’ai l’impression que les possibilités sont énormes…

Il faudra que je m’y mette un jour…

Bonne continuation

Thomas

Bonjour Thomas,

Oui les possibilités sont énormes et je peux t’assurer que leur mise en oeuvre n’est pas si compliquée. Il faut juste se lancer. Et au travers de ce tutoriel, je découvre l’Arduino au fur et à mesure.

Je n’avais pas fait d’électronique depuis mes 25 ans (68HC11 à l’époque et c’était nettement plus compliqué à cabler et à programmer). Là il suffit de brancher des broches (pins) en suivant le manuel …

Il y a encore quelques jours je n’aurais même pas imaginé y mettre un afficheur par exemple. Et finalement je trouve la programmation d’un M83 via les CV bien plus compliqué que mettre en oeuvre un Arduino Nano. En plus le logiciel de programmation arrive avec une foultitude d’exemples tous très bien documentés.

Tsss. Y en a pour 12 euros d’achats et 1 heure de mise en oeuvre … pourquoi repousser ça à la saint glinglin :wink:

Je trouve que ça change les perspectives de ce que l’on peut faire sur un module : simulation d’un poste de soudure à l’arc, ouverture automatique des portes d’une remise, contrôle d’une grue à eau …

J’ai finit l’automatisation de mon pont tournant avec le kit Locomotech avant de mettre en oeuvre cet Arduino. Mais je me faisais la réflexion que je pouvais faire la même chose avec un Arduino Nano, un capteur photo-électrique et deux relais pour le 1/4 du prix … Bon c’est fait mais si c’était à refaire …

Bonne journée :slight_smile:

Julie a raison, c’est simple à mettre en oeuvre et pas cher. J’ai fait un simulateur de soudure à l’arc sans problème. Tu peux aussi gérer des diodes RGB pour une affiche lumineuse, etc…
Sur le site locoduino, il y a plein d’exemple du plus simple à la gestion de locos DCC.
Belle journée Jean-Luc

1 « J'aime »

L’automatisme de la fosse d’inspection est publié ici :

Enjoy.

Hello Julie,
Très intéressant tes explications concernant l’Arduino Uno.
Comme je suis uniquement en analogique, peux-t-on l’utiliser pour travailler avec les signaux et voies de garage, etc, ou il faut absolument une MS2 ou CS2 ?
Moi je n’y connais rien en électronique donc …
Amicalement
Serge

Bonsoir Serge,

Dans le cadre de l’automatisme de la fosse, je n’utilise aucune fonction dite numérique de la voie. Je ne fais que lire sa tension pour savoir si elle est alimentée ou non. Et dans ma vidéo j’utilise la MS2 juste pour mettre la voie en Stop ou en service.

A priori cela devrait fonctionner en analogique mais ne connaissant absolument pas ce domaine ancien de Marklin, je ne serais pas affirmative.

Bonne soirée,

1 « J'aime »

Aucune raison que ça ne fonctionne pas en analogique, l’utilisation de l’Arduino n’a nul besoin du digital pour fonctionner.
Jean-Luc

1 « J'aime »

Merci Jean-Luc pour ces infos, mais ce qui coince pour moi c’est les branchements, pour éviter de cramer les signaux. Y a-t-il des modes d’emploi pour les branchements ?
Serge