Avant d'être dithyrambique avec Jean-Luc, je vais présenter ma solution pour cette gare.
En PJ, la gare numérotée.
Je considère un numéro par canton et un autre numéro par aiguille simple.
Une aiguille triple, c'est deux aiguilles qui se suivent et une TJD, deux aiguilles dos à dos.
Voilà donc la structure de table de ce circuit :
struct canton
{
byte precedent;
byte courant;
byte suivant_TD;
byte suivant_DV;
boolean occupation;
boolean sens_train;
byte pos_aig; // La position d'aiguille n'est pas boolean : il y a 3 positions.
byte suivant_trigo;
byte suivant_horaire;
byte feu_trigo;
byte feu_horaire;
}
Table_Cantons [] =
{ { 100, 1, 3, 2, false,false,2,0,0,0,0},
{ 1, 2,104, 9, false,false,3,0,0,0,0},
{ 105, 3, 0, 1, false,false,2,0,0,0,0},
{ 105, 4,106, 5, false,false,1,0,0,0,0},
{ 108, 5, 6, 4, false,false,1,0,0,0,0},
{ 5, 6,104, 7, false,false,1,0,0,0,0},
{ 103, 7,107, 6, false,false,1,0,0,0,0},
{ 9, 8,103,102, false,false,1,0,0,0,0},
{ 8, 9,101, 2, false,false,3,0,0,0,0},
{ 1,100,109, 0, true, true,0,0,0,0,0},
{ 9,101, 0, 0, false,false,0,0,0,0,0},
{ 0,102, 8, 0, false,false,0,0,0,0,0},
{ 7,103, 8, 0, false,false,0,0,0,0,0},
{ 6,104, 2, 0, false,false,0,0,0,0,0},
{ 4,105, 3, 0, true, true,0,0,0,0,0},
{ 0,106, 4, 0, false,false,0,0,0,0,0},
{ 0,107, 7, 0, false,false,0,0,0,0,0},
{ 0,108, 5, 0, false,false,0,0,0,0,0},
{ 100,109, 99, 0, false,false,0,0,0,0,0},
};
Évidemment, un objet C++ serait plus approprié, mais c'est ma prochaine étape.
Je décris mon processus de construction de la table :
ligne 0 = aiguille 1 :
Le precedent de l'aiguille 1, c'est le canton 100.
Le suivant_TD, c'est l'aiguille 3.
Le suivant_DV, c'est l'aiguille 2.
Et après, tout est à vide (pas là, mais on en reparlera).
On ne tient pas compte des sens pour l'instant;
Arrivent les cantons purs qui démarrent arbitrairement à 100.
Pour des questions de rapidité d'exécution, certains traitement ne concernent QUE les cantons (les feux, par exemple).
Donc on met les aiguilles avant les cantons dans la table.
Si c'étaient des objets, je pense qu'on pourrait se passer de cette "contrainte"
Les cantons sont orientés : sens_H (sens horaire). Ici, on décidera que le sens horaire est de gauche à droite.
Le canton 105 est donc encadré par 3 et 4, comme vous le voyez.
On repère facilement un canton au fait qu'il n'a pas de suivant_DV.
Pour le canton 100, j'ai dû inventer (on n'a pas tout le réseau).
Puis vient la table des itinéraires FORMES. Je n'ai jamais besoin de la description de tous les itinéraires possibles. Juste de ceux qui sont existants (formés).
Décrit tous les itinéraires formés. C'est une table résultat.
Table_Iti doit toujours être décrite dans le sens trigo, par définition
Colonne 0 = Canton départ
Colonne 1 = Aiguille 1
Colonne 2 = Aiguille 2
Colonne 3 = Aiguille 3
Colonne 4 = Aiguille 4
Colonne 5 = Aiguille 5
Colonne 6 = Aiguille 6
Colonne 7 = Aiguille 7
Colonne 8 = Aiguille 8
Colonne 9 = Aiguille 9
Colonne 10 = Aiguille 10
Colonne 11 = Aiguille 11
Colonne 12 = Aiguille 12
Colonne 13 = Aiguille 13
Colonne 14 = Aiguille 14
Colonne 15 = Aiguille 15
Colonne 16 = Canton arrivée
Colonne 17 = Ralenti : 1 = pas de ralenti, 2 = ralenti 60 km/h, 3 = ralenti 30 km/h
*/
byte Table_Iti [][18] =
{ { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
};
Pas dure à remplir ...
Vous noterez la dernière colonne qui donne la valeur de ralenti de l'itinéraire.
Je m'explique :
Si, dans un itinéraire, toutes les aiguilles sont TD, c'est à 1 et le train n'a aucune raison de ralentir.
Si, dans un itinéraire, une, au moins, des aiguilles est à 2, il ne faudra pas dépasser le 60 km/h.
Si, dans un itinéraire, une, au moins, des aiguilles est à 3, il ne faudra pas dépasser le 30 km/h.
D'où le fait que la carte d'aiguilles doit, en fournissant l'info TD/DV, qu'elle précise si c'est un ralenti 60 ou 30 km/h.
Cette info est "en dur" dans la carte et ne dépend que de la configuration physique de l'aiguilles.
La carte envoie donc 1 ou 2, ou alors 1 ou 3.
Et, avec ça, l'Arduino central se débrouille.
Comme je n'ai pas de réseau, j'ai rempli la Table_Cantons avec mes petites mimines la colonne pos.aig
De même, j'ai simulé 2 cantons occupés et leur sens : 100 et 105.
Sinon, c'est le réseau qui envoie ces informations, évidemment.
Dernière table, la table des trains :
struct train
{
byte canton__2;
boolean occupation__2;
byte canton__1;
boolean occupation__1;
byte canton_0;
boolean occupation_0;
boolean sens_0;
byte canton_1;
boolean occupation_1;
byte canton_2;
boolean occupation_2;
byte erreur;
byte feu;
}
Table_Trains [] =
{ { 0,false,0,false,0,false,false,0,false,0,false,0,0},
{ 0,false,0,false,0,false,false,0,false,0,false,0,0},
{ 0,false,0,false,0,false,false,0,false,0,false,0,0},
{ 0,false,0,false,0,false,false,0,false,0,false,0,0},
{ 0,false,0,false,0,false,false,0,false,0,false,0,0},
{ 0,false,0,false,0,false,false,0,false,0,false,0,0},
{ 0,false,0,false,0,false,false,0,false,0,false,0,0},
{ 0,false,0,false,0,false,false,0,false,0,false,0,0},
{ 0,false,0,false,0,false,false,0,false,0,false,0,0},
{ 0,false,0,false,0,false,false,0,false,0,false,0,0},
{ 0,false,0,false,0,false,false,0,false,0,false,0,0},
{ 0,false,0,false,0,false,false,0,false,0,false,0,0},
{ 0,false,0,false,0,false,false,0,false,0,false,0,0},
{ 0,false,0,false,0,false,false,0,false,0,false,0,0},
{ 0,false,0,false,0,false,false,0,false,0,false,0,0},
{ 0,false,0,false,0,false,false,0,false,0,false,0,0},
{ 0,false,0,false,0,false,false,0,false,0,false,0,0},
{ 0,false,0,false,0,false,false,0,false,0,false,0,0},
{ 0,false,0,false,0,false,false,0,false,0,false,0,0},
{ 0,false,0,false,0,false,false,0,false,0,false,0,0},
{ 0,false,0,false,0,false,false,0,false,0,false,0,0},
{ 0,false,0,false,0,false,false,0,false,0,false,0,0},
{ 0,false,0,false,0,false,false,0,false,0,false,0,0},
{ 0,false,0,false,0,false,false,0,false,0,false,0,0},
{ 0,false,0,false,0,false,false,0,false,0,false,0,0},
{ 0,false,0,false,0,false,false,0,false,0,false,0,0},
{ 0,false,0,false,0,false,false,0,false,0,false,0,0},
{ 0,false,0,false,0,false,false,0,false,0,false,0,0},
{ 0,false,0,false,0,false,false,0,false,0,false,0,0},
{ 0,false,0,false,0,false,false,0,false,0,false,0,0},
{ 0,false,0,false,0,false,false,0,false,0,false,0,0},
{ 0,false,0,false,0,false,false,0,false,0,false,0,0},
{ 0,false,0,false,0,false,false,0,false,0,false,0,0},
{ 0,false,0,false,0,false,false,0,false,0,false,0,0},
{ 0,false,0,false,0,false,false,0,false,0,false,0,0},
{ 0,false,0,false,0,false,false,0,false,0,false,0,0},
{ 0,false,0,false,0,false,false,0,false,0,false,0,0},
{ 0,false,0,false,0,false,false,0,false,0,false,0,0},
{ 0,false,0,false,0,false,false,0,false,0,false,0,0},
{ 0,false,0,false,0,false,false,0,false,0,false,0,0},
};
Pas dure à remplir non plus ...
Le but est d'avoir deux cantons d'avance dans chaque sens.
Règle empirique de nommage :
Cn+1 se dit Cn__1
Cn-1 se dit Cn_1
Enfin, dans la Table_Cantons, les feux se calculent en fonction de tout ça, dans les 2 sens (horaire et trigo).
Je suis tout à fait d'accord avec Jean-Luc sur le fait que l'installation de feux à côté des rails est cosmétique. On n'en mets pas dans les gares cachées, etc...
Il n'en reste pas moins que le fait de calculer les feux, partout, dans les 2 sens, permet de donner une consigne de vitesse maxi du canton.
Et des vitesses maxi, dans une zone cachée, ça peut servir
Feux gérés :
/* Gestion des feux : on envoie à l'Arduino du canton un code sur 4 bits. C'est lui qui gèrera l'affichage effectif
| code pgm | code bus |------| | allumage feu
| | | 07 | |
| | |------| | |
VL fixe (Voie Libre, vert ou blanc suivant l'endroit où il est implanté) | 1 | 01 | 06 06 | | 03 ou 04
A fixe (Avertissement) | 2 | 02 | | | 01
S fixe (Sémaphore) | 8 | 03 | 05 07 | | 02
C fixe (Carré, rouge ou violet suivant l'endroit où il est implanté) | 9 | 04 | |------| | 05
VL fixe + R clignotant (Voie Libre + Ralentissement 60) | 11 | 05 | 04 | | 03 et 06
A fixe + R clignotant (Avertissement + Ralentissement 60) | 12 | 06 | | | 01 et 06
VL fixe + R fixe (Voie Libre + Ralentissement 30) | 21 | 07 | 03 | | 03 et 06
A fixe + R fixe (Avertissement + Ralentissement 30) | 22 | 08 | | | 01 et 06
VL fixe + RR clignotant (Voie Libre et Rappel de Ralentissement 60) | 101 | 09 | 02 | | 03 et 07
A fixe + RR clignotant (Avertissement et Rappel de Ralentissement 60) | 102 | 10 | | | 01 et 07
VL fixe + RR fixe (Voie Libre + Rappel de Ralentissement 30) | 201 | 11 | 01 | | 03 et 07
A fixe + RR fixe (Avertissement + Rappel de Ralentissement 30) | 202 | 12 |------| | 01 et 07
*/
Il ne vous reste plus qu'à tester le .ino joint et d'analyser ce qui sort des Serial.print.
Moyennant quoi, je reste épaté par la souplesse de la proposition de Jean-Luc.
Et ça affiche un magnifique schéma.
Passer en objets C++ devrait fortement améliorer ma solution.