2251
Les réseaux / Re : Projet Dominique
« le: juillet 21, 2017, 07:46:50 pm »
Je reprends doucement la description de mon réseau !
Nous en étions aux détecteurs d'occupation qui sont reliés, chez moi, au TCO physique. J'avais aussi parlé du module de commandes d'aiguilles, du module de traction et du gestionnaire.
Au départ je n'avais pas idée de la manière de gérer l'ensemble du réseau par un gestionnaire, je ne soupçonnais pas l'étendue de la complexité et le nombre de choses à relier ensemble.
C'est pour cela que le découpage en modules reliés par un bus CAN m'a semblé idéal.
Pour mettre les idées en place, les rôles du module TCO physique (avec des leds et des clés) devait :
Il a donc fallu définir un certain nombre de messages CAN comme ceci :
Id CAN en Reception :
Je reviendrai plus loin sur les valeurs des octets de message qui suivent l'ID (maximum 8 octets, je n'utilise qu'un seul octet en général).
Le choix des messages CAN est très structurant pour le projet. Mon choix n'est pas le seul possible, il faut bien choisir un jour. Car cela définit les filtres CAN, les fonctions d'émission et réception et le traitement des messages reçus (parsing en anglais, mot qui revient souvent sur Locoduino), que l'on retrouvera partout dans les modules du réseau.
J'ai donc :
Une routine d'interruption qui se charge de récupérer tous les messages CAN acceptés dans une mémoire tampon :
Et le traitement des messages CAN dans la loop :
Les clés et les zones sont décrites sous forme d'objets comme on peut le voir dans le traitement ci-dessus.
Ma premiere réalisation (toujours en place sur le réseau) se limitait à 19 aiguilles (dont 2 TJD) donc avec 19 clés. Mon plan de découpage en zones se limitait à 42 zones.
Il se trouve que la prise en compte des signaux, des itinéraires, les possibilités de manoeuvres offertes par le Gestionnaire que j'avais un peu de mal à appréhender par manque d'expérience, sont devenus maintenant beaucoup plus clairs grâce à l'aide de Pierre59.
Cela a entrainé un certain nombre de modifications qui ne remettent pas en cause les développements matériels et logiciels que j'avais fait, grâce au découpage en modules et aux communications CAN.
Je reviendrai donc sur ces évolutions après la description du TCO.
Nous en étions aux détecteurs d'occupation qui sont reliés, chez moi, au TCO physique. J'avais aussi parlé du module de commandes d'aiguilles, du module de traction et du gestionnaire.
Au départ je n'avais pas idée de la manière de gérer l'ensemble du réseau par un gestionnaire, je ne soupçonnais pas l'étendue de la complexité et le nombre de choses à relier ensemble.
C'est pour cela que le découpage en modules reliés par un bus CAN m'a semblé idéal.
Pour mettre les idées en place, les rôles du module TCO physique (avec des leds et des clés) devait :
- représenter l'ensemble du réseau de façon simple
- récupérer les occupations et allumer une led rouge dans la zone de la détection
- permettre de commander les aiguilles
- visualiser le sens droit ou dévié de chaque aiguille par une led verte allumée du bon coté
- envoyer des messages au gestionnaire à chaque changement d'occupation ou de libération
- envoyer des messages au gestionnaire à chaque changement de clé d'aiguille
- recevoir des messages du gestionnaire pour allumer les leds d'aiguille
Il a donc fallu définir un certain nombre de messages CAN comme ceci :
Id CAN en Reception :
- Id = 20H (commande de led clef)
- Id = 21H (demande d'état de toutes les clefs)
- Id = 11H (clef d'aiguille)
- Id = 10H (occupations)
Je reviendrai plus loin sur les valeurs des octets de message qui suivent l'ID (maximum 8 octets, je n'utilise qu'un seul octet en général).
Le choix des messages CAN est très structurant pour le projet. Mon choix n'est pas le seul possible, il faut bien choisir un jour. Car cela définit les filtres CAN, les fonctions d'émission et réception et le traitement des messages reçus (parsing en anglais, mot qui revient souvent sur Locoduino), que l'on retrouvera partout dans les modules du réseau.
J'ai donc :
Une routine d'interruption qui se charge de récupérer tous les messages CAN acceptés dans une mémoire tampon :
Code: [Sélectionner]
/*
* ISR CAN
*/
void MCP2515_ISR()
{
Flag_Recv = 1;
}
/*
* Routine de récuperation des messages CAN dans la memoire circulaire _Circule
* appelee par LOOP lorsque Flag_Recv = 1;
*/
void CAN_recup()
{
unsigned char len = 0; // nombre d'octets du message
unsigned char buf[8]; // message
unsigned char Id; // Id
while (CAN_MSGAVAIL == CAN.checkReceive()) {
CAN.readMsgBuf(&len, buf); // read data, len: data length, buf: data buf
Id = CAN.getCanId();
if ((_Ncan+len+2) < sizeof(_Circule)) { // il reste de la place dans _Circule
_Circule[_indexW] = Id; // enregistrement de Id
_indexW++;
_Ncan++;
if (_indexW == sizeof(_Circule)) {_indexW = 0;}
_Circule[_indexW] = len; // enregistrement de len
_indexW++;
_Ncan++;
if (_indexW == sizeof(_Circule)) {_indexW = 0;}
for (byte z = 0; z<len; z++) {
_Circule[_indexW] = buf[z]; // enregistrement du message
_indexW++;
_Ncan++;
if (_indexW == sizeof(_Circule)) {_indexW = 0;}
}
} else {
_CANoverflow = 1; // depassement de la capacite de Circule
// message perdu (pas enregistré dans Circule)
}
}
}
Et le traitement des messages CAN dans la loop :
Code: [Sélectionner]
/*
* traitement des messages dans le buffer _Circule
*/
while (_Ncan > 2) { // messages dans _Circule : au moins 3 bytes
//digitalWrite(LedV, HIGH); // led activité CAN reste allumée jusqu'à loop suivante
_Ncan--;
RId = _Circule[_indexR]; // recup Id
_indexR++;
if (_indexR == sizeof(_Circule)) {_indexR = 0;}
_Ncan--;
Rlen = _Circule[_indexR]; // recup longueur
_indexR++;
if (_indexR == sizeof(_Circule)) {_indexR = 0;}
if (_dumpCan) {
Serial.print("CAN id ");
Serial.print(RId);
Serial.print(", data ");
}
for (int k = 0; k < Rlen; k++) {
_Ncan--;
Rbuf[k] = _Circule[_indexR]; // recup octets message
_indexR++;
if (_indexR == sizeof(_Circule)) {_indexR = 0;}
if (_dumpCan) {
Serial.print("0x");
Serial.println(Rbuf[k], HEX);
}
} // le message est dans les globales RId, Rlen et Rbuf[..]
curCLEF = Rbuf[0] & 0x3F; // garder que les bits 0..5 = index aiguille
if (RId == RId_TCO_Clef) {
// 1 octet donnees: bit 7,6 -> 1,1 et 5..0 -> 3F = envoi etats toutes clefs
if (curCLEF == 0x3F) { // commande de lecture etats
if (bitRead(Rbuf[0], 7)) {
if (bitRead(Rbuf[0], 6)) { // demande etat toutes clefs (data = 0xFF)
EnvoiCAN_toutesClefs();
}
}
}
}
if (RId == RId_TCO_Led) {
// 1 octet donnees: bit 7,6 -> 0,0 = devie ou 0,1 = droit, bits 5..0 = numero clef
if (!bitRead(Rbuf[0], 7)) { // bit 7=0, commande de positionnement de Led sur une Clef d'aiguille
if (curCLEF < MaxCLES) { // numero de clef
ListeClef[curCLEF].LedUpdate(bitRead(Rbuf[0], 6)); // bit 6 = position
//affiche_vertes(); // affichage vertes + rouges plus loin
if (_dumpCan) {
Serial.print(" CAN : curCLEF ");Serial.print(curCLEF);
Serial.print(" Aiguille "); Serial.print(ListeClef[curCLEF].NomClef());
if (bitRead(Rbuf[0], 6)) {
Serial.println(" DROIT");
} else {
Serial.println(" DEVIE");
}
}
}
}
} // fin changement leds aiguilles
} // fin traitement messages CAN (while)
Les clés et les zones sont décrites sous forme d'objets comme on peut le voir dans le traitement ci-dessus.
Ma premiere réalisation (toujours en place sur le réseau) se limitait à 19 aiguilles (dont 2 TJD) donc avec 19 clés. Mon plan de découpage en zones se limitait à 42 zones.
Il se trouve que la prise en compte des signaux, des itinéraires, les possibilités de manoeuvres offertes par le Gestionnaire que j'avais un peu de mal à appréhender par manque d'expérience, sont devenus maintenant beaucoup plus clairs grâce à l'aide de Pierre59.
Cela a entrainé un certain nombre de modifications qui ne remettent pas en cause les développements matériels et logiciels que j'avais fait, grâce au découpage en modules et aux communications CAN.
Je reviendrai donc sur ces évolutions après la description du TCO.