Passage à niveau géré par Arduino (3)

Commande du mouvement des barrières

. Par : Christian. URL : https://www.locoduino.org/spip.php?article263

Dans cet article, nous allons compléter notre passage à niveau en lui adjoignant deux barrières commandées par l’approche d’un train. Nous emploierons des servomoteurs pour réaliser le mouvement des barrières car les cartes Arduino disposent d’une bibliothèque capable de commander simplement ces composants très économiques.

Montage des barrières

La figure 1 montre un passage à niveau automatique de type SAL 2 (pour plus de détails sur les passages à niveau, consulter le Hors-Série Loco-Revue N° 60). Nous voyons deux demi-barrières et deux feux de PN. On trouve dans le commerce des kits en plastique ou laiton reproduisant des barrières de passage à niveau. Nous avons choisi pour ce projet un kit en plastique à l’échelle H0 de marque Auhagen (référence 41625). Ce sont ses barrières que nous allons motoriser avec des servomoteurs.

Figure 1
Figure 1
Passage à niveau automatique de type SAL 2

Pour l’instant, nous allons nous concentrer sur le mouvement des servomoteurs et nous verrons ultérieurement comment transmettre ce mouvement aux barrières du kit. La vidéo ci-dessous montre le prototype que nous avons développé et permet de voir le rendu du clignotement des feux, une attente fixée à deux secondes puis le mouvement des barrières. La sonnerie a été rajoutée au montage du film car la partie sonore du projet n’était pas encore réalisée.

Montage des servomoteurs avec la carte Arduino Uno

La carte Arduino Uno est capable de gérer jusqu’à 12 servomoteurs (voir l’article La bibliothèque Servo) ; il ne nous en faut que deux et si ces servomoteurs n’ont pas une consommation trop élevée, ils peuvent être alimentés par la sortie 5 V de la carte Uno. C’est notamment le cas pour les micro-servos Tower Pro SG90 (livrés par exemple avec les kits de découverte d’Arduino) qui ont été utilisés dans ce montage ; leur force de traction est amplement suffisante pour manœuvrer une barrière. La figure 2 montre comment relier ces deux servomoteurs à la carte Arduino Uno.

Figure 2
Figure 2
Le montage des servomoteurs sur la carte Arduino Uno

Lorsqu’une barrière de PN passe de la position fermée à la position ouverte, elle passe d’une position horizontale à une position verticale (ou quasiment). Nous allons donc manœuvrer nos servomoteurs sur un débattement de 90° et pour cela, nous utiliserons la bibliothèque Servo livrée avec l’IDE d’Arduino. Le mouvement ainsi obtenu sera parfait pour des demi-barrières automatiques. Ceux qui veulent reproduire des barrières qui étaient manœuvrées à la main par un garde-barrière auront intérêt à utiliser la bibliothèque SlowMotionServo décrite dans l’article La bibliothèque SlowMotionServo car ils pourront ainsi simuler un rebond de la barrière lorsqu’elle arrivait en position horizontale. Ce rebond n’existe pas pour une demi-barrière automatique donc cette bibliothèque n’apporte aucun avantage d’autant que les barrières doivent être fermées assez rapidement sur un petit réseau comme Train’ In Box.

Le programme

Encore une fois, nous ne faisons que compléter le programme donné dans l’article précédent. Comme le montre la figure 2, les servomoteurs sont reliés aux sorties 4 et 8. Le programme introduit un délai (delaiFermeture) entre le clignotement des feux de PN et le début du mouvement des barrières. Ce délai était égal à 2 secondes pour tourner la vidéo ci-dessus mais a été mis à zéro car le programme est livré pour le réseau TIB ; à vous d’adapter ce délai en fonction de la taille de votre réseau pour que les barrières soient entièrement fermées quand le train passe. Ceux qui ont un grand réseau pourront se rapprocher de la réalité où le délai est de l’ordre de 8 secondes (voir le premier article). La vitesse du mouvement des barrières est aussi réglable grâce à la variable speedServo.

L’instanciation crée deux objets de type Servo appelé servo1 relié à l’entrée S1 et servo2 relié à l’entrée S2. L’initialisation doit se faire avec un train sur la zone du PN donc barrières fermées.

La fonction loop n’est pas compliquée à comprendre. Elle surveille l’état de la zone PN et agit en conséquence. Si la zone PN est libre, il suffit d’arrêter le clignotement des feux et d’ouvrir les barrières. Si la zone PN est occupée, son état passe de false à true et il faut alors faire l’inverse et fermer les barrières. Or on veut attendre un petit délai avant de fermer les barrières, c’est pourquoi on compare l’état de la zone avec son état précédent de manière à lancer l’attente que s’il y a eu changement d’état. Si on ne faisait pas cela, alors on relancerait indéfiniment le délai à attendre et il ne serait jamais terminé pour manœuvrer les barrières. Le mouvement des barrières est obtenu grâce à la méthode write(posServo).

Le mouvement des barrières est donc obtenu en faisant varier la position du servomoteur de 1° à chaque itération de la fonction loop() jusqu’à avoir atteint la position souhaitée (PN ouvert ou fermé). La vitesse du mouvement est contrôlée en introduisant un petit délai grâce à delay(speedServo);.

La fonction delay() ne devrait jamais être utilisée avec la bibliothèque "LightDimmer" car les états des LED doivent être mises à jour fréquemment. On peut d’ailleurs le lire en commentaire dans le fichier écrit en C++ LightDimmer.cpp : " LightDimmer::update shall be called in loop to allow the library to update the state of each LED... So you shall never use the delay function in your sketch ". Le délai introduit ici est très court et ne perturbe pas énormément la mise à jour des états des LED de LightDimmer comme on peut le constater sur la vidéo. Cela peut paraître peu académique mais dans la mesure où le résultat produit est satisfaisant, on peut le faire sans état d’âme. Bien évidemment, toute modification du programme pour y introduire de longs délais serait vouée à l’échec et ne produirait pas l’effet escompté.

Le programme ci-dessous est suffisamment commenté pour ne pas présenter de difficultés de compréhension. Par rapport au programme du précédent article, voici ce que nous avons ajouté :

  • inclusion de la bibliothèque Servo (ligne 15)
  • déclaration des sorties pour les servomoteurs (lignes 19-20)
  • des variables à la main de l’utilisateur pour régler le délai avant fermeture et la vitesse du mouvement (lignes 23 à 27)
  • des variables à ne pas modifier (lignes 29 à 38)
  • instanciation de deux objets de type Servo (ligne 42-43)
  • ans le setup : rattachement des servomoteurs aux sorties déclarées (lignes 63-64) et fermeture des barrières (lignes 65 à 67)
  • dans la loop : ouverture des barrières dès que etatZonePN est égal à false (lignes 79 à 85) ou bien fermeture des barrières une fois le délai avant fermeture passé si etatZonePN est égal à true (lignes 94 à 102)
/******************************************************************************
 * PN_TIB_FeuBarrieresAttente_InitFerme.ino
 * ****************************************************************************
 * Programme developpe pour le projet de PN pour Train In Box.
 * Il prend en compte l arrivee du train, le clignotement des feux en simulant 
 * une ampoule a filaments, un delai de deux secondes avant mouvement des 
 * barrieres, le mouvements des deux barrieres sur 90° d amplitude (depend de 
 * la transmission adoptee).
 * Le programme s'initialise barrieres fermees, donc AVEC TRAIN EN GARE.
 * ****************************************************************************
 * Christian BEZANGER - 13 Novembre 2018 - 2 Juin 2019 - 29 mai 2020
 ******************************************************************************/

#include <LightDimmer.h>  // Bibliotheque pour gerer les feux du PN
#include <Servo.h>        // Bibliotheque pour gerer les barrieres du PN

const byte ILS=2; // entree des capteurs 
const byte LED=6; // sortie PWM des feux du PN
const byte S1=4; // sortie pour le servomoteur 1
const byte S2=8; // sortie pour le servomoteur 2
unsigned int compteur = 1;  // compteur d evenements (survol ILS)

// Variables utilisateur pour reglage du mouvement des barrieres
// -------------------------------------------------------------
unsigned long delaiFermeture = 0; // Regle le delai entre clignotement LED 
// et fermeture barrieres - entre 2000 et 8000 mais 0 sur TIB (pas de delai)
int speedServo = 30;  // Regle la vitesse de mouvement des barrieres

// Variables non utilisateur
// -------------------------
volatile static boolean etatZonePN = true; // true si la zone du PN est occupee
volatile static boolean old_etatZonePN = false; // etat anterieur de la zone
volatile static unsigned long old_top_debutISR;  // Date anterieure d appel ISR
unsigned long old_top = 0;  // variable pour afficher donnees utiles
int posServo = 90; // position courante a initialiser imperativement FERMEE
int posOuvert = 0;  // barriere a 10° de la verticale
int posFerme = 90; // barriere a l'horizontale (90° de la verticale)
unsigned long topAttente = 0; // top pris au début franchissement de la zone PN

// Instanciations
LightDimmer feuPN;
Servo servo1;
Servo servo2;

void changeEtat() { // routine d'interruption (ISR)
  unsigned long top_debutISR = millis();  // date appel ISR
  if((top_debutISR - old_top_debutISR) > 2000) {
    // 2 secondes au moins entre execution ISR
    etatZonePN = !etatZonePN; // etat passe a etat oppose
    old_top_debutISR = top_debutISR;  // initialisation date anterieure d appel ISR
  }
} // fin de ISR

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200); // communication avec le moniteur
  pinMode (ILS, INPUT_PULLUP);  // entree capteur
  pinMode (LED_BUILTIN, OUTPUT);  // LED du module allumee si Zone PN occupee
  pinMode (LED, OUTPUT);  // sortie pour feux du PN
  attachInterrupt (digitalPinToInterrupt(ILS), changeEtat, FALLING);
  digitalWrite (LED_BUILTIN, LOW);
  feuPN.begin(LED, HIGH); // LED s'allume avec etat haut
  servo1.attach(S1);
  servo2.attach(S2);
  // initialisation des barrieres en position fermee
  servo1.write(posFerme); // barriere 1 FERMEE apres initialisation
  servo2.write(posFerme); // barriere 2 FERMEE apres initialisation
  delay(2000);
  digitalWrite (LED_BUILTIN, HIGH); // Indique fin de setup
}  // fin de setup

void loop() {
  // put your main code here, to run repeatedly:
    if(etatZonePN == false) {
    old_etatZonePN = etatZonePN;
    digitalWrite (LED_BUILTIN, LOW); // eteint LED de controle de la zone PN
    feuPN.stopBlink();  // arrete le clignotement
    feuPN.off();  // eteint les feux
    // ouverture barriere
    if(posServo > posOuvert) {
      posServo = posServo - 1;
      servo1.write(posServo);
      servo2.write(posServo);
      delay(speedServo);
    }  // fin du test sur position des servos
  }  // fin du test sur etat de la Zone du PN -> false
  if(etatZonePN == true) {
    if(etatZonePN != old_etatZonePN) {
      topAttente = millis();  // prend un top d'entree dans zone PN
      old_etatZonePN = etatZonePN;
    }  // fin du deuxieme if
    digitalWrite (LED_BUILTIN, HIGH); // allume LED de controle de la zone PN
    feuPN.startBlink(); // commence le clignotement
      // fermeture barriere après attente
    if(millis() - topAttente > delaiFermeture) {
      if(posServo < posFerme) {
        posServo = posServo + 1;
        servo1.write(posServo);
        servo2.write(posServo);
        delay(speedServo);
      }  // fin du test sur position des servos 
    }  // fin du test sur delai avant fermeture
  }  // fin du test sur etat de la Zone du PN -> true
  LightDimmer::update();
  if(old_top_debutISR != old_top) { // Affichage pour chaque nouveau survol ILS
    Serial.print(compteur);
    Serial.print("     ");
    Serial.print(old_top_debutISR);
    Serial.print("     ");
    Serial.println(old_top_debutISR - old_top);
    old_top = old_top_debutISR; 
    compteur = compteur + 1;   
  }
}  // fin de loop

Transmission mécanique du mouvement

Avoir des servomoteurs qui bougent est une chose mais encore faut-il transmettre ce mouvement aux barrières. Et pour cela, il faut aussi des barrières. Il existe des kits de passage à niveau en plastique dans le commerce ; ils sont assez bon marché et assez faciles à assembler mais ils sont tout de même très fragiles et ne représentent pas toujours correctement un PN français, ce qui nécessite de les reprendre un peu. On trouve également des kits en laiton à un prix plus élevé et qui demandent une certaine aptitude pour les assembler, mais ils sont de meilleure facture.

À la demande de LR-Modélisme, nous avons développé un PN automatique afin de l’implanter sur le réseau Train’ In Box (TIB). Nous sommes partis du kit en plastique de passage à niveau Auhagen référence 41625 pour le H0. Nous allons décrire dans les grandes lignes les solutions que nous avons retenues pour transmettre le mouvement aux barrières. Bien évidemment, notre conception peut trouver sa place sur un autre réseau que TIB. Dans le dernier article de cette série, nous verrons d’autres possibilités de barrières que la solution Auhagen.

Le PN Auhagen est surtout prévu pour être statique avec ses barrières fermées mais la notice de montage prévoit qu’on peut tout de même motoriser la barrière avec un servomoteur. Le mouvement des barrières est obtenu en tirant ou en poussant une tige de commande en plastique et le débattement doit être de 2,5 mm, ni plus ni moins, afin de faire passer la barrière de la position horizontale (barrière fermée) à la position verticale ou presque (barrière ouverte).

Il convient donc de passer du mouvement de rotation de 90° du servomoteur à un mouvement de translation de 2,5 mm de la tige de commande sans dépasser l’amplitude de 2,5 mm. La solution retenue est de faire appel à une came excentrique tournant de 90° (ce qui permet un mouvement relativement lent) et dont la forme permet à la tige de bouger de 2,5 mm, ni plus ni moins. Cependant, la tige en plastique du PN Auhagen est flexible et doit être renforcée avec un tube en laiton. De plus, un réglage de la longueur de la tige de commande est prévu pour tenir compte de l’épaisseur de la plateforme supportant le PN qui dépend du matériau utilisé.

Afin de maintenir ensemble le servomoteur, sa came et la tige de commande de la barrière, un petit support en contreplaqué de 3 mm est fabriqué et ce support est collé sous la plateforme en carton gris de 2 mm du coffret TIB. Enfin, pour permettre à la barrière de remonter lors du mouvement d’ouverture, un petit élastique joue le rôle de ressort de rappel.

La figure 3 donne les cotes de chaque pièce constituant les supports de servomoteur, ainsi que la façon de les monter ensemble grâce à un code de couleur différent pour chaque pièce. Les pièces F1 et F2 (21 mm x 15 mm) ont un chanfrein à 45° ; elles sont collées l’une sur l’autre pour constituer une gorge à 90° dans laquelle viendra s’insérer le tube en laiton de 3 mm de diamètre extérieur et de 16 mm de long (appelé tube 2, référence P1249 chez Octant, et servant à guider le mouvement de la tige de commande). Dans ce tube 2 viendra coulisser un tube plus petit renforçant la tige de commande en plastique des barrières Auhagen. Tube 2 doit affleurer le haut des pièces F1 et F2 et dépasser en bas et il doit être positionné juste au-dessus de la came excentrique.

Figure 3
Figure 3
Les pièces constituant le support de servomoteur

Celle-ci est découpée dans du bois tendre d’épaisseur 8 mm ; sa forme est constituée d’un demi-cercle de rayon 10 mm pour sa partie inférieure et d’une demi-ellipse de demi-grand axe 12,5 mm pour sa partie supérieure comme le montre la figure 4.

Figure 4
Figure 4
Dessin de la came excentrique

La figure 5 montre le support de servomoteur terminé et la came mise en place. Pour un meilleur glissement avec la tige de commande, on peut graphiter le pourtour de la came avec de la poudre de mine de crayon gras (genre 2B) car le graphite est un excellent lubrifiant.

Figure 5
Figure 5
Le support de servomoteur terminé

Afin de renforcer la tige de commande, nous l’entourons d’un premier tube en laiton de diamètre intérieur 1,4 mm et de diamètre extérieur 2,0 mm (appelé tube 1, référence P1245 chez Octant), qui coulisse parfaitement avec tube 2 servant au guidage en respectant un jeu de 0,1 mm comme préconisé par Octant. Le collage de tube 1 avec la tige de commande se fait à la fin du montage de la barrière, mais il faut respecter une certaine distance par rapport à la tête carré de la tige de commande qui est de 12,5 mm. Faites un repère au feutre sur la tige de commande avant de commencer le montage conformément à la figure 6. La longueur de tube 1 est de 25,5 mm (tolérance +0,5 -0 mm). La tige de commande en plastique est recoupée à la pince coupante pour qu’elle ne dépasse pas du tube.

Figure 6
Figure 6
Tige de commande renforcée
Tube 1 est collé à la tige de commande avec une microgoutte de cyanoacrylate mais uniquement lorsque le mécanisme de commande est complètement monté (conformément à la notice Auhagen). Ne jamais coller tube 1 et tige de commande avant d’assembler le mécanisme. Pour le collage, assembler à blanc la tige et le tube puis déposer un peu de cyanoacrylate liquide en haut du tube (côté tête de tige de commande) : celle-ci s’infiltrera par capillarité et maintiendra définitivement le tout assurant que le tube est bien à 12,5 mm de la tête.

Le montage de la barrière est bien décrit dans la notice Auhagen ; il ne faut surtout pas utiliser de colle sauf entre le pied de barrière et le socle. La figure 7 montre la barrière une fois montée et renforcée.

Figure 7
Figure 7
Mécanisme de barrière
La mécanique du mouvement des barrières ainsi obtenue est assez fragile du fait qu’elle est en plastique, notamment le petit ergot de la fourche entrant dans la tête de la tige. Il convient donc de ne pas tirer trop fort sur cette tige lors des mouvements d’ouverture ou fermeture.

Tube 1 est rallongé par une pièce constituée de la partie métallique en laiton d’un simple domino d’électricien, le plus petit modèle que vous trouverez en GSB. Non seulement cette pièce permet à la tige de commande de reposer sur la came avec un ajustement précis et réglable, mais la vis permet aussi de retenir l’élastique permettant à la tige de redescendre (voir la figure 9 et la vidéo du début d’article).

L’élastique est un modèle de 30 à 35 mm de diamètre, tenu dans les encoches des pièces C1 et C2 et sur une des vis de la pièce de rallonge. Sa force de rappel doit être juste suffisante pour maintenir la tige de commande en contact avec la came sans bloquer la mécanique.

Faites un trou de diamètre 4 mm aux endroits voulus pour les barrières ; le support de servomoteur est collé sous le réseau et la barrière est positionnée par le dessus dans cet ensemble comme le montre la figure 8.

Figure 8
Figure 8
La barrière installée sur le réseau

Reliez le servomoteur à la carte Arduino et démarrez celle-ci. Après l’initialisation, c’est-à-dire quand les feux de PN clignotent, le servomoteur est en position barrière fermée et il suffit alors de positionner la came pour que son grand axe soit dans le prolongement de la tige de commande. Réglez alors la rallonge puis positionnez l’élastique comme le montre la figure 9. Votre installation est terminée.

Figure 9
Figure 9
Le support de servomoteur en place sous le réseau. On remarque la rallonge domino sur laquelle l’élastique vient s’accrocher.

Notre passage à niveau a déjà tout d’un grand : des feux qui clignotent, des barrières qui bougent, un train qui passe. Il ne lui manque plus que la parole… enfin, le son ! Rendez-vous à l’épisode suivant.