Une débutante dans le décor - Ep4 - Kitbashing d’une fosse d'inspection

Hello,Je suis FAN !
Hyper FAN !

Chris

1 « J'aime »

C’est remarquable … et je me rends compte à quel point je suis nul en électronique, je n’y comprends rien …
Bravo pour la réalisation.

Amitiés
Thierry

Bonjour Thierry,

Tsss. Des cartes achetées dans le commerce pour quelques euros, un branchement très facile (y aura même pas besoin de fer à souder) et une programmation basique.

A la portée de toute personne capable de connecter une voie C avec une MS2 :slight_smile: Je vais montrer tout ça dans un petit tutoriel à suivre !

Bonne journée,

1 « J'aime »

Hello manu,

J’ai reçu les Auhagen, ils sont vendus par pair. A première vue ils sont adaptables pour faire un coupon 24361 version cheap :slight_smile:

Ça tombe bien il me fallait quatre fosses :

  • une fosse d’inspection bien visible, objet du présent tutoriel,
  • une fosse pour l’atelier moteur,
  • deux fosses techniques pour la double remise technique.

Pour la fosse de l’atelier moteur, je vais recycler :recycle: le prototype du présent tutoriel et le noyer dans la chape de béton qui va accueillir le bâtiment de l’atelier moteur. Bâtiment plutôt moderne pour l’époque avec une bonne visibilité sur l’intérieur du bâtiment,

Pour la double remise, je vais utiliser les Auhagen car je ne vais pas faire des fosses trop abouties en terme de réalisation car elles seront moins visibles et se laisseront deviner au travers des fenêtres plus réduites d’un bâtiment époque I - 1918, rénové après guerre pour les besoins de l’héritière.

Donc mon cher Manu, si tu as un peu de patience, je compléterais le présent tutoriel d’une version mons scratch et plus kit bashing en utilisant ces références qui sont plutôt répandues et accessibles en terme de prix.

Dis moi juste si tu veux les équiper d’un éclairage ou pas (peut être j’en ferais un avec éclairage et l’autre sans, il me reste des leds en bande à placer).

@+

Wahou ! C’est classieux ! Du beau boulot.

1 « J'aime »

Bonsoir Thierry,

Le tutoriel est paru :slight_smile: ici :

Grand merci Julie
Je vais étudier cela très attentivement
Bonne fin de weekend
Thierry

Episode 4.5 - Automatisme et finitions

Il est temps de finir notre fosse de visite. La partie qui suit est optionnelle, elle consiste à ajouter un automatisme pour l’éclairage de la fosse. Une solution plus simple consiste juste à brancher + et - des bandeaux de leds à l’alimentation des accessoires.

14 mai 2021 : simplification du montage et amélioration du filtre pour lire l’état de la voie (cf Tuto05)

Pour cet automatisme je me suis donnée le cahier des charges suivants :

  • si la voie est STOP, la fosse est éteinte, quelque soit son état d’occupation.
  • lorsqu’une locomotive se présente sur la fosse, elle ne s’éclaire qu’après un laps de temps (8s avec mon paramétrage). Cela permet de laisser la fosse éteinte quand la locomotive ne fait que passer.
  • de manière symétrique, lorsqu’une locomotive quitte la fosse allumée, celle-ci s’éteint après un laps de temps (8s avec mon paramétrage).
  • lorsque la fosse est allumée, un mode veille se déclenche qui éteint la fosse au bout de 6 minutes.
  • deux entrées en pull up (mettre un interrupteur à GND) permettent de forcer l’allumage ou l’extinction.

Un afficheur optionnel affiche l’état de la fosse et l’éventuel décompte en cours :

  • “5 -” : la voie est STOP
  • “E xx” : la fosse est éteinte mais la séquence d’allumage est enclenchée - il reste xx secondes avant allumage
  • “A xx” : la fosse est allumée mais la séquence d’extinction est enclenchée - il reste xx secondes avant extinction
  • “Ax:xx” : la fosse est allumée mais la séquence de mise en veille est enclenchée - il reste xxx secondes avant la mise en veille
  • " : " : l’éclairage de la fosse est en veille
  • “U xx” : l’état xx n’est pas connu (ça ne devrait jamais s’afficher !)
  • “FA” : la fosse est forcée allumée
  • “FE” : la fosse est forcée éteinte

La liste du matériel comprend (on peut aussi acheter directement chez AZ Delivery mais j’ai profité de mon abonnement Prime chez Amazon pour ne pas payer de frais de port) :

Soit un automatisme qui va couter unitairement moins de 14 euros.

Le schéma de connexion est une simple évolution du tutoriel Tuto07, avec deux entrées de forçage supplémentaire :

Le sketch (pour utiliser la terminologie Arduino, c’est à dire le programme) est assez conséquent mais facile à suivre (très commenté et la suite logique du tutoriel progressif de l’épisode 6).

La vraie nouveauté est l’implémentation d’une machine à état finis (Finite State Machine) pour s’assurer de l’exhaustivité des situations rencontrées par l’automatisme. C’est un objet informatique moins classique mais que toute personne pratiquant l’automatisme devrait connaitre.

On trouvera plus d’information sur les machines à états finis sur Google, et on commencera par la page Wikipedia Automate fini — Wikipédia

// Fosse v1.5
// (c) Julie Dumortier, 2020-2021
// licence GPL
//
// Evolutions
// v1.0 première version sur plateforme de démonstration
// v1.5 détection STOP sur la voie et afficheur optionnel (v20201222)
// 14 mai 2021 : lecture de l'état STOP directement sur le rail !

// mettre à 1 pour un debug dans la console série
#define debug 1

// D3 : input : forçage allumé (pullup) (par défaut, l'allumage n'est pas forcé)
// D4 : input : forçage éteint (pullup) (par défaut, l'extinction n'est pas forcée)
// D5 : output : allumage des bandeaux de leds (COMMON - NC)

int Pin_forcageAllume = 3;
int Pin_forcageEteint = 4;
int Pin_allumageLeds = 5;

// A3 : input : état d'occupation de la fosse (rail contact / fil bleu)
int Pin_etatRail = 3;

// Temps avant allumage (en secondes) : 4 (debug) ou 8
int tempsAvantAllumage = 8/(1+debug);

// Compteur de temps avant l'ellumage (en millisecondes)
unsigned long timeAllumage = 0; 

// Mise en veille (en secondes) : 8 (debug) ou 180
int tempsAvantVeille = 60*6/(1+(43*debug));

// Compteur de temps avant la Veille (en millisecondes)
unsigned long timeVeille = 0; 

// Temps avant extinction (en secondes) : 4 (debug) ou 8
int tempsAvantExtinction = 8/(1+debug);

// Compteur de temps avant l'extinction (en millisecondes)
unsigned long timeExtinction = 0; 

// Filtre bas du signal d'occupation
int msFiltre = 192;

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

// Seuil de déclenchement du signal d'occupation
int seuilSignal = 384;

// inclus une librairie toute simple pour l'afficheur
#include <Arduino.h>
#include <TM1637Display.h>

// Connexion de l'afficheur sur lAarduino : CLK sur D9 et DIO sur D8
#define CLK   9
#define DIO   8

// Crée l'objet display pour interagir avec l'afficheur
TM1637Display display(CLK, DIO);

// structure globale avec le contenu de l'afficheur
uint8_t segments[] = {0xff, 0xff, 0xff, 0xff};

// FSM (Machine à etats finis) Etats possibles des lumières de la fosse
// cf https://fr.wikipedia.org/wiki/Automate_fini
// Ce type d'approche permet d'implémenter un automatisme robuste

#define state_Eteint        0
#define state_Allume        1
#define state_ForceEteint   2
#define state_ForceAllume   3
#define state_enAllumage    4
#define state_enExtinction  5
#define state_enVeille      6

// La FSM est complétée par l'état de la voie
// 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

// AfficheSegVal
//  affiche des segments sur le premier digit et une valeur sur les trois autres digits
//  seg : encodage du 1er digit 
//  val : valeurs à afficher sur les trois digits suivant
//  dp  : allume le double point

void AfficheSegVal(uint8_t seg,int val,boolean dp=false)
{
  uint8_t b1;
  uint8_t b2;
  
  // prépare la structure des segments
  segments[0] = seg;

  if (val>0) {
    b1 = (val / 100) % 10;
    segments[1] = b1?display.encodeDigit(b1):0x00 | (dp?0x80:0x00);
    segments[2] = (b1||b2) ? display.encodeDigit((val / 10) % 10) : 0x00;
    segments[3] = display.encodeDigit(val % 10);
  } else {
    segments[1] = (dp?0x80:0x00);
    segments[2] = 0x00;
    segments[3] = SEG_G;
  }
  // appel la librairie pour envoyer les segments sur l'afficheur
  display.setSegments(segments); 
}

// AfficheEtatVal
//  affiche l'état de la voie et une valeur (tension sur la voie) en dV
//  etat : etat de la voie
//  val  : valeur de la tension (0 - 1023)

void AfficheEtatVal(int etat,int val)
{
  uint8_t seg;  // segments du 1er digit
  float   temp; // variable temporaire pour la conversion
 
  // conversion de val en dixième de Volts (dV)
  // capteur de tension est sur une plage 0-25V
  temp = (250.0*val)/1024.0; 
  val = (int)temp;
  
  // construire le 1er segment selon l'état de la voie
  switch (etat) {
    case voie_Libre:
      // (L)ibre
      seg = SEG_F | SEG_E | SEG_D;
      if (debug) { Serial.print("voie_Libre val="); Serial.println(val);}
      break;

    case voie_Occupee:
      // (O)ccupée
      seg = SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F;
      if (debug) { Serial.print("voie_Occupee val="); Serial.println(val);}
      break;

    case voie_STOP:
      // (S)top + val
      seg = SEG_A | SEG_C | SEG_D | SEG_F | SEG_G;
      if (debug) { Serial.print("voie_STOP val="); Serial.println(val);}
      break;

    default:
      // (U)nknown + etat
      seg = SEG_B | SEG_C |SEG_D | SEG_E |SEG_F ;
      val = etat;
      if (debug) { Serial.print("voie_"); Serial.print(val); Serial.print("? val="); Serial.println(val);}
      break; 
  }

  // affiche le contenu
  AfficheSegVal(seg,val); 
}

// EtatVoie
// retourne l'état de la voie (voie_Occupee,voie_Libre, voie_STOP)
//
// L'algorithme est assez trivial
// Lecture des entrées analogiques vr Rail contact et vt Rail traction
// Si on trouve au moins un vr supérieur à un seuil, le rail contact est occupé
// Si on ne trouve aucun vt supérieur à un seuil, le rail traction est STOP
// Sinon le rail contact est libre
//
// NB : quand le rail traction est STOP, il n'est pas possible de savoir si le
// rail contact est libre ou occupé. 

int EtatVoie()
{
  int n = msFiltre; // nombre de fois que l'on va s'assurer que le rail contact est libre
  int c = 0;
  
  int vr = 0; // valeur analogique sur le Rail Contact
  int vt = 0; // valeur analogique sur le Rail traction

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

    // la voie de traction est-elle alimentée ?
    if (vt>1) {
      traction = vt;
    }

    // le rail de contact est-il libre ?
    if (vr>seuilSignal) {
      c = c + 1;
    }
    if (c>nbFiltre) {
      // la voie est encore occupée

      // attends la fin du compteur pour une fonction à temps défini (environ filtreBas ms)
      delay(n);

      // met à jour l'afficheur
      if (debug) 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

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

  // pas de traction

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

// Etat courant de la machine à état finis (FSM)
// A l'initialisation de l'Arduino, tout est censé être éteint
int state = state_Eteint;

// FSM Séauences (cahier des charges) :
// 1. fosse normalement éteinte sauf si forçage par D3 (M83 - bouton vert - au commun==GND)
// 2. une locomotive passe sans s’arrêter, la fosse reste éteinte sauf si le forçage est en cours
// 3. une locomotive stationne, au bout d’un temps programmable, la fosse s’allume
// 4. la fosse allumée s’éteint au bout d’un certain temps programmable, économie d’énergie oblige
// 5. une locomotive repart, la fosse allumée s’éteint au bout d’un temps programmable
// 6. D4 pour un forçage éteint même si des locomotives stationnent (M83 - bouton rouge - au commun==GND)

// allumeLeds
void allumeLeds()
{
  // relais COMMON - NC (led verte allumée)
  digitalWrite(Pin_allumageLeds,LOW);
}

// eteintLeds
void eteintLeds()
{
  // relais COMMON - NO (led verte eteinte)
  digitalWrite(Pin_allumageLeds,HIGH);
}

// Eteint la fosse
void EteintFosse()
{  
  switch (state) {
    case state_enAllumage:
      // la fosse était en phase d'allumage quand l'ordre d'éteindre arrive
      // on stoppe le timer d'allumage et on passe en statut Eteint
      timeAllumage = 0;
      state = state_Eteint;

      // par acquis de conscience, on éteint les leds (censées être eteintes)
      eteintLeds();

      if (debug) Serial.println("EteintFosse() state:enAllumage -> Eteint");
      break;
      
    case state_ForceEteint:
      // éteint immédiatement les leds si ce n'est pas déjà fait
      eteintLeds();

      if (debug) Serial.println("EteintFosse() state:ForceEteint");
      break;

    case state_enVeille:
      // la fosse passe en veille
      // on stoppe le timer de veille et on passe en statut Eteint
      state = state_Eteint;
      timeVeille = 0;
      
      // éteint immédiatement les leds si ce n'est pas déjà fait
      eteintLeds();

      if (debug) Serial.println("EteintFosse() state:enVeille -> Eteint");
      break;
    
    case state_Eteint:
      // la fosse est déjà Eteint, ça ne change pas grand chose
      
      // par acquis de conscience, on éteint les leds (censées être eteintes)
      eteintLeds();

      if (debug) Serial.println("EteintFosse() state:Eteint");
      break;

    case state_Allume:
      // La fosse est allumée, il faut démarrer la séquence d'extinction
      // et amorcer le timer d'extinction
      state = state_enExtinction;
      timeExtinction = millis()+tempsAvantExtinction*1000L;
      
      if (debug) Serial.println("EteintFosse() state:Allume -> enExtinction");
      break;

    case state_ForceAllume:
      // l'ordre d'éteindre doit être ignoré et
      // allume immédiatement les leds si ce n'est pas déjà fait
      allumeLeds();

      if (debug) Serial.println("EteintFosse() state:ForceAllume");
      break;

    case state_enExtinction:
      // l'ordre d'extinction est donné alors que la fosse se prépare à s'éteindre
      
      // il faut vérifier si le timer est échu -> phase d'extinction terminée ?
      if (timeExtinction < millis()) {
        // effectivement, le temps est écoulé, on remet le timer à 0 et on éteint tout
        timeExtinction = 0;
        state = state_Eteint;
        
        eteintLeds();
        
        if (debug) Serial.println("EteintFosse() state:enExtinction -> Eteint");
      } else {
        // le temps n'est pas écoulé, on attend avant d'éteindre
        
        if (debug) {
          Serial.print("EteintFosse() state:enExtinction millis=");
          Serial.print(millis());
          Serial.print(" timeExtinction=");
          Serial.println(timeExtinction);
        }
        
       }
      break;
      
    default:
      if (debug) { 
          Serial.print("EteintFosse() state:unknown state ");
          Serial.println(state);
      }
      // ne fait rien
      break;  
  }
}

// Allume la fosse
void AllumeFosse()
{  
  switch (state) {
    case state_enAllumage:
      // l'ordre d'allumage est donné alors que la fosse se prépare à s'allumer

      // il faut vérifier si le timer est échu -> phase d'eallumage terminée ?
      if (timeAllumage < millis()) {
        // effectivement, le temps est écoulé, on remet le timer à 0 et on allume tout
        timeAllumage = 0;
        state = state_Allume;
        allumeLeds();

        // et on amorce le timer pour le mode veille !
        timeVeille = millis() + tempsAvantVeille*1000L;
        
        if (debug) Serial.println("AllumeFosse() state:enAllumage -> Allume");
      } else {
        // le temps n'est pas écoulé, on attend avant d'allumer
        if (debug) {
          Serial.print("AllumeFosse() state:enAllumage millis=");
          Serial.print(millis());
          Serial.print(" timeAllumage=");
          Serial.println(timeAllumage);
        }
      }
      break;
      
    case state_ForceEteint:
      // éteint immédiatement les leds si ce n'est pas déjà fait
      eteintLeds();

      if (debug) Serial.println("AllumeFosse() state:ForceEteint");
      break;
      
    case state_Eteint:
       // les leds sont éteintes, il faut démarrer la séquence d'allumage
       // avec le timer d'allumage
      state = state_enAllumage;
      timeAllumage = millis()+tempsAvantAllumage*1000L;
      
      if (debug) Serial.println("AllumeFosse() state:Eteint -> enAllumage");
      break;

    case state_Allume:
      // en état allumé, nous devons vérifier l'échéance du timer de veille

      // le timer de veille est-il échu ?
      if (timeVeille<millis()) {
        // oui -> la veille doit se déclencher
        timeVeille = 0;
        state = state_enVeille;

        // on peut éteindre les leds
        eteintLeds();
        
        if (debug) Serial.println("AllumeFosse() state:Allume -> EnVeille");
      } else {
        // le timer veille n'est pas encore échu
        
        // par acquis de conscience, on allume les leds (censées être allumées)
        allumeLeds();
        
        if (debug) {
          Serial.print("AllumeFosse() state:Allume millis=");
          Serial.print(millis());
          Serial.print(" timeVeille=");
          Serial.println(timeVeille);
        }
      }
      break;

    case state_ForceAllume:
      // allume immédiatement les leds si ce n'est pas déjà fait
      allumeLeds();

      if (debug) Serial.println("AllumeFosse() state:forceAllume");
      break;

    case state_enExtinction:
      // l'ordre d'allumage est reçu alors que nous étions en phase d'extinction
      // annule la phase d'extinction
      timeExtinction = 0;
      state = state_Allume;
      
      // par acquis de conscience, on allume les leds (censées être allumées)
      allumeLeds();

      if (debug) Serial.println("AllumeFosse() state:enExtinction -> Allume");
      break;

    case state_enVeille:
      // éteint immédiatement les leds si ce n'est pas déjà fait
      eteintLeds();

      if (debug) Serial.println("AllumeFosse() state:enVeille");
      break;
      
    default:
      if (debug) { 
          Serial.print("AllumeFosse() state:unknown state ");
          Serial.println(state);
      }
      // ne fait rien
      break;  
  }
}

// AfficheEtatVal
//  affiche l'état de la FSM et un décompte représentatif
//  le mode veille affiche le double point
//

void AfficheEtatFSM(int ev) 
{
  // vérifie si la voie est sous-tension
  if (ev==voie_STOP) {
    // (5)top
    AfficheSegVal(SEG_A | SEG_C | SEG_D | SEG_F | SEG_G,0);
    return;
  }

  // sinon, affiche l'état de la FSM et de l'éventuel décompte en cours
  switch (state) {
      case state_Eteint:
        // (E)teint
        AfficheSegVal(SEG_A | SEG_G | SEG_D | SEG_E | SEG_F,0);
        break;

      case state_Allume:
        // (A)llume + décompte veille
        AfficheSegVal(SEG_A | SEG_F | SEG_B | SEG_E | SEG_C | SEG_G,(timeVeille-millis())/1000,true);
        break;

      case state_ForceEteint:
        // FE
        segments[0] = SEG_A | SEG_F | SEG_G | SEG_E ; 
        segments[1] = SEG_A | SEG_G | SEG_D | SEG_E | SEG_F ;
        segments[2] = 0x00;
        segments[3] = 0x00;
        display.setSegments(segments);
        break;

      case state_ForceAllume:
        // FA
        segments[0] = SEG_A | SEG_F | SEG_G | SEG_E ; 
        segments[1] = SEG_A | SEG_B | SEG_C | SEG_G | SEG_E | SEG_F;
        segments[2] = 0x00;
        segments[3] = 0x00;
        display.setSegments(segments);
        break;
        
      case state_enAllumage:
        // (E)teint + décompte d'allumage
        AfficheSegVal(SEG_A | SEG_G | SEG_D | SEG_E |SEG_F,(timeAllumage-millis())/1000);
        break;
        
      case state_enExtinction:
        // (A)llumé + décompte d'extinction
        AfficheSegVal(SEG_A | SEG_F | SEG_B | SEG_E | SEG_C | SEG_G,(timeExtinction-millis())/1000);
        break;
        
      case state_enVeille:
        // :
        AfficheSegVal(0,0,true);
        break;

    default:
      // (U)nknown + state
      AfficheSegVal(SEG_B | SEG_C |SEG_D | SEG_E |SEG_F,state);
      break;
  }
}

// code executé une seule fois au démarrage du module (ou après un reset)
void setup() {
  // programme les différentes Pin en entrée ou sortie
  pinMode(Pin_forcageAllume,INPUT_PULLUP);
  pinMode(Pin_forcageEteint,INPUT_PULLUP);
  
  pinMode(Pin_allumageLeds,OUTPUT);
  eteintLeds();

  // au démarrage il est probable que la voie soit STOP
  pinMode(LED_BUILTIN,OUTPUT);
  digitalWrite(LED_BUILTIN,HIGH);    
  
  // 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 !
  if (debug) Serial.begin(57600);

  // Annonce la version
  Serial.println("Fosse v1.5 - (c) Julie Dumortier - Licence GPL");

  // On démarre avec la fosse éteinte et la voie STOP
  state = state_Eteint;
  timeExtinction = 0;
  timeVeille = 0;
  timeAllumage = 0;

  // regle l'intensité de l'affichage
  display.setBrightness(debug?0x0f:0x0d);
  display.clear();

  EteintFosse();
}

// code executé en permanence (une boucle)
void loop() {
  
  int ev; // état de la voie

  // demande de forçage eteint ?
  if (digitalRead(Pin_forcageEteint)==LOW) {
    // demande d'etre eteint en permanence
    state = state_ForceEteint;
    
    if (debug) Serial.println("loop() IN: state:ForceEteint");
  } else {
    if (state==state_ForceEteint) {
      // fin du forçage eteint
      state = state_Eteint;
      
      if (debug) Serial.println("loop() state:ForceEteint -> Eteint");
    }
  }

  // demande de forçage allumé ?
  if (state!= state_ForceEteint) {
    if (digitalRead(Pin_forcageAllume)==LOW) {
      // demande d'etre allumé en permanence
      state = state_ForceAllume;
      
      if (debug) Serial.println("loop() IN: state:ForceAllume");
    } else {
      if (state==state_ForceAllume) {
        // fin du forçage allumé, amorce le timer de veille
        state = state_Allume;
        timeVeille = millis() + tempsAvantVeille*1000L;
        
        if (debug) Serial.println("loop() state:ForceAllume -> Allume");
      }
    }
  }

  ev = EtatVoie();
  switch (ev) {
    case voie_Occupee:
      // indique que la voie est sous-tension
      digitalWrite(LED_BUILTIN,LOW);    

      // déclenche la FSM d'allumage de la Fosse
      AllumeFosse();
      break;

    case voie_STOP:
      // Modifie l'état de la FSM pour demander une extinction immédiate
      state = state_Eteint;
      timeExtinction = 0;
      
      // déclenche la FSM d'extinction de la Fosse
      EteintFosse();

      // indique que la voie est STOP
      digitalWrite(LED_BUILTIN,HIGH);    
      break;
 
    case voie_Libre:
      // indique que la voie est sous-tension
      digitalWrite(LED_BUILTIN,LOW);    
      
      // déclenche la FSM d'extinction de la Fosse
      EteintFosse();
      break;
      
    default:
      if (debug) {
        Serial.print("loop() EtatVoie : unknown state =");
        Serial.println(ev);
      }
      break;
  }

  // pour avoir le temps de lire l'état de la voie
  if (debug) delay(500); 

  // affiche l'état de la FSM
  AfficheEtatFSM(ev);

  // pour avoir le temps de lire l'état de la FSM
  if (debug) delay(250); 

  // délai normal : la FSM est déclenchée 4 fois par seconde environ
  delay(250-msFiltre);

}

Pour télécharger le programme : fosse_v1.5.pdf (43,0 Ko)

Et comme d’habitude, une petite vidéo de démonstration de l’ensemble :

Ce chapitre clos la réalisation de notre fosse d’inspection. Mais le sujet n’est pas totalement clos, je travaille à une intégration propre des fosses Auhagen que je vais utiliser dans ma double remise.

Moins visible dans la remise, elles ne seront pas automatisées, seulement éclairées et fonctionnelles avec un “discret” rail minitrix en rail central.

A suivre donc …

2 « J'aime »

Chapeau bas !!!

Belle réalisation que cette fosse de maintenance.
A garder en mémoire pour un éventuel “copiage”.

Cdlt,

Claude papaciela

1 « J'aime »

Episode 4.6 - Version du coupon 24361 avec une fosse Auhagen

Je crois qu’il est temps de terminer ce tutoriel sur les fosses en voie C, enfin pour l’instant. C’est pas moins de 4 fosses différentes que j’aurais réalisé :

  • une fosse d’inspection from scratch avec un bel automatisme Arduino, objet de l’épisode 4.5 précédent,
  • le prototype initial kitbashing d’une fosse Régions & Compagnies, que j’ai amélioré pour la fosse de l’atelier moteur (vidéo à la fin de ce billet),
  • deux fosses d’entretien pour la double remise, sur la base d’un kit Auhagen référence 41612. Elles sont moins visibles dans cette remise, elles doivent surtout être fonctionnelles.

Je dois vous l’avouer, j’en ai marre des fosses ! :upside_down_face: mais j’y reviendrais plus tard, je n’ai pas abdiqué pour une solution différente pour ma fosse d’inspection, une solution sans rail central.

Pour les deux fosses d’entretien, j’ai relevé le défi de @Mulsanne : transformer en 3rails les deux fosses en moins de deux heures chrono en main :smiley:

C’est parti pour un coupon 24361 sur base Auhagen 41612 …

Je prends un coupon 24360 et mes fosses et j’en déduis précisément la longueur de plastique que je vais garder et je découpe avec la technique que j’ai déjà plusieurs fois présentée scie à métaux et on y va mollo sur la fin pour ne pas attaquer les deux rails :

Je positionne l’ensemble pour vérifier :

Attention quand vous insérez les rails dans les fixations Auhagen, elles sont très fragiles. Assurez vous que vos rails sont bien lisses.

Je ne garde qu’une extrémité en voie C puisque ce sont des coupons qui se terminent dans le fond de la remise. Mais si on veut faire une fosse d’inspection, il suffit de garder les deux extrémités et d’enlever précisément 180 mm de plastique correspondant à la longueur de la fosse Auhagen.

Maintenant on va s’occuper du rail central. Comme pour mes fosses, j’ai utilisé un rail minitrix que je démonte délicatement (le rail a tendance à se tordre facilement). Et surtout je vais garder des bouts de traverses sur lesquelles je vais découper à la pince Xuron les petites fixations que je vais utiliser ensuite :

Puis je pointe et je perce un trou pour le passage de l’alimentation qui sera positionnée au niveau d’un des deux piliers :

Je fixe mon cable rouge avec l’éclisse que j’ai récupéré et je mets un petit point de soudure :

Et je vais placer deux petits piliers pour soutenir le rail central. J’utilise des H Evergreen coupé à 8 mm de hauteur (pour une fosse qui fait 10 mm de profondeur) :

Et je teste l’ensemble avec les petites fixations et je colle à la Cyano !

Puis je pose un masque sur le rail central avant de passer en atelier peinture pour l’apprêt (une astuce qui m’a été indiquée par @Schwabisch me semble-t-il) :

En sortie de l’atelier peinture, les deux fosses Auhagen et la fosse de l’atelier moteur. On se rend bien compte de la différence … (mais ce n’est pas le même boulot !).

On retire le masque de protection du rail central :

On branche le fil rouge sur le B et hop on passe aux tests direct !

La vidéo de démonstration, les deux coupons 24361 Auhagen montés cul à cul :

On pourra y rajouter de la lumière (j’ai la flemme) en perçant des trous sur les côtés pour installer des leds. Je le ferais certainement au moment de leur intégration dans le plancher de la double remise, à suivre dans un prochain épisode.

Reste aussi à peindre et à patiner … on verra ça lors de leur intégration dans un plancher béton.

Pour clôturer cet épisode 4, je vous donne des nouvelles du prototype initial (cf épisode 4.2). J’ai légèrement amélioré la fixation du rail central, j’ai positionné l’éclisse à une extrémité et non pas contre un pilier :

Après un premier passage en peinture pour l’apprêt (la peinture définitive sera faite lors de son intégration dans le plancher de l’atelier moteur), la fidèle DHG 700 C valide complètement ce concept.

Finalement une version intéressante car bien éclairée, visuellement plutôt sympa avec une belle profondeur, très fonctionnelle mais sans aucun automatisme à ce stade. Il sera facile de greffer un nouvel Arduino ou de voir si le premier Arduino est capable de gérer les deux fosses (défi 2021 !).

La vidéo (j’ai volontairement pas monté le second bandeau de led ni branché l’éclairage … grosse flemme encore, ça sent la fin d’année :rofl:) :

THE END

3 « J'aime »

Bonjour Claude,

Avec plaisir, et n’hésites pas à me contacter sur le sujet au besoin.

Bonnes fêtes.

Et bien, tu modélise plus vite que ton ombre :astonished:

Bravo pour ces “fosses express” :smiley:

Heureux d’avoir donné un petit conseil qui se révèle pratique !

Joyeux Noël à toi. Je sens que le sapin :christmas_tree: va être garni de beaux cadeaux à faire rouler :wink:

Oh oh oh :santa:t2:

1 « J'aime »

Je crois que je vais monter un business :star_struck:. Vous m’envoyez vos fosses Auhagen et un rail minitrix et je vous retourne une fosse prête à l’emploi. Référence du coupon 24361 :rofl:

Pour le tarif, vu le prix du bout de plastique Auhagen et le prix du Kit Régions et Compagnies, je pense que je peux demander au moins la différence entre les deux kits :smiley: et je serais à 15 € de l’heure de main d’oeuvre.

:chart_with_upwards_trend:

(je plaisante bien évidemment, les fosses j’en ai suffisamment soupé !)

Oui je crois savoir qu’une V60 est sous le sapin :wink: et peut être un peu de lecture, de qui tu sais que tu apprécies particulièrement pour les décors …

Et j’espère qu’il sera bien garni pour toi aussi :smiley: !

Bonjour Julie,

Beau travail et merci pour le tuto.

Auusi, je pense en faire une un jour car c’est un plus sur un réseau.

Bonnes fêtes.

Errol.

J’ai déposé du graphite sur les rails. ça donne un effet plutôt sympa

4 « J'aime »

Bonsoir Julie,

Super tuto avec les fosses Auhagen ! ça me servira le moment venu. Mais je trouve que celle fabriquée de toute pièce pas tes soins a quand même fière allure :wink:

A+

Manu

Bonsoir Manu,

Oui je trouve aussi. Mais ce n’est pas le même usage.

Les Auhagen seront peu visibles à l’intérieur d’une double remise où je mettrais plutot en valeur l’automatisme d’ouverture des portes :slight_smile: alors que celle fabriquée de toute pièce est plus imposante (en taille et en profondeur aussi) et se trouve mise en valeur à l’extérieur.

Ceci dit, je vais quand même ajouter de la lumière à mes Auhagen (quelques leds sur les côtés) et je vais voir aussi à transformer mon programme Arduino pour qu’il soit capable de gérer plusieurs fosses simultanément :). On va passer en programmation objet avec un objet Fosse :slight_smile:

A suivre donc,

1 « J'aime »

Wahou. Sacré et beau boulot. Ca rend bien.

Episode 4.7 - Automatisme 2.1

J’ai présenté un automatisme pour gérer les séquences d’éclairage de la fosse, dans une version dite 1.5 - lire Une débutante dans le décor - Ep4 - Kitbashing d’une fosse d'inspection - #36 par Julaye

Cet automatisme a subit deux évolutions parallèles :

  • une version 2.0 qui consiste à utiliser des objets informatique et gérer ainsi plusieurs fosses avec le même Arduino. Chaque objet est initialisé avec les entrées et sorties nécessaires à son fonctionnement et gère son état interne comme l’état du rail contact associé, les différents timers …

  • une version 1.7 qui consiste à remplacer le capteur de tension par une carte opta-isolée de type DST-1R4P-N ou DST-1R8P-N - cf le Tuto6b Une débutante dans le décor - Ep6 - Quelques automatismes (Arduino Nano) - #61 par Julaye

Ce soir, j’ai décidé de fusionner les deux versions pour n’en faire qu’une seule : la version 2.1.

Cette version est paramétrée pour gérer deux fosses mais bien évidemment il est possible d’ajouter d’autres fosses, la limite étant le nombre d’entrées digitales :slight_smile:

Vous remarquerez les objets CEtatTraction et CEtatFosse, le premier étant unique et partagé, le second étant créé autant de fois que nécessaire.

// Objet pour l'état de la traction sur l'entrée D4
CEtatTraction etatTraction(4);

// Objet pour l'état de la fosse 1 (fosse inspection)
// D5 : output : allumage des bandeaux de leds (COMMON - NC)
// D3 : input : état d'occupation de la fosse (rail contact / fil bleu)
// D9 : CLK afficheur
// D8 : DIO afficheur
TM1637Display display1(9,8);
CEtatFosse etatFosse1(5,3,&display1);

// Objet pour l'état de la fosse 2 (fosse atelier moteur)
// D10 : output : allumage des bandeaux de leds (COMMON - NC)
// D2 : intput : état d'occupation de la fosse (rail contact / fil bleu)
// pas de forçage, pas d'afficheur
CEtatFosse etatFosse2(10,2,0);

Je publie ici le code source et je me tiens à la disposition des personnes intéressées qui voudraient déployer cet environnement :

fosse v2.1.pdf (47,7 Ko)

Enjoy !

Bonjour Julie, bonjour tout le monde,

Je viens de regarder l’ensemble du post. Sur le 36/47, le schéma indique que tu utilises le voltage sensor (livré avec le Nano).
Si, pour lancer un pgrm de l’Arduino une fois sur le circuit, (sans l’ordi donc), j’utilise un ILS ou un bouton poussoir(plutôt qu’un rail contact), comment je le connecte sur le Nano (avec le voltage sensor !??), à quelle pin (Analog ou Digit) et comment le déclarer sur le prgm du Nano?

Merci de l’aide,

Claude papaciela