Voir les contributions

Cette section vous permet de consulter les contributions (messages, sujets et fichiers joints) d'un utilisateur. Vous ne pourrez voir que les contributions des zones auxquelles vous avez accès.


Messages - Dominique

Pages: 1 ... 139 140 [141] 142 143 ... 169
2101
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).

// 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 :

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 :

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 :

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 !

2102
Je vais ici reprendre l'exemple de la mise en oeuvre du gestionnaire de Pierre dans mon réseau.

La description que je vais faire est et sera complétée par mon autre fil http://forum.locoduino.org/index.php?topic=290.0 consacré à mon projet global.

Une petite introduction est cependant nécessaire : Lorsque j'ai commencé la construction de mon réseau, j'étais loin de comprendre comment j'allais arriver à réaliser le gestionnaire. J'ai donc commencé par la réalisation d'un module de traction, puis d'un module de commandes d'aiguilles puis d'un module TCO qui gère les occupations  et les aiguilles. Le gestionnaire était ptévu sous la forme d'un Arduino Due relié aux autres (tous des Arduino Mega) via un bus CAN.

Avec ces modules je peux faire tourner mes trains manuellement sans sécurité (sans cantonnement), sans signaux, sans itinéraires.

Mon gestionnaire a commencé par intégrer un module graphique qui sert à visualiser des tas de choses qui me servent à comprendre où je vais !
Il y  en a un exemple au début de ce fil, lorsque j'ai intégré les zones selon Pierre.

Après le 4ème article du gestionnaire de Pierre, j'ai donc décidé d'intégrer la totalité des ressources qui sont permises, tout simplement en partant de son exemple du Locodrome et en y greffant mes zones, mes aiguilles, mes signaux, mes itinéraires :

Pour les zones, voici un exemple de classe dérivée de la classe de base Zone :

// 6 sortie GC Hor (pair=7, impair=5+aiguilleNdevié=4)
class Z6 : public Zone {
public:
  Z6(int n,Signal* sp,Signal* si):Zone(n,sp,si) {}// constructeur
  virtual Zone* suivantePaire();
  virtual Zone* suivanteImpaire();
  virtual void actions();
  virtual void desactions();
};

J'en ai 47 comme ça, toutes (presque) identiques (parfois sans les methodes actions() et desaction()) !

Pour les signaux, voici quelques exemples de classes dérivées :

class S5:public SemaphoreBAL {
public:
  S5(int n):SemaphoreBAL(n) {} // constructeur mini
  virtual Signal* suivant();
  virtual Signal* precedent();
  virtual boolean cantonOccupe();
};

class CRR3:public CarreAvertissementRappelRalentissement {
public:
  CRR3(int n):CarreAvertissementRappelRalentissement(n) {} // constructeur mini
  virtual Signal* suivant();
  virtual Signal* precedent();
  virtual boolean ralentissement30();
};

class CV1:public CarreViolet {
public:
  CV1(int n):CarreViolet(n) {} // constructeur mini
  virtual Signal* suivant();
  virtual Signal* precedent();
};

J'en ai 30 comme ça, avec pas mal de types de signaux, ce qui n'était pas évident vu mes lacunes en signalisation SNCF (j'ai appris depuis) !!

Pour les itinéraires, voici un exemple de classe dérivée :

//X27a30 = de z27 à z30 avec Carré C1
class X27a30:public Itineraire {
public:
  X27a30(int n):Itineraire(n) {}
  virtual boolean formable();
  virtual void former();
  virtual boolean deformable();
  virtual void deformer();
  virtual void tracer(boolean b);
};

J'en ai 43 comme ça, toutes identiques (seul le nom change)  !

Ensuite je déclare les objets réels :

// declarations des objets réels

SignalBAL* s1=new S1(0);
SignalBAL* s2=new S2(1);
SignalBAL* s3=new S3(2);
SignalBAL* sr4=new SR4(3);
SignalBAL* s5=new S5(4);
SignalBAL* s6=new S6(5);
SignalBAL* s7=new S7(6);
SignalBAL* sr8=new SR8(7);
Signal* c1=new C1(8);
Signal* c2=new C2(9);
Signal* c4=new C4(10);
Signal* crr2=new CRR2(11);
Signal* crr4=new CRR4(12);
Signal* c3=new C3(13);
Signal* c5=new C5(14);
Signal* c6=new C6(15);
Signal* c7=new C7(16);
Signal* c8=new C8(17);
Signal* cr1=new CR1(18);
Signal* cr2=new CR2(19);
Signal* crr1=new CRR1(20);
Signal* crr3=new CRR3(21);
Signal* cv1=new CV1(22);
Signal* cv2=new CV2(23);
Signal* cv3=new CV3(24);
Signal* cv4=new CV4(25);
Signal* cv5=new CV5(26);
Signal* cv6=new CV6(27);
Signal* cv7=new CV7(28);
Signal* cv8=new CV6(29);

#define MaxSignal 30

Signal* tableSignaux[MaxSignal] {s1,s2,s3,sr4,s5,s6,s7,sr8,c1,c2,c4,crr2,crr4,c3,c5,c6,
  c7,c8,cr1,cr2,crr1,crr3,cv1,cv2,cv3,cv4,cv5,cv6,cv7,cv8}; // la table des signaux

/////////////////// DECLARATIONS des ZONES ////////////////////

Zone* z0=new Z0(0,NULL,NULL); // n° / signal-pair / signal-impair
Zone* z1=new Z1(1,NULL,NULL);
Zone* z2=new Z2(2,NULL,NULL);
Zone* z3=new Z3(3,NULL,NULL);
Zone* z4=new Z4(4,c7,NULL);
Zone* z5=new Z5(5,c6,NULL);
Zone* z6=new Z6(6,NULL,NULL);
Zone* z7=new Z7(7,s5,NULL);
Zone* z8=new Z8(8,s6,s5);
Zone* z9=new Z9(9,s7,s6);
Zone* z10=new Z10(10,sr8,s7);
Zone* z11=new Z11(11,crr4,sr8);
Zone* z12=new Z12(12,NULL,NULL);
Zone* z13=new Z13(13,c4,c8); // c8 ou NULL ?
Zone* z14=new Z14(14,c5,c5); // c5 ou NULL ?
Zone* z15=new Z15(15,NULL,NULL);
Zone* z16=new Z16(16,crr3,cv5); // cv5 ou NULL ?
Zone* z17=new Z17(17,NULL,NULL);
Zone* z18=new Z18(18,NULL,cv3);
Zone* z19=new Z19(19,NULL,NULL);
Zone* z20=new Z20(20,NULL,NULL);
Zone* z21=new Z21(21,NULL,NULL);
Zone* z22=new Z22(22,NULL,cr1);
Zone* z23=new Z23(23,NULL,cr2);
Zone* z24=new Z24(24,NULL,NULL);
Zone* z25=new Z25(25,NULL,crr2);
Zone* z26=new Z26(26,NULL,NULL);
Zone* z27=new Z27(27,NULL,c1);
Zone* z28=new Z28(28,cv1,c2);
Zone* z29=new Z29(29,NULL,NULL);
Zone* z30=new Z30(30,cv6,s1);
Zone* z31=new Z31(31,s1,s2);
Zone* z32=new Z32(32,s2,s3);
Zone* z33=new Z33(33,s3,sr4);
Zone* z34=new Z34(34,sr4,crr1);
Zone* z35=new Z35(35,NULL,NULL);
Zone* z36=new Z36(36,NULL,cv2);
Zone* z37=new Z37(37,cv7,cv8);
Zone* z38=new Z38(38,cv4,NULL);
Zone* z39=new Z39(39,NULL,NULL);
Zone* z40=new Z40(40,NULL,NULL);
Zone* z41=new Z41(41,NULL,NULL);
Zone* z42=new Z42(42,NULL,NULL);
Zone* z43=new Z43(43,NULL,NULL);
Zone* z44=new Z44(44,NULL,NULL);
Zone* z45=new Z45(45,NULL,NULL);
Zone* z46=new Z46(46,NULL,NULL);

#define MaxZone  47

Zone* tableZones[MaxZone]=  {   // liste des pointeurs de zone pour la retrosignalisation
    z0, z1, z2, z3, z4, z5, z6, z7, z8, z9, z10, z11, z12, z13, z14, z15,
    z16, z17, z18, z19, z20, z21, z22, z23, z24, z25, z26, z27, z28, z29, z30,
    z31, z32, z33, z34, z35, z36, z37, z38, z39, z40, z41, z42, z43, z44, z45, z46  };

/////////////////// DECLARATIONS des AIGUILLES //////////////////// 
 
Aiguille* a0=new Aiguille(0,z26);  //dans z26
Aiguille* a1=new Aiguille(1,z26);  //dans z26
Aiguille* a2=new Aiguille(2,z15);  //dans z15
Aiguille* a3=new Aiguille(3,z44);  //dans z44
Aiguille* a4=new Aiguille(4,z15);  //dans z15
Aiguille* a5=new Aiguille(5,z42);  //dans z42
Aiguille* a6=new Aiguille(6,z43);  //dans z43
Aiguille* a7=new Aiguille(7,z12);  //dans z12
Aiguille* a8=new Aiguille(8,z12);  //dans z12
Aiguille* a9=new Aiguille(9,z29);  //dans z29
Aiguille* a10=new Aiguille(10,z38); //dans z38
Aiguille* a11=new Aiguille(11,z29); //dans z29
Aiguille* a12=new Aiguille(12,z38); //dans z38
Aiguille* a13=new Aiguille(13,z39); //dans z39
Aiguille* a14=new Aiguille(14,z35); //dans z35
Aiguille* a15=new Aiguille(15,z2); //dans z2
Aiguille* a16=new Aiguille(16,z6); //dans z6
Aiguille* a17=new Aiguille(17,z17); //dans z17
Aiguille* a18=new Aiguille(18,z24); //dans z24
Aiguille* a19=new Aiguille(19,z45); //dans z45 coté pair
Aiguille* a20=new Aiguille(20,z46); //dans z46 coté impair

#define MaxAig  21

Aiguille* tableAiguilles[MaxAig]= {
  a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11,
  a12, a13, a14, a15, a16, a17, a18, a19, a20 };

/////////////////

Itineraire *x4a7=new X4a7(0);
Itineraire *x5a7=new X5a7(1);
Itineraire *x7a11=new X7a11(2);
Itineraire *x11a13=new X11a13(3);
Itineraire *x11a14=new X11a14(4);
Itineraire *x13a16=new X13a16(5);
Itineraire *x14a16=new X14a16(6);
Itineraire *x16a4=new X16a4(7);
Itineraire *x16a5=new X16a5(8);
Itineraire *x22a25=new X22a25(9);
Itineraire *x23a25=new X23a25(10);
Itineraire *x25a27=new X25a27(11);
Itineraire *x25a28=new X25a28(12);
Itineraire *x27a30=new X27a30(13);
Itineraire *x28a30=new X28a30(14);
Itineraire *x30a34=new X30a34(15);
Itineraire *x34a22=new X34a22(16);
Itineraire *x34a23=new X34a23(17);
Itineraire *x28a36=new X28a36(18);
Itineraire *x36a28=new X36a28(19);
Itineraire *x14a18=new X14a18(20);
Itineraire *x18a14=new X18a14(21);
Itineraire *x14a38=new X14a38(22);
Itineraire *x38a14=new X38a14(23);
Itineraire *x13a30=new X13a30(24);
Itineraire *x14a30=new X14a30(25);
Itineraire *x25a13=new X25a13(26);
Itineraire *x25a14=new X25a14(27);
Itineraire *x14a11=new X14a11(28);
Itineraire *x13a11=new X13a11(29);
Itineraire *x16a13=new X16a13(30);
Itineraire *x16a14=new X16a14(31);
Itineraire *x30a27=new X30a27(32);
Itineraire *x30a28=new X30a28(33);
Itineraire *x4a3=new X4a3(34);
Itineraire *x3a4=new X3a4(35);
Itineraire *x3a1=new X3a1(36);
Itineraire *x30a13=new X30a13(37);
Itineraire *x30a14=new X30a14(38);
Itineraire *x37a18=new X37a18(39);
Itineraire *x18a37=new X18a37(40);
Itineraire *x37a38=new X37a38(41);
Itineraire *x38a37=new X38a37(42);

#define MaxItineraire 43

Itineraire* tableItineraires[MaxItineraire] {
    x4a7,x5a7,x7a11,x11a13,x11a14,x13a16,x14a16,x16a4,x16a5,x22a25,
    x23a25,x25a27,x25a28,x27a30,x28a30,x30a34,x34a22,x34a23,x28a36,x36a28,
    x14a18,x18a14,x14a38,x38a14,x13a30,x14a30,x25a13,x25a14,x14a11,x13a11,
    x16a13,x16a14,x30a27,x30a28,x4a3,x3a4,x3a1,x30a13,x30a14,x37a18,x18a37,x37a38,x38a37}; // la table des itineraires pour tco

Les tableaux d'objets sont indispensables pour pouvoir ensuite accéder à leurs méthodes et variables à partir de leur numéro.

Jusque là c'est assez simple quand on a bien décortiqué son réseau et réalisé les coupures de zones et les points d'alimentation nécessaire, ce qui n'était pas tout à fait mon cas (je devrai faire quelques modifications).

A partir de là, maintenant, il faut définir les méthodes particuliers qui dépendent de la configuration du réseau (il faut un bon dessin !) :

  • Des zones, exemple :
Zone* Z12::suivantePaire() { return selonAiguille(a7,z13,selonAiguille(a6,NULL,z43)); }
Zone* Z12::suivanteImpaire() { return selonAiguille(a8,z11,selonAiguille(a11,NULL,z29)); } // !! changement de sens sur z30
void Z12::actions() { aubiner(crr4,c8,c6); }
void Z12::desactions() { detruire(x11a13,x13a11,x11a14,x14a11);detruire(x13a30,x30a13,x14a30,x30a14); }

  • Des signaux, exemple :
Signal* CRR2::suivant() { return selonAiguille(a0,selonAiguille(a1,c1,selonAiguille(a3,NULL,c2)),selonAiguille(a2,NULL,selonAiguille(a4,c8,c4))); }
Signal* CRR2::precedent() { return selonAiguille(a18,cr1,cr2); }
boolean CRR2::ralentissement30() { return a1->deviee()?true:false; }

  • Et des itinéraires, exemple :
boolean X4a7::formable() { return libres(x4a7,x3a4,x4a3,x5a7) && libres(z6,z7,z39); }
void X4a7::former() { a16->directer(); a13->devier(); c7->ouvrir(); }
boolean X4a7::deformable() { return libres(z4,z6,z39); }
void X4a7::deformer() { c7->fermer(); }
void X4a7::tracer(boolean b) { trace(b,z4,z6,z39);z7->tracer(b); }

Ce qui fait encore un gros paquet de lignes de code, soit 600 lignes dans mon cas !!!

Au total, l'ensemble des définitions des objets dérivés, les déclarations d'objets réels et les méthodes particulières prennent 1950 lignes de code (dont quelques lignes de commentaires quand même). C'est un gros travail assez fastidieux, mais plein de copier-coller.

Ce qu'il faut mettre dans les méthodes particulières doit suivre un certain nombre de règles que j'ai notées au fur et à mesure. Je vous les donnerai dans une des suites de ce fil.

Maintenant que tout cela est fait, il faut le tester et corriger les anomalies.

Je dois dire que ces tests sont absolument nécessaires car, à ce stade de l'écriture des méthodes particulières des objets, on ne se rend pas bien compte si on bien codé ou pas.

En effet, il n'est pas toujours facile de savoir comment combiner les zones et les aiguilles, comment définir les itinéraires et le meilleur moyen est de simuler un passage de train et de regarder le comportement du gestionnaire.

Ce sera l'objet de la suite qui va suivre !!!

...

2103
« Par ma foi ! il y a plus de quarante ans que je dis de la prose sans que j'en susse rien, et je vous suis le plus obligé du monde de m'avoir appris cela. »

Bonsoir Marc-Henri,

Comme le dirai Monsieur Jourdain, je viens de découvrir que je fais du thread sans le savoir ! Si, en fait et je donne un exemple :

Dans un programme Arduino, il y a le Setup() qui est éxécuté une seule fois en premier, puis la Loop() qui est éxécutée ensuite de façon répétitive. C'est exactement comme un while(1) { ………}. Le compilateur l'ajoute subrepticement sans qu'on le voit !

Quand je programme mon gestionnaire de réseau, je fais donc éxécuter dans la Loop(), toute une série de tâches qui ne vont occuper le processeur qu'une petite fraction du temps en le libérant le plus vite possible, pour que la suivante prenne la main, et ainsi de suite.

Ces tâches sont (dans mon gestionnaire, mais tout le monde reconnaitra des cas qu'il rencontre aussi) :

  • Récupération des messages CAN si le flag a été monté par l'interruption. Il faut lire tous les messages CAN reçus sinon l'interruption n'aura plus lieu ensuite. Les messages sont stockés temporairement dans un tampon circulaire.
  • Traitement d'UN SEUL message CAN reçu et stocké dans le tampon circulaire (une occupation ou une libération, ou une demande d'itinéraire, de changement d'aiguille ou de mouvement de train.
  • Lecture du port série s'il y a des caractères reçus et une action est lancée seulement si une commande complète est reçue (sinon elle est stockée temporairement). Cela sert principalement au Debug pour valider ou non certains affichages ou passer des commandes de simulation
  • Lecture des boutons d'un écran tactile : un seul à la fois donne lieu à l'exécution d'une commande
  • Toute une série de tâches périodiques se suivent ensuite en testant la valeur de millis() par rapport à des tops d'actions comme le rafraichissement d'affichages, des clignotements de leds, les calculs de durée d'execution (combien de tours de Loop() par seconde pour mesurer la vitesse du programme), des time-out, des pas de simulation (envoyer par exemple une commande lue dans une carte SD toutes les 2 secondes), etc..
  • On peut en imaginer d'autres ...

J'ai décrit là 5 types de threads qui sont, en fait, programmés comme des sous-programme (une entrée et une sortie) et qui ne s'interdisent aucune contrainte de programmation.

En particulier le switch / case est totalement permis et fort heureusement car il faut bien agir en fonction de la commande reçue et une suite de if ne serait pas agréable. Les Macros ne sont pas obligatoires non plus.

Ces tâches correspondent bien à un gestionnaire de réseau, mais mon Arduino Mega qui commande des aiguilles est fait de la même façon, avec les tâches liées aux messages, mais aussi les commandes des moteurs d'aiguilles qui sont décalées dans le temps d'au moins une 1/2 seconde pour éviter les appels de courant simultanés (j'ai fait sauter un fusible avent cela !)

La seule contrainte est de bien respecter le non-blocage du processeur pendant l'éxécution d'une tâche (pas de delay(), des while() bien contrôlés, des tests sur toutes les limites) et que chaque tâche puisse reprendre la main sans perdre d'événement d'où quelques tests de Debug pour mesurer les temps d'exécution. D'une manière générale, je n'ai jamais eu de surprise (hors bug évidemment).

Voilà comment on fait du thread sans le savoir !

Amicalement


2104
Vos projets / Re : Un mini module sonore
« le: mars 14, 2017, 06:56:35 pm »
Voici une liste de fournisseurs pour les composants de cette carte (en fait, ceux que j'ai utilisé) :


C1       470µF   aluminium-capacitor   radial-capacitor-100-50
http://www.tme.eu/fr/details/uvr1e471mpd/condensateurs-electrolytiques-tht-85c/nichicon/
C2       100nF   unpolarized-capacitor   metallized-polyester-capacitor-50
http://www.tme.eu/fr/details/r82dc3100dq50j/condensateurs-de-polyester-tht/kemet/
C3       100nF   unpolarized-capacitor   metallized-polyester-capacitor-50
C4       47µF   aluminium-capacitor   radial-capacitor-25-70
http://www.tme.eu/fr/details/uvr1j470med/condensateurs-electrolytiques-tht-85c/nichicon/
C5       1µF   unpolarized-capacitor   metallized-polyester-capacitor-50
http://www.tme.eu/fr/details/r82dc4100aa60k/condensateurs-de-polyester-tht/kemet/
C6       10nF   unpolarized-capacitor   metallized-polyester-capacitor-50
http://www.tme.eu/fr/details/r82ic2100dq50j/condensateurs-de-polyester-tht/kemet/
D1       1N4007   1n400x   do41-long
D2       led   round-led-3mm
IC1       7805   lm78xx   to220up
http://www.tme.eu/fr/details/l7805cv/stabilisateurs-de-tension-non-regles/st-microelectronics/
K1      terminal-block-3-way-5mm   terminal-block-3
http://www.tme.eu/fr/details/tb-5.0-p-3p_gy/borniers-de-serrage-pcb/ninigi/
K2      terminal-block-3-way-5mm   terminal-block-3
K3      terminal-block-3-way-5mm   terminal-block-3
K4      terminal-block-3-way-5mm   terminal-block-3
K5      terminal-block-3-way-5mm   terminal-block-3
K6      terminal-block-3-way-5mm   terminal-block-3
K7      terminal-block-3-way-5mm   terminal-block-3
K8      grid-100mils-3-1   grid-100mils-3-1
K9      grid-100mils-3-1   grid-100mils-3-1
K10      grid-100mils-3-1   grid-100mils-3-1
K11      grid-100mils-3-1   grid-100mils-3-1
K12      grid-100mils-3-1   grid-100mils-3-1
K13      grid-100mils-3-1   grid-100mils-3-1
K14      grid-100mils-3-1   grid-100mils-3-1
K15      grid-100mils-3-1   grid-100mils-3-1
K16      grid-100mils-1-8   sil8
P1       4,7k   small_trimmer   small_ajustable_resistor
PROMINI1   pro-mini2   pro-mini-2
http://www.ebay.fr/itm/401090346945?_trksid=p2055119.m1438.l2649&ssPageName=STRK%3AMEBIDX%3AIT
http://www.ebay.fr/itm/311569959184?_trksid=p2055119.m1438.l2649&ssPageName=STRK%3AMEBIDX%3AIT
R1       10k   resistor   mf12
R2       4,7k   resistor   mf12
R3       1k   resistor   mf12
sd1      sdcard   sd-card
http://www.ebay.fr/itm/2PCS-Micro-SD-TF-Card-Storage-Memory-Module-SPI-Level-conversion-For-Arduino-/311011440000?hash=item4869b9f580

Pour programmer le Mini :
http://www.ebay.fr/itm/401241175865?_trksid=p2055119.m1438.l2649&ssPageName=STRK%3AMEBIDX%3AIT
http://www.ebay.fr/itm/311760212115?_trksid=p2055119.m1438.l2649&ssPageName=STRK%3AMEBIDX%3AIT

Composants passifs
http://stores.ebay.fr/Distri-Compo/Condensateurs-electrolytique-/_i.html?_fsub=9075072018&_sid=1176693738&_trksid=p4634.c0.m322

Attention, c'est bien ce modèle de Pro-Mini qu'il faut, avec les pins A4 A5 A6 A7 sur le petit côté opposé à l'interface de programmation USB/TTL.

Amicalement
Dominique

2105
Vos projets / Re : Re : Un mini module sonore
« le: mars 14, 2017, 06:47:44 pm »
Bonjour à tous,
Puisque nous sommes dans le son, quelqu'un connaît-il la carte Audio FX - 2x2W de Adafruit?
Possibilité de commander la lecture de 1 fichier audio parmi 10 en commutant une des 10 broches de commande à la masse.
L'arduino n'a plus qu'à présenter une broche au moins sur une des entrées (alimentations mises en commun sur le moins).
Il existe une version avec ampli 2 x 2W incorporée sur le circuit.

Non, je ne la connaissais pas ! Merci pour ce tuyau.

Mais elle coûte 30$ et c'est beaucoup plus qu'un simple lecteur SD à 1€, d'autant qu'un Arduino Pro-Mini peut très bien gérer plus que 10 sons (jusqu'à concurrence de la taille de la carte SD).

Attendons la version chinoise si c'est de l'open source.

2106
Vos projets / Re : Un mini module sonore
« le: mars 14, 2017, 06:06:19 pm »
Ah, ça bouge : les circuits viennent de quitter Hong-Kong et sont en cours d'acheminement via les postes suisse puis française.

2107
Bus CAN / Re : Le bus CAN
« le: mars 14, 2017, 09:20:17 am »
Cela veut dire que LCC est encore trop jeune !

2108
Bus CAN / Re : Le bus CAN
« le: mars 12, 2017, 10:25:05 pm »
C'est intéressant de revoir Don Goodman-Wilson de RailStar, qui a conçu CmdrArduino (celui qu'on laisse au profit de DCC++). Don avait disparu du support de son produit, pour se consacrer à Open-LCB qui a finalement été choisi par NMRA comme standard qui s'appelle maintenant LCC. Bravo Don !

Je n'ai pas encore tout compris, à part le choix du bus CAN pour les échanges fiables et la câblage facile.

Ce que je peux en déduire (mais je vais surement me tromper), c'est que pour interconnecter autant de choses différentes que des aiguilles, des feux, des panneaux de led et boutons (TCO ?), des détecteurs d'occupation et Railcom, des manettes, des boosters (on dit centrale en général)... et un soft gestionnaire comme JMRI, ET TOUT CELA PLUG&PLAY, c'est forcément compliqué (tout ce qui est simple pour l'utilisateur est forcément une usine à gaz à l'intérieur).

L'expérience du Wifi et de TCP/IP ont donné lieu, finalement, à des choses simples à mettre en oeuvre, avec des composants pas cher (vu les millions d'unités produites) et des bibliothèques ad'hoc.

Mais ce ne sera pas à la portée du gars qui voudrait seulement faire clignoter un led 5 fois (joke), avant un bon moment.
Apparemment chaque "noeud" du réseau (connecté à un équipement) doit contenir un fichier de configuration qui semble ne pouvoir être construit et modifié que par JMRI. En tous cas c'est un fichier XML : ajouter un parser et un éditeur Wisiwyg dans un Arduino n'est pas une mince affaire !

Du coté des locos (la commande DCC++ par exemple), on imagine bien qu'un gros paquet de données sont stockées dans le noeud connecté à la centrale, de façon à piloter toutes les locos d'une manière standard (par exemple en leur donnant un ordre contenant la vitesse réelle à l'échelle, et non pas un cran DCC).

Cela dit, on va se faire un point d'honneur à Locoduino, à tenter de vous expliquer tout ça et de construire quelque chose.

Ca tombe bien, mon réseau est constitué de plusieurs éléments (à base d'Arduino) qui communiquent entre eux via un bus CAN  ;D ;D, sans JMRI, chaque élément (DCC booster, détecteurs d'occupations, contrôleur d'aiguilles, TCO, gestionnaire) a forcément sa configuration propre qui m'a valu une description sur papier, ainsi que les messages qui s'échangent entre modules.

Je ne me sens pas trop dépaysé, donc à suivre ...

2109
Bus CAN / Re : Re : BUS CAN 3 rails
« le: mars 10, 2017, 08:23:40 pm »
Pour ce qui concerne la carte Locoduino, je ne comprends pas ceci :
si vous utilisez 2 paires, d'accord mais !
je dirais que chaque paire devrait être connectée sur un fil à CANH et à l'autre à CANL.
Ce n'est pas le cas sur la carte Locoduino !

Pourquoi ?

Bàv
Jacques ( PapyJack)

Non c'est tout bête : les 2 prises RJ11 sont en parallèle pour permettre le chainage des cartes et relier les cartes 2 à 2 avec un cable droit.
Il faut mettre la résistance de 120 Ohm en bout de chaine (d'où le strap).

Je joins le schéma :

2110
Bus CAN / Re : BUS CAN 3 rails
« le: mars 10, 2017, 01:39:41 pm »
Tu devrais poser la question directement à l'auteur de l'article ou en bas de l'article.

Néanmoins je "prendrais le risque" pour 1,14€  :o


2111
Vos projets / Re : CIRCULATION ALTERNÉE
« le: mars 10, 2017, 11:43:49 am »
Bravo Fabien,

Un petit conseil (pour tous également) : Pour partager un programme, le mieux est de compresser le dossier du programme qui contient le .ino (et éventuellement d'autres fichiers) et de joindre le fichier compressé (.zip) à la discussion, comme ci-dessous  :D

Mais là tu permets de le lire directement ce qui est utile aussi  ;)



2112
Bus CAN / Re : BUS CAN 3 rails
« le: mars 10, 2017, 11:37:41 am »
Je fais référence en particulier à cette petite carte à moins de 2€ :

http://www.ebay.fr/ulk/itm/311520457612

Bonjour,

Je débarque, peut-être ai-je manqué un commentaire, mais cette carte "peuchère" me paraît fonctionner seulement en RX !
C'est d'ailleurs ce qui est mis dans le libellé du produit!
Sur les photos on observe également qu'il n'est possible que de connecter une seule paire de fils sur le bus CAN.

Jacques

Bonjour Jacques,

Il ne faut pas prendre "à la lettre" les libellés des vendeurs sur eBay, qui sont souvent traduits par un robot.

Si vous regardez les articles sur le site Locoduino, vous verrez que cette carte fonctionne en émission ET réception !

Le bus CAN est bidirectionnel : une seule paire suffit (lisez les articles !!!)

Amicalement

2113
Bienvenue Alibert ;)

Un échec n'est qu'un essai avant la réussite  ;)

J'ai automatisé un va et vient sur une voie unique du réseau d'expo en N de mon club. Prêt à le partager si tu veux.

Dominique

2114
Présentez vous ! / Re : se présenter ? ok
« le: mars 07, 2017, 09:54:00 pm »
Bonjour Junon et bienvenue parmi nous.

J'ai l'impression qu'il va faire plus de 4 mètres surtout pour faire tourner des TGVs (en HO ou N ?).

Déjà l'atout c'est d'avoir un ami qui sait faire de beaux décors, car si tu te lances dans l'électronique et la programmation, ça fait pas mal de sujets à traiter !


Pour t'y retrouver dans toutes les techniques possibles décrites ou pas encore décrites sur Locoduino, le mieux est d'avoir une vision générale de ton projet que tu peux partager ici pour en discuter. Nous nous ferons un plaisir de répondre à tes questions.

Bon courage
Dominique

2115
Vos projets / Re : Un mini module sonore
« le: mars 06, 2017, 06:37:16 pm »
Bon, je viens de passer commande de 20 cartes chez ElectroDragon, ce qui revient à 1,40€ par carte !
Je devrais les recevoir dans 2 à 3 semaines, je vous préviendrai quand j'aurai des précisions.

Pour le moment j'ai cette liste :
5 cartes pour moi
3 cartes pour Claude91 (est-ce Claude Laurent ?, sinon ça marchera quand même)
2 cartes pour Thierry
2 cartes pour Denis
2 cartes pour Catplus

Je vous remercie de m'envoyer un MP avec votre adresse perso.

Voici la liste des composants :

C1       470µF   aluminium-capacitor   radial-capacitor-100-50
C2       100nF   unpolarized-capacitor   metallized-polyester-capacitor-50
C3       100nF   unpolarized-capacitor   metallized-polyester-capacitor-50
C4       47µF   aluminium-capacitor   radial-capacitor-25-70
C5       1µF   unpolarized-capacitor   metallized-polyester-capacitor-50
C6       10nF   unpolarized-capacitor   metallized-polyester-capacitor-50
D1       1N4007   1n400x   do41-long
D2       led   round-led-3mm
IC1       7805   lm78xx   to220up
K1      terminal-block-3-way-5mm   terminal-block-3
K2      terminal-block-3-way-5mm   terminal-block-3
K3      terminal-block-3-way-5mm   terminal-block-3
K4      terminal-block-3-way-5mm   terminal-block-3
K5      terminal-block-3-way-5mm   terminal-block-3
K6      terminal-block-3-way-5mm   terminal-block-3
K7      terminal-block-3-way-5mm   terminal-block-3
K8      grid-100mils-3-1   grid-100mils-3-1
K9      grid-100mils-3-1   grid-100mils-3-1
K10      grid-100mils-3-1   grid-100mils-3-1
K11      grid-100mils-3-1   grid-100mils-3-1
K12      grid-100mils-3-1   grid-100mils-3-1
K13      grid-100mils-3-1   grid-100mils-3-1
K14      grid-100mils-3-1   grid-100mils-3-1
K15      grid-100mils-3-1   grid-100mils-3-1
K16      grid-100mils-1-8   sil8
P1       4,7k   small_trimmer   small_ajustable_resistor
PROMINI1   pro-mini2   pro-mini-2
R1       10k   resistor   mf12
R2       4,7k   resistor   mf12
R3       1k   resistor   mf12
sd1      sdcard   sd-card


On installe, au choix, soit les borniers à vis K1 à K7, soit les barettes males au pas de 2,54 K8 à K15, mais pas les 2 à la fois. A vous de choisir.

Pages: 1 ... 139 140 [141] 142 143 ... 169