2101
Modélisation, Architectures logicielles et matérielles / Re : Modélisation logicielle d'un réseau - le système de Pierre59
« le: mars 16, 2017, 10:56:58 pm »
Merci Denis,
La suite va t'interesser !
Maintenant je vais aborder la méthode de tests et de mise au point des méthodes particulières des objets !!!
Vous avez remarqué que le Locodrome (V4) est fourni avec un programme écrit en Processsing. Ce programme communique, via un port série de votre ordinateur, avec un Arduino (Uno, Mega, etc..) dans lequel le Gestionnaire a été téléversé (ce qui suppose au préalable que le compilateur soit content :-)).
Ce n'est pas très difficile d'arriver à ce stade où le compilateur voit un "sans faute", quand on part bien du Gestionnaire (V4) et qu'on introduit progressivement tous les objets que j'ai présenté précédemment. Mon conseil est de vérifier très souvent et de corriger les erreurs au fur et à mesure.
Donc le programme Locodrome en Processing ressemble à cela :
Et le principe des échanges entre le Locodrome Processing et le Gestionnaire Arduino est assez simple :
Dans la série des onglets du programme Arduino (Composants.h, Constantes.h, Fonctions.h, Methodes.h, Signaux.h, SignauxBal.h, TCO.h, Train.h), on remarque qu'il y en a un qui s'appelle TCO.h et qui contient cette fonction tco(byte c,byte x,byte n).
Cette fonction tco() est appelée à différents endroits du code Arduino, dans les méthodes:
Et seulement dans ces méthodes : cela correspond aux ordres qui seraient envoyés vers les organes de commande (visualisation sur un TCO, manoeuvre des signaux et des aiguilles via la formation des itinéraires).
Si on regarde maintenant la fonction tco() qui reçoit 3 arguments :
On voit que cette fonction se contente d'envoyer seulement quelques caractère "imprimables" : A pour aiguille, Z pour Zone, etc... puis un numéro, puis un code de couleur G pour gris, R pour rouge, etc...
C'est simple et cela permet au programme Locodrome Processing de réagir en affichant des changements de couleur de zone (rouge = occupée, grise = libérée, blanche = réservée pour un itinéraire), des basculements d'aiguilles, des couleurs de signaux.
Dans l'autre sens, il faut bien que le Gestionnaire réagisse aux événements du réseau virtuel simulé par le Locodrome :
Je vais laisser de coté la gestion des trains pour le moment, histoire de ne pas trop compliquer la compréhension de l'exposé, mais sachez que le Gestionnaire a quand même besoin de connaître le sens de déplacement des trains pour appliquer les règles d'itinéraires.
Pour réagir, le Gestionnaire fait une traitement dans sa loop() des caractères reçus via le port série :
C'est impressionnant de concision !
Alors la vraie question vous saute aux yeux : ces traitements des échanges pour le Locodrome ne marchent plus pour mon réseau car j'ai 47 zones, 30 signaux, 21 aiguilles, 43 itinéraires !
Pas de panique !
Je n'ai pas changé la présentation des messages dans le sens Gestionnaire -> Locodrome.
Par contre, dans le sens Locodrome -> Gestionnaire, au lieu d'utiliser une lettre de l'alphabet pour chaque d'objet (il n'y en aurait pas assez), j'ai utilisé un simple entier avec la convention suivante :
Ce que j'ai matérialisé dans cette fonction :
Mais vous avez remarqué aussi une autre GROS problème : le programme Locodrome en Processing ne correspond plus graphiquement à mon réseau
Mais comme Pierre avait tout prévu, on peut tester le gestionnaire sans le Locodrome en Processing, simplement avec les affichages dans le moniteur : c'est beaucoup moins "parlant" mais c'est utile quand même.
Voici un exemple de scenario de simulation fait entièrement avec le moniteur de l'IDE Arduino :
La première ligne "0 A13=/R E46Z4= Z6= Z39= Z7= B0=B" signifie :
Un peu plus loin "209 C4=B C3=R T9=G Z9=" signifie :
Bon c'est fastidieux, il faut le reconnaitre !
Il faut tout de même trouver une solution plus graphique : il y en a deux possibles :
La réponse est les deux mon général !
C'est ce que je vais vous présenter dans la suite ...
Stay tuned !
La suite va t'interesser !
Maintenant je vais aborder la méthode de tests et de mise au point des méthodes particulières des objets !!!
Vous avez remarqué que le Locodrome (V4) est fourni avec un programme écrit en Processsing. Ce programme communique, via un port série de votre ordinateur, avec un Arduino (Uno, Mega, etc..) dans lequel le Gestionnaire a été téléversé (ce qui suppose au préalable que le compilateur soit content :-)).
Ce n'est pas très difficile d'arriver à ce stade où le compilateur voit un "sans faute", quand on part bien du Gestionnaire (V4) et qu'on introduit progressivement tous les objets que j'ai présenté précédemment. Mon conseil est de vérifier très souvent et de corriger les erreurs au fur et à mesure.
Donc le programme Locodrome en Processing ressemble à cela :
Et le principe des échanges entre le Locodrome Processing et le Gestionnaire Arduino est assez simple :
Dans la série des onglets du programme Arduino (Composants.h, Constantes.h, Fonctions.h, Methodes.h, Signaux.h, SignauxBal.h, TCO.h, Train.h), on remarque qu'il y en a un qui s'appelle TCO.h et qui contient cette fonction tco(byte c,byte x,byte n).
Code: [Sélectionner]
// commandes du TCO, des aiguilles et des signaux
// ne sert que pour l'interface avec le TCO virtuel
/////////////////////////////////////////////////////////////////////////////
enum {CODE_AIGUILLE,CODE_ZONE,CODE_SIGNAL,CODE_CARRE,
CODE_BOUTON,CODE_BOUTON_CLI,CODE_ERREUR,CODE_INFO,CODE_CAB,CODE_MEM,CODE_TRAIN};
void tco(byte c,byte x,byte n) { byte buf[3]; // code numero info
if (TCO) { buf[0]=c; buf[1]=n; buf[2]=x; Serial.write(buf,3); return; }
switch(c) { // mise en forme pour affichage sur le moniteur serie
case CODE_AIGUILLE: Serial.print('A'); break; // manoeuvre aiguille
case CODE_ZONE: Serial.print('Z'); break; // coloration zone (sur tco)
case CODE_SIGNAL: Serial.print('S'); break; // manoeuvre signal (semaphore)
case CODE_CARRE: Serial.print('C'); break; // manoeuvre signal (carre)
case CODE_BOUTON: Serial.print('B'); break; // coloration bouton (sur tco)
case CODE_BOUTON_CLI: Serial.print('b'); break; // coloration bouton clignotant (sur tco)
case CODE_ERREUR: Serial.print('E'); break; // erreur
case CODE_INFO: Serial.print('I'); break; // info
case CODE_CAB: Serial.print('s'); break; // cabsignal
case CODE_MEM: Serial.print('M'); break; // memoire RAM disponible (borne a 4095)
case CODE_TRAIN: Serial.print('T'); break; // suivi des trains
default: Serial.print('?');
}
Serial.print(n);
if (c==CODE_ERREUR || c==CODE_INFO) return;
Serial.print('=');
if (c==CODE_AIGUILLE) { if (x) Serial.print('/'); else Serial.print('|'); }
else { //Serial.println(x);
switch(x) { // mise en forme des couleurs
case COULEUR_GRISE: Serial.print('G'); break;
case COULEUR_ROUGE: Serial.print('R'); break;
case COULEUR_BLANCHE: Serial.print('B'); break;
case COULEUR_JAUNE: Serial.print('J'); break;
case COULEUR_VERTE: Serial.print('V'); break;
case COULEUR_ROSE: Serial.print('r'); break;
default: Serial.print('?');
}
}
Serial.print(' ');
}
Cette fonction tco() est appelée à différents endroits du code Arduino, dans les méthodes:
- Aiguille::manoeuvrer()
- Zone::occuper()
- Zone::liberer()
- Signal::manoeuvrer()
- Itineraire::formation()
- Itineraire::detruire()
- Itineraire::effacer()
- Et dans les fonctions du cab-signal : signalChange() et signalVu()
Et seulement dans ces méthodes : cela correspond aux ordres qui seraient envoyés vers les organes de commande (visualisation sur un TCO, manoeuvre des signaux et des aiguilles via la formation des itinéraires).
Si on regarde maintenant la fonction tco() qui reçoit 3 arguments :
- Un code type d'objet
- Un numéro d'objet
- Une commande
On voit que cette fonction se contente d'envoyer seulement quelques caractère "imprimables" : A pour aiguille, Z pour Zone, etc... puis un numéro, puis un code de couleur G pour gris, R pour rouge, etc...
C'est simple et cela permet au programme Locodrome Processing de réagir en affichant des changements de couleur de zone (rouge = occupée, grise = libérée, blanche = réservée pour un itinéraire), des basculements d'aiguilles, des couleurs de signaux.
Dans l'autre sens, il faut bien que le Gestionnaire réagisse aux événements du réseau virtuel simulé par le Locodrome :
- Former, détruire, effaccer un itinéraire
- Occuper, libérer une zone
- Indiquer les changement de sens des trains
Je vais laisser de coté la gestion des trains pour le moment, histoire de ne pas trop compliquer la compréhension de l'exposé, mais sachez que le Gestionnaire a quand même besoin de connaître le sens de déplacement des trains pour appliquer les règles d'itinéraires.
Pour réagir, le Gestionnaire fait une traitement dans sa loop() des caractères reçus via le port série :
Code: [Sélectionner]
void loop() { Itineraire* it; char code=0;
if (Serial.available()>=1) { // test si retrosignalisation ou commande
code=Serial.read();
if (!TCO) { Serial.println(); Serial.print(code); Serial.print(':'); Serial.print(' '); }
if (code=='X') { // commande de reinitialisation
reset();
}
if (code>='0' && code <='8') { // commande d'itineraire
it=tableItineraires[code-'0'];
if (it->enAttente()) it->effacer(); else // destruction
if (it->libre()) it->formation(); else // essai de formation
if (it->forme()) it->destruction(); // essai de destruction
if (!TCO && it->enAttente()) Serial.print('m');
}
if (code>='A' && code <='F') { // occupation zone (retrosignalisation)
tableZones[code-'A']->occuper();
}
if (code>='a' && code <='f') { // liberation zone (retrosignalisation)
tableZones[code-'a']->liberer();
}
if (code=='s') train1->invSens();
if (code=='S') train2->invSens();
code=0; return;
}
// test itineraires en attente
for (int i=0; i<MaxItineraire; i++) {
it=tableItineraires[i];
if (it->enAttente()) {
if (!TCO && it->formable()) { Serial.println('('); Serial.println(i); Serial.print(')'); Serial.print(':'); Serial.print(' '); }
if (it->formable()) it->formation();
}
}
} // fin loop
C'est impressionnant de concision !
Alors la vraie question vous saute aux yeux : ces traitements des échanges pour le Locodrome ne marchent plus pour mon réseau car j'ai 47 zones, 30 signaux, 21 aiguilles, 43 itinéraires !
Pas de panique !
Je n'ai pas changé la présentation des messages dans le sens Gestionnaire -> Locodrome.
Par contre, dans le sens Locodrome -> Gestionnaire, au lieu d'utiliser une lettre de l'alphabet pour chaque d'objet (il n'y en aurait pas assez), j'ai utilisé un simple entier avec la convention suivante :
- de 0 à i (i<95) il s'agit d'une demande d'itinéraire i
- de 100 à 1xx il s'agit d'une occupation de zone du numéro xx
- de 200 à 2yy il s'agit d'une libération de zone du numéro yy
- de 300 à 30t il s'agit d'une inversion de sens du train t
Ce que j'ai matérialisé dans cette fonction :
Code: [Sélectionner]
void execCode(int c) {
int code = c;
Itineraire* it;
///////////////// TRAITEMENT ITINERAIRE ////////////
if (code>=0 && code <MaxItineraire) { // commande d'itineraire
it=tableItineraires[code];
if (it->enAttente()) it->effacer(); else // destruction
if (it->libre()) it->formation(); else // essai de formation
if (it->forme()) it->destruction(); // essai de destruction
if (!TCO && it->enAttente()) Serial.print('m');
}
///////////////// TRAITEMENT OCCUPATION ////////////
if (code>=100 && code <100+MaxZone) { // occupation zone (retrosignalisation)
tableZones[code-100]->occuper();
}
///////////////// TRAITEMENT LIBERATION ////////////
if (code>=200 && code <200+MaxZone) { // liberation zone (retrosignalisation)
tableZones[code-200]->liberer();
}
///////////////// INVERSION DE SENS ////////////
if (code==300) train1->invSens();
if (code==301) train2->invSens();
return;
}
Mais vous avez remarqué aussi une autre GROS problème : le programme Locodrome en Processing ne correspond plus graphiquement à mon réseau
Mais comme Pierre avait tout prévu, on peut tester le gestionnaire sans le Locodrome en Processing, simplement avec les affichages dans le moniteur : c'est beaucoup moins "parlant" mais c'est utile quand même.
Voici un exemple de scenario de simulation fait entièrement avec le moniteur de l'IDE Arduino :
Code: [Sélectionner]
0 A13=/R E46Z4= Z6= Z39= Z7= B0=B
4 A7=/R A6=/R C11=? C6=? Z11= Z12= Z43= Z14= B4=B
104 E202Z4=
106 E46T6=? Z6=
139 T39=? Z39=
107 T7=? Z7=
204 T4=G Z4=
206 Z4= Z6= B0=G T6=G Z6=
239 T39=G Z39=
108 C3=V T8=? Z8=
207 T7=G Z7=
109 C4=V T9=? Z9=
208 C3=B T8=G Z8=
110 C5=V T10=? Z10=
209 C4=B C3=R T9=G Z9=
111 C6=V T11=? Z11=
210 C5=B C4=R T10=G Z10=
112 C11=? T12=? Z12=
143 T43=? Z43=
114 T14=? Z14=
211 C6=B C5=R T11=G Z11=
212 Z11= Z12= B4=G T12=G Z12=
243 T43=G Z43=
6 A5=/R A4=/R C13=B Z42= Z15= Z16= B6=B
La première ligne "0 A13=/R E46Z4= Z6= Z39= Z7= B0=B" signifie :
- 0 : demande d'itinéraire n° 0
- A13=/ : manoeuvre de l'aiguille 13 en position déviée
Un peu plus loin "209 C4=B C3=R T9=G Z9=" signifie :
- 209 : libération de la zone 9
- C4=B : le signal C4 allume le feu blanc
- C3=R : le signal C3 allume le feu rouge
Bon c'est fastidieux, il faut le reconnaitre !
Il faut tout de même trouver une solution plus graphique : il y en a deux possibles :
- Développer un moteur graphique dans le gestionnaire (ou un module séparé, via le bus CAN)
- Développer un "Locodrome" conforme à mon réseau
La réponse est les deux mon général !
C'est ce que je vais vous présenter dans la suite ...
Stay tuned !