Etude d’un passage à niveau universel

Par une approche orientée objet

. Par : Dominique, JPClaude. URL : http://www.locoduino.org/spip.php?article170

Nous allons, dans cette présentation, reprendre le problème posé par la précédente publication sur la gestion d’un passage à niveau mais dans une approche orientée objet qui permet de s’adapter à toutes sortes de configurations possibles (donc la vôtre) en y mettant les objets dont vous avez besoin.

Il est recommandé au préalable d’avoir lu les articles sur la programmation objet proposés sur le site. [1]

Cet article vous donnera ainsi un exemple d’application de la programmation objet et de ses bénéfices pour traiter des cas plus complexes (disons plutôt moins simples !) en les rendant plus faciles à aborder et à programmer.

Le plan de cet article est le suivant :

  • Principe de fonctionnement et contraintes
  • Définition du cahier des charges
  • Algorithmes à mettre en place
  • Approche objet
  • Définition des classes
  • Méthode de programmation d’une configuration
  • Un exemple de programmation
  • Optimisation des configurations

Principe de fonctionnement du passage à niveau

Petit rappel : le passage à niveau de l’article précédent ressemble à cela :

Les capteurs représentés sont des ILS mais d’autres types de capteurs de passage sont possibles et seront présentés plus loin.

Il y a 2 capteurs par voie entrante ou sortante du passage à niveau. Pour chaque sens de circulation, seulement trois capteurs sont utilisés, le premier, répertorié par un O, détermine l’arrivée d’un train sur le passage à niveau, le second répertorié par un F du même côté que le précédent, impose la fermeture du passage à niveau, le troisième répertorié par un O de l’autre côté du passage à niveau, prévient que le train a complétement franchit le passage à niveau.
Chaque voie du passage à niveau est donc composée de deux parties, une partie à « gauche » du passage et une à « droite ».
Chaque partie est elle-même décomposée en deux zones, chacune possédant un capteur.
• L’une, matérialisée par les capteurs répertoriés avec un O dans l’image précédente, se trouve assez loin du passage à niveau, c’est une zone d’entrée-sortie qui conditionne les actions sur le passage. Elle a un double rôle : Dans le cas d’une sortie du passage à niveau elle correspond à une demande d’ouverture, dans le cas d’une arrivée sur le passage à niveau, à une demande de fermeture.
• La seconde, matérialisée par les capteurs répertoriés avec un F dans l’image précédente, plus proche du passage à niveau, correspond à la fermeture effective des barrières dans le sens entrée et n’a aucune action dans le sens sortie.
L’ouverture des barrières ne pourra se faire que s’il n’y a plus de condition de fermeture en cours, et donc plus aucun train sur les voies du passage à niveau

Le schéma suivant résume ce principe :

prinicpe des zones de capteurs

Les schémas suivant résument l’ensemble de ce fonctionnement pour un train arrivant par la gauche du passage à niveau (le raisonnement est symétrique s’il arrive de l’autre côté) :

1 : étape de l’arrivée d’un train :

étape arrivée d’un train

Le train passe sur le capteur de la zone d’entrée-sortie gauche, il y a donc une demande de fermeture du passage à niveau ; on incrément alors la variable ETAT et on note que le train va vers la droite dans la variable DIR (le train a donc une direction opposée (vers la droite) au côté de la zone qui se trouve à gauche)

2 : étape de fermeture du passage à niveau

étape fermeture du passage à niveau

Le train arrive sur le capteur de la zone de fermeture. On vérifie qu’il y a des demandes de fermeture en examinant la variable ETAT et que le train arrive bien sur le passage à niveau, c’est-à-dire que sa direction (DIR) est bien vers le passage à niveau, opposée au côté de la zone d’où il vient, ici sa direction DIR est vers la droite et la zone considérée est à gauche.

3 : étape ou rien ne se passe

étape sans action

Le train passe sur le capteur de la zone de fermeture de droite, la direction du train (DIR) et le coté de la zone étant les mêmes (le train va à droite et la zone est à droite), il n’y a rien à faire, on garde le passage fermé.

4 : étape du départ d’un train

étape départ du train

Le train arrive sur le capteur de la zone d’entrée-sortie droite. La zone et la direction du train (DIR) étant la même, tous les deux à droite, il s’agit d’une demande d’ouverture du passage à niveau, on décrémente donc le nombre de demandes de la variable ETAT.

5 : étape ouverture du passage à niveau

étape ouverture du passage à niveau

Le passage à niveau ne peut être ouvert que si toutes les variables ETAT de toutes les voies qui le traversent sont nulles.

Contraintes  :
Tous les cas possibles ne sont pas forcément considérés dans cette analyse.
La première contrainte est, pour une voie donnée et un sens de circulation, qu’il faut que toutes les demandes d’ouverture soient réalisées avant d’admettre un sens de circulation opposé, en d’autre terme chaque voie fonctionne en « half-duplex ».
La seconde correspond à des manœuvres, par exemple, avec entrée dans une zone sans traversée du passage, peuvent résulter dans une fermeture définitive du passage. C’est pour cela qu’un bouton de "triage" est envisagé qui permet de fermer et de suspendre la gestion du passage à niveau le temps des manœuvres.
Le troisième cas correspond à un cafouillage sur les capteurs qui bloquerait le programme et pour ces cas un bouton « reset » est proposé afin de remettre le programme de son état initial.

Cahier des charges

Le cahier des charges est la première chose à faire. Cela permet de ne rien oublier et surtout de ne rien ajouter inutilement. En ce qui concerne notre passage à niveau, voici ce que l’on attend comme résultat :

Le nombre de voies ne peut être limité que par le choix de la carte Arduino, selon la quantité de capteurs à mettre en œuvre.

  • Les voies comprennent des zones qui regroupent des capteurs ayant même rôle
    1. Une zone gauche d’entrée-sortie (éloignée)
    2. Une zone gauche de fermeture du passage (proche)
    3. Une zone droite de fermeture du passage (proche)
    4. Une zone droite d’entrée-sortie (éloignée)

Le passage à niveau possède des accessoires au choix :

  • feux seuls (croix de St André)
  • barrières seules (à bobines ou à relais)
  • barrières et feux
  • et dans un futur nous souhaitons y incorporer du son, celui de la sonnerie activée pendant la fermeture de la barrière.

Les actions devront être :

  • Ouverture protégée du passage à niveau
  • Fermeture du passage à niveau
  • Mode triage, ferme le passage et suspend sa gestion
  • Reset, remise à l’état initial du passage
  • Clignotement des feux routiers
  • Et dans un futur, activation d’une sonnerie

Gestion du passage par TCO

  • Un bouton reset de remise à l’état initial (en cas de cafouillage ou cas non prévu)
  • Un commutateur triage qui bloque la gestion du passage à niveau et le ferme
  • Une Led témoin de l’état triage
  • Une Led témoin de l’état du passage à niveau
  • le TCO est déporté via un bus CAN
  • Le bus CAN peut aussi déporter certains capteurs (notamment ceux qui sont éloignés) par une mise en commun avec des capteurs d’occupation.

Algorithmes

Il va y avoir trois algorithmes fondamentaux, le premier concerne le traitement des demandes d’action, le second le traitement des fermetures des barrières et le clignotement des feux routiers, enfin le troisième correspond à l’ouverture des barrières de façon sécurisée et l’arrêt des feux routiers.

Algorithme de traitement des demandes d’action

Cet algorithme est exécuté de façon indépendante par chaque zone (gauche et droite) d’entrée-sortie de chaque voie qui traverse le passage à niveau.
D’où l’intérêt de la programmation objet que nous aborderons.
Tout d’abord il faut savoir si la demande correspond à une demande d’ouverture (train quittant le passage) ou de fermeture (train arrivant sur le passage). Pour cela nous avons la variable « DIR » qui nous fournira cette information. Puisque la demande peut être distante du passage il peut y avoir plusieurs demandes de fermeture en attente (cas de plusieurs voies convergentes vers le passage à niveau), on a donc la variable « ETAT » qui s’incrémente et se décrémente, donc maintient le nombre de demandes de fermeture pour une voie donnée.

L’algorithme est le suivant, pour une zone (gauche ou droite) de demande :

Algorithme des entrées/sorties

  1.  
  2. Si (ETAT == 0) // le nombre de demande est nulle, la voie est donc libre
  3. Alors {
  4. ETAT +1 ; // c’est forcément une arrivée
  5. DIR = vers le sens opposé à la zone ;
  6. }
  7. Sinon { // la voie possède déjà au moins une demande
  8. Si (DIR est la même que la zone) // c’est une sortie
  9. Alors {
  10. ETAT – 1 ; // une demande de moins
  11. }
  12. Sinon { // la direction du train va dans le sens opposé de la zone
  13. Alors { // c’est une arrivée
  14. ETAT + 1 ;
  15. DIR = vers le sens opposé à la zone ;
  16. }
  17. }

Algorithme de traitement des fermetures

Cet algorithme est effectué de façon indépendante par chaque zone (gauche ou droite) de fermeture de chaque voie qui traverse le passage à niveau. La fermeture ne peut avoir lieu que si l’action provient d’une entrée sur le passage à niveau. Il faut donc qu’il y ait eu au moins une demande au préalable et que l’on soit en entrée du passage, c’est-à-dire que la direction du train soit dans le sens opposée de la zone (ie : un train allant vers le passage à niveau), et que les barrières soient ouvertes, sinon le travail a déjà était fait.

L’algorithme est le suivant pour une zone (gauche ou droite) de fermeture :

Algorithme des demandes de fermeture

  1. Si (ETAT >0 & DIR == sens opposé à la zone & barrière ouverte) {
  2. on ferme la barrière ;
  3. }

NB : dans le cas d’une voie unidirectionnelle, c’est-à-dire dont on est sûr que les trains vont toujours dans le même sens il suffit d’avoir une seule zone de fermeture celle qui est du côté par laquelle le train arrive.

Traitement de l’ouverture de la barrière

Cet algorithme est exécuté au niveau global du passage à niveau. Il tient compte de tous les traitements effectués localement par les différentes voies et leurs zones associées. L’ouverture ne peut avoir lieu que si toutes les voies sont libres, en d’autre terme que la somme des variables locales d’état est nulle.

L’algorithme d’ouverture de barrière est le suivant :

Algorithme de l’ouverture

  1. Si (Somme(ETAT) == 0) {ouverture de la barrière}

Approche orientée objet

L’approche orientée objet consiste à recenser les différents composants nécessaires à la réalisation de notre projet. Il y deux façons de procéder, par composition, on part des éléments de base et on construit petit à petit l’ensemble, ou par décomposition, on part de l’ensemble et par raffinement on dégage les objets.

Méthode par composition

De base on a des objets « capteurs  », ces capteurs sont regroupés dans des « zones  ». Une « voie » sera constituée de quatre zones (zone gauche de demande, zone gauche de fermeture, zone droite de fermeture, zone droite de demande), enfin un « passage » sera constitué par plusieurs voies. A cela il faut rajouter les accessoires du passage à niveau, les « barrières, les « feux » routiers et d’autres accessoires comme la sonnerie par exemple. Il faut aussi intégrer le « TCO » avec son « reset », son mode « triage » et ses « Led » témoins, qui communique via un bus « CAN »

Méthode par décomposition

C’est la démarche inverse, un « passage  » est constitué de plusieurs « voies » qui elle-même comporte plusieurs « zones  ». Ces dernières regroupent un ensemble de « capteurs  ». On retrouve évidemment les accessoires, « barrières  », « feux  » routier, ainsi que le « TCO  », « reset  », « Led  » et « triage  » et son bus « CAN  ».

Dans l’approche orientée objet chaque composant deviendra une classe (un modèle) dont chaque instance (réalisation) deviendra un objet. Il faut déterminer les variables du composant (ses attributs) et les actions que l’on peut lui appliquer (les méthodes).

On obtient donc le schéma suivant :

Les composants du passage à niveau

Étude de chaque composant et leur hiérarchie

Capteur
Un capteur est relié au microcontrôleur par le biais d’une broche et accessoirement avec un nom pour le différencier des autres capteurs. Pour les actions il faut tester l’état actif ou non, ou les transitions d’état du capteur.

Zone
Une zone regroupe un ensemble de capteurs ayant tous le même rôle. Une zone devra posséder au moins une liste de ses capteurs et accessoirement un nom pour la différencier des autres zones. Pour les actions il faut au minimum savoir si la zone est active, c’est-à-dire qu’au moins un de ses capteurs le soit.

Voie
Une voie bidirectionnelle regroupe 4 zones, une zone de demande et une zone de fermeture à gauche et de même pour la droite. Une voie unidirectionnelle n’a besoin que de trois zones, une zone demande en entrée, une zone fermeture et une zone demande en sortie. Une voie possédera une liste de ses zones et également accessoirement un nom. Une voie a pour rôle de déterminer si elle demande une fermeture de la barrière, il faut donc pouvoir tester cette demande.

Passage
Un passage regroupe un ensemble de voies, il aura donc une liste des voies. Il intègre des accessoires (barrières, feux), des interfaces avec le TCO (reset, triage, Led témoin, bus CAN). Il devra contrôler l’ensemble de ses voies afin de savoir s’il doit ou non ouvrir les barrières et actionner les éléments périphériques (feux, Led, sonnerie, signe de main de la garde barrière, etc..).

Accessoires
Les accessoires peuvent être divers et variés.
FEUX : Les feux routiers sont connectés à une broche du microcontrôleur et on doit pouvoir allumer, faire clignoter ou éteindre ces feux en fonction de la position des barrières.
BARRIERES : Le fonctionnement des barrières peut se faire de plusieurs façons. Les barrières à relais, les barrières à servos, les barrières avec moteur pas à pas commandent des moteurs dont le mouvement peut être lent alors que les barrières à bobines sont instantanées. Il faudra donc distinguer ces différents types de barrière. Par contre elles devront proposer les mêmes actions, action d’ouverture et de fermeture des barrières.

Bus CAN
Du côté de la gestion du passage à niveau il faut pouvoir initialiser le bus et recevoir les commandes du TCO (reset et demande du mode triage) et envoyer les confirmations d’actions. Du côté du TCO il faut également pouvoir l’initialiser, envoyer les commandes (reset, triage) et recevoir les confirmations d’actions. Dans notre approche le « reset » est fait de façon matériel commandé par une broche connectée via une résistance de 1K sur la broche RST de l’Arduino.
On pourra aussi utiliser le bus CAN pour recevoir des informations de capteurs produites pour d’autres organes, comme celles des détecteurs d’occupation destinées au TCO et au gestionnaire de réseau.

TCO
Le TCO se trouve à distance et communique avec la gestion du passage à niveau par l’intermédiaire du bus CAN. Il possède un bouton reset, un switch triage qui demande la mise en mode triage du passage à niveau, une Led témoin de la position des barrières et une autre pour le mode triage. Le TCO envoie ses commandes (reset, triage) et reçoit les confirmations de ces commandes ainsi que les états du passage à niveau.

Il y a donc deux programmes, l’un pour le passage à niveau et un autre pour le TCO qui communiquent entre eux via le bus CAN.

Les classes du passage à niveau

Il est nécessaire d’avoir les bibliothèques suivantes installées :

1- La classe « barriere »

Classe abstraite représentant une barrière
La barrière peut être commandée de différentes façons (bobines, relais, servo, etc…). C’est une classe abstraite car elle impose à chaque classe fille de définir obligatoirement des méthodes qui se caractérisent par la définition suivante :

  1. virtual type nomFonction(signature)=0 ;

Constructeur :

  1. barriere(int temps,byte sorte);
  • temps : une durée de fonctionnement
  • sorte : détermine le type de fonctionnement (unipolaire, bipolaire ou quadripolaire)

Attributs utilisables par tous les héritiers :

  • mode sens : (enum : montee,descente,arret) : sens de la manœuvre
  • etat situation (enum : ouvert, ferme, encours) : état de la barrière
  • bool _actif : état d’activation de la barrière
  • unsigned long timer : sert à partager le temps d’exécution
  • int duree : une durée d’activation
  • byte poles : le nombre de pôles du moteur de la barrière

Méthodes utilisables par tous :

  1. bool ouverte(); // vrai si barrière ouverte
  2. bool fermee(); // vrai si barrière fermée
  3. bool stop(); // vrai si pas de manœuvre
  4. bool monte(); // vrai si en cours de montée
  5. bool descend(); // vrai si en cours de descente
  6. bool mouvement(); // vrai si manœuvre active
  7. bool actif(); // renvoie l’état de la manœuvre de la barrière
  8. byte nombrePoles(); // renvoie le nombre de pin utilisé

Méthodes à définir obligatoirement pour chaque type de barrière :

  1. void ouverture(); // méthode qui commande l’ouverture de la barrière
  2. void fermeture(); // méthode qui commande la fermeture de la barrière
  3. void manoeuvre(); // méthode qui commande le déplacement de la barrière
  4. int broche(int num); // retourne le numéro de la pin de rang num

2- La classe « bobine »

Classe qui hérite de « barriere » pour des barrières de type bobines

Constructeur :

  1. bobine(int pina, int pinb,bool cde, int activation, int delai);
  • pina : pin bobine ouvrante
  • pinb : pin bobine fermante
  • cde : niveau actif des bobines (LOW, HIGH)
  • activation : durée de l’activation des bobines
  • delai : attente après passage du train pour ouvrir la barrière

Méthodes redéfinies :

  1. void ouverture(); // ouvre la barrière
  2. void fermeture(); // ferme la barrière
  3. void manoeuvre(); // simulation de la manœuvre d’ouverture
  4. int broche(int num); // renvoie le numéro d’une des deux pins

3- La classe « relais »

Classe qui hérite de « barriere » pour des barrières avec relais

Constructeur :

  1. relais(int pina, int pinb,bool cde, int duree);
  • pina : pin relais ouvrant
  • pinb : pin relais fermant
  • cde : niveau actif des relais (LOW, HIGH)
  • duree : durée d’activation des relais

Méthodes redéfinies :

  1. void ouverture(); // ouvre la barrière
  2. void fermeture(); // ferme la barrière
  3. void manoeuvre(); // manœuvre d’ouverture
  4. int broche(int num); // renvoie le numéro d’une des deux pins

4- La classe « servomoteur »

Classe qui hérite de « barriere » pour des barrières avec un ou deux servos synchrones.

Constructeurs :

  1. servomoteur(Servo& servoa,int pina, int ferme, int ouvre, int pas, int duree); servomoteur(Servo& servoa,int pina, Servo& servob, int pinb, int ferme, int ouvre, int pas, int duree);
  • servoa : un servo
  • pina : la pin du servoa
  • servob : un deuxième servo (synchrone au premier)
  • pinb : la pin du servob
  • ferme : valeur basse de la durée du signal PWM   (minimum 544us)
  • ouvre : valeur haute de la durée du signal PWM   (maximum 2400us)
  • pas : vitesse de rotation en us
  • time : durée de pause pour le servo

Méthodes redéfinies :

  1. void ouverture(); // ouvre la barrière
  2. void fermeture(); // ferme la barrière
  3. void manoeuvre(); // manœuvre d’ouverture
  4. int broche(int num); // renvoie le numéro d’une des deux pins

NB1 : il faut dans le cas de servo, mettre dans les déclarations du programme

  1. INO l’instanciation des servos (Servo servo1) ;

et dans le setup faire l’attachement des servos

  1. servo1.attach (pin) ;

NB2 : Il est souhaitable d’alimenter les servos avec une alimentation externe.

5- La classe « pas_a_pas »

Classe qui hérite de « barriere » pour des barrières avec un moteur pas à pas.

Constructeurs :

  1. pas_a_pas(int pina, int pinb, int pinc, int pind,int degre, int vitesse);
  • pina, pinb, pinc, pind : les 4 pins du moteur
  • degre : la valeur de l’angle d’ouverture en degré
  • vitesse : la vitesse de déplacement en us

Méthodes redéfinies :

  1. void ouverture(); // ouvre la barrière
  2. void fermeture(); // ferme la barrière
  3. void manoeuvre(); // manœuvre d’ouverture
  4. int broche(int num); // renvoie le numéro d’une des quatre pins

NB : Il est souhaitable d’alimenter le moteur avec une alimentation externe.

6- La classe « feux »

Classe de gestion des feux routiers

Constructeurs :

  1. feux(int pin, bool cde) ;
  2. feux(int pin, bool cde , int pas) ;
  • pin : pin des feux du passage à niveau
  • cde : niveau actif des Leds (LOW, HIGH)
  • pas : durée du pas du fading

Méthodes :

  1. int broche(); // renvoie la pin des feux du passage à niveau
  2. void ON(); // allume les feux
  3. void OFF(); // éteint les feux
  4. bool etatON(); // vrai si en phase ON
  5. bool etatOFF(); // vrai si en phase OFF

7- La classe « capteur »

Classe commune à tous les capteurs.
Les capteurs doivent être connecte en input PULL_UP.
Utilise la bibliothèque Bounce2.

Constructeurs :

  1. capteur(int pin);
  2. capteur(int pin,char* nom);
  3. capteur(int pin ,int duree, char* nom);
  • pin : Une broche ou est relie le capteur
  • durée : Un temps pour la bibliothèque Bounce (optionnel)
  • nom : Un nom de capteur (optionnel)

Méthodes :

  1. int broche(); // renvoie la broche du capteur
  2. String nom(); // renvoie le nom du capteur
  3. bool actualiser(); // mise à jour du capteur
  4. bool actif(); // renvoie si un capteur à changer d’état

8- La classe « zone »

Elle représente un ensemble de capteurs ayant une caractéristique particulière, demande d’ouverture ou de fermeture du passage à niveau, les capteurs d’une zone ont tous le même rôle.

Constructeur :

  1. zone(char* nom);
  • nom : un nom

Méthodes :

  1. bool add(capteur&); // ajoute un capteur a la zone
  2. void print(); // affiche la configuration de la zone, si mode console
  3. char* nom; // renvoie le nom de la zone
  4. bool actualiser(); // met à jour les capteurs de la zone
  5. bool actif(); // renvoie vrai si au moins un capteur de la zone est actif

9- La classe « voie »

La classe commune a toutes les voies. Elle représente un ensemble de 4 zones de capteurs, zone gauche ouvrante, zone gauche fermante, zone droite ouvrante, zone droite fermante.

Constructeurs :

  1. voie();
  2. voie(char* nom);
  • nom : un nom

Méthodes :

  1. char* nom(); // renvoie le nom de la voie
  2. int etat(); // renvoie l’état de la voie, nombre de demandes de passage
  3. bool demandeFermeture();// renvoie si il y a une demande de fermeture (vrai si demande)
  4. void config(zone1,zone2,zone3,zone4,nom(optionnel));
  5. // les 4 zones, un nom (optionnel)
  6. // pour la configuration d’une voie bidirectionnelle;
  7. void config(zoneGauche, zoneFerme, zoneDroite, char* name);
  8. // les 3 zones et un nom (optionnel)
  9. // pour la configuration d ’une voie unidirectionnelle;
  10. bool print(); // affiche la configuration, si mode console
  11. bool Loop; // boucle sur les capteurs et active les algorithmes de la voie

10- La classe « passage »

Classe d’un passage à niveau, on peut créer des passages avec :

  • Une barrière seulement, avec des commandes par bobines ou par relais
  • Des feux routiers seulement
  • Une barrière et des feux routiers

Constructeurs :

  1. passage(feux &fanal ) ;
  2. passage(feux &fanal, char* nom ) ;
  3. passage(barriere &barrier) ;
  4. passage(barriere &barrier, char* nom) ;
  5. passage(barriere &barrier,feux & fanal) ;
  6. passage(barriere &barrier, feux &fanal, char* nom) ;
  • &barrier : Une adresse d’instance de barrière
  • &fanal : Une adresse d’instance de feux
  • nom : Un nom

Méthodes :

  1. void add(voie& _voie); // ajoute une voie au passage à niveau
  2. void addCAN(int CS,int debit, int mode, int IDlocal, int IDdistant);
  3. // ajoute un bus can au passage à niveau
  • CS : la broche CS suivant la carte Arduino (10 : NANO/MINI/UNO, 53 : MEGA)
  • Debit : le débit du bus (50, 100, 250, 500,1000)
  • Mode : 0 normal, 1 étendu
  • IDlocal : identificateur CAN du passage à niveau
  • IDdistant : identificateur CAN du TCO
  1. void updateCAN(); // mis à jour du bus CAN
  2. void print(); // affiche la configuration du passage à niveau, si mode console
  3. void reception(); // affiche les messages reçus, si mode console
  4. void emission(); // affiche les messages émis , si mode console
  5. char*nom(); // renvoie le nom du passage a niveau
  6. void Loop(); // boucle sur l’ensemble de la configuration,
  7. // détermine le fonctionnement du passage à niveau
  8. void addReset(pin); // ajoute la pin reset au passage à niveau
  9. // qui sera reliée à la pin RST via une résistance de 1K.

11- La classe COM

Classe pour la communication sur le bus CAN [2].

C’est une interface simplifiée qui permet d’initialiser le bus et de configurer les masques et filtres simplement. On a choisi de ne considérer que les messages ayant l’identificateur du passage à niveau, en d’autre terme il n’y a qu’un masque (0xFFF) (tous les bits du filtre sont à considérer) et pour le filtre l’ID du passage à niveau (on limite ainsi le nombre de message). S’il y a besoin de rétroaction c’est au TCO de le faire puisqu’il reçoit toutes les informations du passage à niveau.

Constructeur :

  1. COM(int cs, int baudRate, int idmode);
  • cs : la broche CS (10 pour NANO/MINI/UNO, 53 pour MEGA)
  • baudRate : le debit du bus (50, 100, 250, 500, 1000)
  • idmode : 0 normal, 1 etendu

Méthodes :

  1. bool init(int filtre, int ID); // initialise le bus CAN
  2. void receptionMessage(); // réception des messages depuis le bus
  3. bool lireCode(unsigned char& code);// réception d’un code depuis le TCO
  4. int ecrireCode(unsigned char code );// envoie d’un code vers le TCO

Les codes sont sur un octet et sont les suivants :
RESET 0x01 // code réception du reset
TRIAGE_ON 0x02 // code réception triage ON
TRIAGE_OFF 0x03 // code réception triage OFF
RESET_CONF 0x04 // code émission confirmation reset
TRIAGE_ON_CONF 0x05 // code émission confirmation triage ON
TRIAGE_OFF_CONF 0x06 // code émission confirmation triage OFF
LED_ON 0x07 // code émission Led ON
LED_OFF 0x08 // code émission Led OFF

12- La classe CANbusInterface du TCO

Cette classe fournit une interface simple pour utiliser le bus CAN dans le cadre de nos tests, nécessite les bibliothèques SPI   et mcp_can.

Structure d’un message CAN :

  1. struct messageCAN {
  2. long unsigned int id; // ident du message
  3. unsigned char len; // longueur des donnees
  4. unsigned char buf[MAX_CHAR_IN_MESSAGE]; // buffer de donnees
  5. };

Constructeur :

  1. CANbusInterface(int cs, int baudRate, int idmode);

Méthodes (avec différentes façon d’initialiser en fonction du nombre de filtres souhaités) :

  1. bool init(int masque,int filtre) ;
  2. bool init(int mask0, int filter0, int filter1, int mask1, int filter2, int filter3, int filter4, int filter5) ;
  3. void receiveMessage() ; // reception des messages depuis le bus
  4. bool readMessage (messageCAN & message) ; // lecture d’un message CAN
  5. int writeMessage (messageCAN message) ; // envoie d’un message CAN

Démarche de programmation d’une configuration de passage à niveau

Dans les déclarations

  • Inclure les classe : # « includes.h »
  • Définir les paramètres du bus CAN
  • Définir tous les capteurs
  • Définir les zones
  • Créer les instances de voie
  • Définir le type de barrière
  • Définir les feux routiers
  • Définir le passage à niveau
  • Définir le reset

Dans le setup

  • Initialiser le bus CAN
  • Affecter les capteurs aux zones
  • Affecter les zones aux voies
  • Affecter les voies au passage à niveau
  • Attacher la pin reset

Dans la boucle

  • Mettre à jour le bus CAN
  • Boucler sur le passage à niveau

Démarche de programmation du TCO

Dans les déclarations

  • Inclure la classe : #include "CANbusInterface.h"
  • Définir les paramètres du bus CAN
  • Définir le mode triage
  • Définir le témoin du mode triage
  • Définir le reset
  • Définir le témoin de l’état du passage à niveau
  • Définir les méthodes d’envoie et réception des codes

Dans le setup

  • Initialiser les broches
  • Initialiser le bus CAN

Dans la boucle

  • Mettre à jour le bus CAN
  • Gérer les messages CAN

Un exemple de programmation avec un bus CAN

1- Programmation du passage à niveau

Considérons un passage à niveau traversé par deux voies en double sens.
Le schéma suivant présente les objets de ce passage.

configuration du passage à niveau de l’exemple

En rouge sont notées les broches de l’Arduino. CD signifie capteur demande, CF pour capteur fermeture, G pour gauche et D pour droite, enfin le chiffre se rapporte à la voie concernée, par exemple CDG1 veut dire capteur de demande de la zone gauche de la voie 1.

Ce type de configuration tient sur un Arduino NANO auquel il faut rajouter une interface MCP2515 pour la connexion avec le bus CAN. Cette interface utilise le bus SPI entre l’Arduino et le MCP2515. Les broches suivantes sont donc utilisées pour le bus CAN (13(SCK), 12 (SO), 11 (SI), 10(CS) et 2 (INT).

On trouvera plus de détails sur l’utilisation du bus CAN avec Arduino dans les articles Mise en oeuvre du Bus CAN entre modules Arduino (1) et Mise en oeuvre du Bus CAN entre modules Arduino (2).

Vous trouverez plus loin le programme dans « passage_a_niveau_bus_can ».

a) Les déclarations

  1. #include "includes.h" // inclus l'ensemble des classes utiles
  2.  
  3. #define CONSOLE // à enlever si pas d’affichage
  4. #define DEDIT_CONSOLE 9600
  5.  
  6. /*********************************************
  7.  * parametres du bus CAN
  8.  * *************************************************/
  9.  
  10. #define CS 10 // la broche CS 10: NANO/MINI/UNO, CS = 53 : MEGA
  11. #define DEBIT 500 // debit du bus
  12. #define ID_MODE 0 // 0 : mode normal, 1 : mode etendu
  13. #define ID_LOCAL 0x01 // ID du passage a niveau
  14. #define ID_DISTANT 0x02 // ID du TCO
  15.  
  16. /*************************************************
  17.  * l'interruption pour le bus CAN
  18.  * ****************************************************/
  19.  
  20. volatile bool FlagReceive = false;
  21. void CAN_ISR(){FlagReceive = true;}
  22.  
  23. /**************************************************
  24.  * definition des capteurs (pin, nom) en pull_up
  25.  ***************************************************/
  26.  
  27. capteur CDG1(3,"Dde voie1 gauche");
  28. capteur CFG1(5,"Fermeture voie1 gauche");
  29. capteur CFD1(7,"Fermeture voie1 droite");
  30. capteur CDD1(A1,"Dde voie1 droite");
  31. capteur CDG2(4,"Dde voie2 gauche");
  32. capteur CFG2(6,"Fermeture voie2 gauche");
  33. capteur CFD2(8,"Fermeture voie2 droite");
  34. capteur CDD2(A0,"Dde voie2 droite");
  35.  
  36. /***********************************************************
  37.  * definition des zones de detection (nom)
  38.  ***********************************************************/
  39.  
  40. zone zone1GaucheDde("demande Gauche");
  41. zone zone1GaucheFerme("fermeture Gauche");
  42. zone zone1DroiteDde("demande Droite");
  43. zone zone1DroiteFerme("fermeture Droite");
  44. zone zone2GaucheDde("demande Gauche");
  45. zone zone2GaucheFerme("fermeture Gauche");
  46. zone zone2DroiteDde("demande Droite");
  47. zone zone2DroiteFerme("fermeture Droite");
  48.  
  49. /************************************************
  50.  * instances de voie tranversant le passage
  51.  ******************************************************/
  52. voie voie1;
  53. voie voie2;
  54.  
  55. /*********************************************************
  56.  * definition de la barriere a relais (pin ouvre, pin ferme, delai activation)
  57.  * commenter les versions non utilisées (ici test avec relais)
  58.  *********************************************************/
  59.  
  60. relais cdeRelais(A2,A3,LOW,5000);
  61. // HIGH : relais active au plus, LOW : relais active au moins
  62.  
  63. //bobine cdeBobines(A2,A3,LOW,500,4000); // HIGH : bobine active au plus, LOW : bobine active au moins
  64.  
  65. //pas_a_pas cdeSteps(A2,A3,A4,A5,90,5000);// les 4 pins, ouverture en degre, vitesse de deplacement en us
  66.  
  67. //Servo servo1;
  68. //Servo servo2;
  69. //servomoteur cde1Servo(servo1,A2,1000,2000,20,75);
  70. //servomoteur cde2Servos(servo1,A2,servo2,A3,1000,2000,20,75);
  71.  
  72. /***********************************************************
  73.  * definition des feux (pin, cde, pas du fading) // pas = 10 par defaut
  74.  *************************************************************/
  75.  
  76. feux fanal(9, LOW); // high : actif au plus, LOW actif au moins
  77.  
  78. /**********************************************************
  79.  * definition du passage a niveau (barriere,feux,nom)
  80.  ********************************************************/
  81.  
  82. passage PAN(cdeRelais,fanal,"PN Locoduino bus CAN");
  83.  
  84. /******************************************************
  85.  * definition de la pin RESET
  86.  ***********************************************************/
  87.  
  88. int pinReset = A6;

b) Le setup

  1. void setup() {
  2.  
  3. /***************************************************
  4.   * pour le bus CAN
  5.  *******************************************************/
  6.  
  7. PAN.addCAN(CS,DEBIT,ID_MODE,ID_LOCAL,ID_DISTANT);
  8. attachInterrupt(0,CAN_ISR,FALLING);
  9.  
  10. /************************************************************************
  11.   * affectation des capteurs aux zones de detection
  12.   **************************************************************************/
  13.  
  14. zone1GaucheDde.add(CDG1);
  15. zone1GaucheFerme.add(CFG1);
  16. zone1DroiteDde.add(CDD1);
  17. zone1DroiteFerme.add(CFD1);
  18. zone2GaucheDde.add(CDG2);
  19. zone2GaucheFerme.add(CFG2);
  20. zone2DroiteDde.add(CDD2);
  21. zone2DroiteFerme.add(CFD2);
  22.  
  23. /******************************************************************
  24.   * affection des zones aux voies
  25.   ************************************************************************/
  26.  
  27. voie1.config(zone1GaucheDde,zone1GaucheFerme,zone1DroiteDde,zone1DroiteFerme,"voie1");
  28. voie2.config(zone2GaucheDde,zone2GaucheFerme,zone2DroiteDde,zone2DroiteFerme,"voie2");
  29.  
  30. /*******************************************************************
  31.  * affectation des voies au passage a niveau
  32.  **************************************************************************/
  33.  
  34. PAN.add(voie1);PAN.add(voie2);
  35.  
  36. /********************************************************
  37.   * attachement de la pin reset
  38.   *************************************************************/
  39.  
  40. PAN.addReset(pinReset);
  41.  
  42. /***************************************************
  43.  * affichage de la configuration
  44.  ******************************************************/
  45.  
  46. #ifdef CONSOLE
  47. Serial.begin(DEDIT_CONSOLE); // la console
  48. Serial.println(F("Configuration du passage a niveau"));
  49. Serial.println();
  50. PAN.print();
  51. Serial.println();
  52. #endif
  53. }

c) La boucle

  1. void loop() {
  2.  
  3. if (FlagReceive) {
  4. FlagReceive = false;
  5. PAN.updateCAN(); // mise a jour du bus CAN
  6. }
  7. PAN.Loop(); // on boucle sur le passage a niveau
  8. #ifdef CONSOLE
  9. PAN.reception(); // affiche les messages reçus
  10. PAN.emission(); // affiche les messages émis
  11. #endif
  12. }

NB :Le programme reste le même (aux caractéristiques près de la connexion du bus SPI ) si l’on utilise un MEGA.

d) Le résultat

Voici l’affichage de la configuration :

Configuration du passage a niveau

passage : PN Locoduino bus CAN
etat du passage : libre
feux routiers sur pin9, etat des feux : eteints
barrieres : pin1 pin16, pin2 pin17, position des barrieres : ouvertes

voie : voie1
Direction en cours :  vers la gauche
Etat de la voie : libre
Zone demande Gauche
 capteur Dde voie1 gauche :  pin3
Zone fermeture Gauche
 capteur Fermeture voie1 gauche :  pin5
Zone demande Droite
 capteur Dde voie1 droite :  pin15
Zone fermeture Droite
 capteur Fermeture voie1 droite :  pin7

voie : voie2
Direction en cours :  vers la gauche
Etat de la voie : libre
Zone demande Gauche
 capteur Dde voie2 gauche :  pin4
Zone fermeture Gauche
 capteur Fermeture voie2 gauche :  pin6
Zone demande Droite
 capteur Dde voie2 droite :  pin14
Zone fermeture Droite
 capteur Fermeture voie2 droite :  pin8

2- Programmation du TCO

Le programme du TCO se situe sur un autre Arduino relié à l’Arduino du passage à niveau via le bus CAN. Il est donc nécessaire ici aussi d’avoir une interface MCP2515 et de réserver les broches du bus SPI pour son fonctionnement. La configuration est la suivante : le switch du mode triage est sur la pin 3, le bouton de reset sur la pin 4, la LED témoin de l’état du passage à niveau sur la pin 5 et la LED témoin du mode triage sur la pin 6. Dans cet exemple le TCO est sur un Arduino UNO, mais un MEGA peut très bien être utilisé.

a) déclarations

  1. #include "CANbusInterface.h" // interface simplifiant l'utilisation du bus CAN
  2. // option pour la console
  3. #define CONSOLE // a supprimer pour une utilisation autonome
  4. #define DEBIT_CONSOLE 9600 // debit pour la console
  5.  
  6. /********************************************************
  7. * parametres du bus CAN
  8. *********************************************************/
  9.  
  10. #define CS 10 // la broche CS 10 pour NANO/MINI/UNO, 53 pour MEGA
  11. #define DEBIT 500 // debit du bus CAN
  12. #define ID_MODE 0 // mode 0 : normal, 1 : etendu
  13. #define ID_DISTANT 0x01 // ID du passage a niveau
  14. #define ID_LOCAL 0x02 // ID du TCO
  15. #define MASK 0xFFF // masque integral, on ne prend que l'ID du passage a niveau
  16.  
  17. // les codes des commandes
  18. #define RESET 0x01 // code emission du du reset
  19. #define TRIAGE_ON 0x02 // code emission triage ON
  20. #define TRIAGE_OFF 0x03 // code emission triage OFF
  21. #define RESET_CONF 0x04 // code reception confirmation reset
  22. #define TRIAGE_ON_CONF 0x05 // code reception confirmation triage ON
  23. #define TRIAGE_OFF_CONF 0x06 // code reception confirmation triage OFF
  24. #define LED_ON 0x07 // code reception led ON
  25. #define LED_OFF 0x08 // code reception led OFF
  26.  
  27. // une instance du bus CAN
  28. CANbusInterface can(CS,DEBIT,ID_MODE);
  29.  
  30. // les messages pour le bus CAN
  31. messageCAN messageR;
  32. messageCAN messageS;
  33.  
  34. /********************************************************
  35. * les composants du TCO
  36. * *********************************************************/
  37.  
  38. // bouton pour le mode triage
  39. int pinCdeTriage = 3;
  40. bool triage = false;
  41.  
  42. // bouton pour le reset
  43. int pinCdeReset = 4;
  44. bool reset = false;
  45.  
  46. // led temoin de l'etat du passage a niveau
  47. int pinLed = 5;
  48.  
  49. // led temoin du mode triage
  50. int pinTriage = 6;

b) Les méthodes pour le bus CAN

  1. /********************************************************
  2.  * les methodes du bus CAN
  3.  **********************************************************/
  4.  
  5. ///////// la routine d'interruption du bus CAN
  6.  
  7. volatile bool FlagReceive = false; // drapeau d'IT du bus CAN
  8. void MCP2515_ISR() {FlagReceive = true;} // mise a jour du drapeau d'IT sur arrivee d'un message
  9.  
  10. /////////// initialisation du bus CAN
  11.  
  12. void initCAN () {
  13. while (true) {
  14. if (can.init(MASK,ID_LOCAL)) {
  15. attachInterrupt(0,MCP2515_ISR,FALLING); // attachement de la routine d'IT sur la pin 2 (IT0)
  16. #ifdef CONSOLE
  17. Serial.println(F("Initialisation reussie"));
  18.  
  19. #endif
  20. break;}
  21. else {
  22. #ifdef CONSOLE
  23. Serial.println(F("initialisation impossible"));
  24. Serial.println();
  25. #endif
  26. }
  27. }
  28. }
  29.  
  30. /////// / gestion des codes recus depuis le passage a niveau
  31.  
  32. void processMessage()
  33. {
  34. switch (messageR.buf[0]) {
  35. case RESET_CONF : {digitalWrite(pinTriage,HIGH);digitalWrite(pinLed,HIGH); // confirmation de reset
  36. #ifdef CONSOLE
  37. Serial.println(F("TCO <== PAN : CONFIRMATION RESET"));
  38. #endif
  39. break;}
  40. case TRIAGE_ON_CONF : {digitalWrite(pinTriage,LOW); // confirmation du mode triage
  41. #ifdef CONSOLE
  42. Serial.println(F("TCO <== PAN : CONFIRMATION MODE TRIAGE ACTIF"));
  43. #endif
  44. break;}
  45. case TRIAGE_OFF_CONF : {digitalWrite(pinTriage,HIGH); // confirmation arret du mode normal
  46. #ifdef CONSOLE
  47. Serial.println(F("TCO <== PAN : CONFIRMATION MODE TRIAGE INACTIF"));
  48. #endif
  49. break;}
  50. case LED_ON : {digitalWrite(pinLed,LOW); // led temoin allumee
  51. #ifdef CONSOLE
  52. Serial.println(F("TCO <== PAN : BARRIERES FERMEES"));
  53. #endif
  54. break;}
  55. case LED_OFF : {digitalWrite(pinLed,HIGH); // led temoin eteinte
  56. #ifdef CONSOLE
  57. Serial.println(F("TCO <== PAN : BARRIERES OUVERTES"));
  58. #endif
  59. break;}
  60. }
  61. }
  62.  
  63. //////////// envoie des messages CAN au passage a niveau
  64.  
  65. void sendMessage() {
  66. // test si envoie d'une demande de mode triage
  67. if ((digitalRead(pinCdeTriage) == LOW) && (!triage)) {messageS.buf[0] = TRIAGE_ON; can.writeMessage(messageS);
  68. #ifdef CONSOLE
  69. Serial.println(F("TCO ==> PAN : MODE TRIAGE ACTIF"));
  70. #endif
  71. triage = true;}
  72.  
  73. // test si envoie de l'arret du mode triage
  74. if ((digitalRead(pinCdeTriage) == HIGH) && (triage)) {messageS.buf[0] = TRIAGE_OFF; can.writeMessage(messageS);
  75. #ifdef CONSOLE
  76. Serial.println(F("TCO ==> PAN : MODE TRIAGE INACTIF"));
  77. #endif
  78. triage = false;}
  79.  
  80. // test si envoie d'un reset
  81. if ((digitalRead(pinCdeReset) == LOW)&& (!reset)) {messageS.buf[0] = RESET; can.writeMessage(messageS);
  82. digitalWrite(pinTriage,HIGH);
  83. digitalWrite(pinLed,HIGH);
  84. #ifdef CONSOLE
  85. Serial.println(F("TCO ==> PAN : RESET"));
  86. #endif
  87. reset = true;}
  88.  
  89. // stop le reset
  90. if (digitalRead(pinCdeReset) == HIGH) {reset = false;}
  91. }

  1. /**************************************************
  2.  * affichage de la configuration
  3.  *************************************************/
  4.  
  5. void affiche() {
  6. Serial.println(F("Configuration du TCO du passage a niveau"));
  7. Serial.println();
  8. Serial.print(F("switch du mode triage sur pin : pin")); Serial.println(pinCdeTriage);
  9. Serial.print(F("bouton reset sur pin : pin")); Serial.println(pinCdeReset);
  10. Serial.print(F("Led temoin passage ferme sur pin : pin")); Serial.println(pinLed);
  11. Serial.print(F("Led temoin mode triage ON sur pin : pin")); Serial.println(pinTriage);
  12. Serial.println();
  13. }

c) Le setup

  1. void setup() {
  2.  
  3. /********************************************
  4.   * pour la console
  5.   ***********************************************/
  6.  
  7. #ifdef CONSOLE
  8. Serial.begin(DEBIT_CONSOLE);
  9. affiche();
  10. #endif
  11.  
  12. /*************************************************
  13.   * initialisation des broches
  14.   ******************************************************/
  15.  
  16. pinMode(pinCdeTriage,INPUT_PULLUP);
  17. pinMode(pinCdeReset,INPUT_PULLUP);
  18. pinMode(pinLed,OUTPUT); digitalWrite(pinLed,HIGH);
  19. pinMode(pinTriage,OUTPUT); digitalWrite(pinTriage,HIGH);
  20.  
  21. /*******************************************************
  22.   * initialisation du bus CAN
  23.   *******************************************************/
  24.  
  25. initCAN();
  26.  
  27. //preformattage des messages CAN
  28.  
  29. messageS.id = ID_DISTANT; // un seul ID, le passage a niveau
  30. messageS.len = 1; // une donnee sur un octet, le code
  31. }

d) La boucle

  1. void loop() {
  2.  
  3. /***********************************************************
  4.   * reception des messages du bus CAN
  5.   ************************************************************/
  6.  
  7. if (FlagReceive) {
  8. FlagReceive = false;
  9. can.receiveMessage();
  10. } // si message recu du bus les mettre dans le buffer circulaire
  11.  
  12. /***************************************************************
  13.   * lecture des messages arrivees en attente
  14.   *****************************************************************/
  15.  
  16. if (can.readMessage(messageR)){
  17. processMessage();
  18. } // si message en attente de traitement
  19.  
  20. /********************************************************************
  21.  * envoie des commandes au passage à niveau
  22.  ******************************************************************/
  23. sendMessage();
  24. }

Voici un exemple d’échanges entre le TCO et le passage à niveau  :

Emission PAN : PAN ⇒ TCO : BARRIÈRES FERMÉES
Réception TCO : TCO ⇐ PAN : BARRIÈRES FERMÉES

Emission PAN : PAN ⇒ TCO : BARRIÈRES OUVERTES
Réception TCO : TCO ⇐ PAN : BARRIÈRES OUVERTES

Emission TCO : TCO ⇒ PAN : MODE TRIAGE ACTIF
Réception PAN : PAN ⇐ TCO : MODE TRIAGE ACTIF
Réception TCO : TCO ⇐ PAN : CONFIRMATION MODE TRIAGE ACTIF
Emission PAN : PAN ⇒ TCO : BARRIÈRES FERMÉES
Réception TCO : TCO ⇐ PAN : BARRIÈRES FERMÉES

Emission TCO : TCO ⇒ PAN : MODE TRIAGE INACTIF
Réception PAN : PAN ⇐ TCO : MODE TRIAGE INACTIF
Réception TCO : TCO ⇐ PAN : CONFIRMATION MODE TRIAGE INACTIF
Emission PAN : PAN ⇒ TCO : BARRIÈRES OUVERTES
Réception TCO : TCO ⇐ PAN : BARRIÈRES OUVERTES

Emission TCO : TCO ⇒ PAN : RESET
Réception TCO : TCO ⇐ PAN : CONFIRMATION RESET

Un exemple de programmation sans bus CAN

Pour ceux qui veulent tester rapidement en local ou qui n’ont pas de bus CAN, le fichier « testLocal » propose une version autonome. La configuration est la même que précédemment mais on récupère les broches du bus SPI pour connecter une LED témoin du mode triage sur la broche 10, un switch pour le mode triage sur la broche 11 et une LED témoin de l’état du passage à niveau sur la broche 12. Pour le reset il suffit de mettre une résistance de 1K entre la broche RST et de mettre un bouton connecté à la masse pour faire un reset.

Les programmes

Voici le programme pour créer un passage à niveau avec un bus CAN

programme passage à niveau avec bus CAN

Voici le programme du TCO correspondant avec le bus CAN

le programme TCO avec bus CAN

Le programme suivant peut être utilisé sur un Arduino seul, sans bus CAN

programme de tests en local

Optimisation des configurations

Il est possible d’optimiser le nombre de capteurs et le nombre de pins utilisés.
La manière la plus efficace pour les pins est d’utiliser des "expander" comme le MCP23017 qui utilise l’I2C et fournit 16 pins INPUT/OUTPUT pour 2 broches utilisées sur l’Arduino.
Cependant, le principe adopté ici consiste en deux zones de capteurs, ceux qui font des demandes d’actions et ceux qui ferment les barrières.
Les premiers gèrent un compteur qui s’incrémente pour chaque arrivée d’un train sur le passage à niveau et qui se décrémente pour chaque sortie de train du passage à niveau. Ces capteurs sont donc directement liés au nombre de voies d’arrivées/départs du passage à niveau. On ne peut donc les restreindre.
Par contre les capteurs qui ferment le passage ne sont pas liés au nombre de voies qui entourent le passage à niveau, on peut donc les regrouper en un seul capteur équivalent. Cela peut se faire par un « ET câblé » sur l’ensemble de ces capteurs, ce qui va limiter le nombre de pins utilisés sur l’Arduino.

ET câblé

La seconde optimisation est lorsque l’on considère une voie unidirectionnelle, dans ce cas le capteur de fermeture de sortie n’a aucun rôle, on peut donc le supprimer, ce qui limite le nombre de capteurs réels.

Voici un exemple de voie unidirectionnelle avec trois voies d’entrée et trois de sorties. Au lieu de 12 capteurs, 9 sont suffisants et avec le ET câblé au lieu de 9 pins Arduino, seuls 7 sont nécessaires. On optimise donc sur les deux aspects : nombre de capteurs et nombre de pins Arduino.

cas d’une voie unidirectionnelle

Voici le même exemple cette fois-ci en bidirectionnel. Ici par contre on ne réduit pas le nombre de capteurs mais seulement le nombre de pins Arduino qui passe de 12 à 8.

cas d’une voie bidirectionnelle

[2Rappel des connexions du bus SPI pour le MCP2515

Arduino UNO/PRO/MINI/NANO

  • SCK = 13
  • SO = 12
  • SI = 11
  • CS = 10
  • INT = 2

Arduino MEGA

  • SCK = 52
  • SO = 50
  • SI = 51
  • CS = 53
  • INT = 2

On trouvera plus de détails sur l’utilisation du bus CAN avec Arduino dans les articles Mise en oeuvre du Bus CAN entre modules Arduino (1) et Mise en oeuvre du Bus CAN entre modules Arduino (2).