LOCODUINO

Etude d’un passage à niveau universel

Par une approche orientée objet

.
Par : Dominique, JPClaude

DIFFICULTÉ :

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
 
Si (ETAT == 0) 	// le nombre de demande est nulle, la voie est donc libre
Alors {
 	ETAT +1 ;  	// c’est forcément une arrivée
 	DIR =  vers le sens opposé à la zone ;
}
Sinon {  // la voie possède déjà au moins une demande
 	Si (DIR est la même que la zone) // c’est une sortie
	Alors {
		ETAT – 1 ;  // une demande de moins
	}	
	Sinon {   // la direction du train va dans le sens opposé de la zone
	Alors {  // c’est une arrivée
		ETAT + 1 ;
		DIR =  vers le sens opposé à la zone ;
		}
}

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
Si (ETAT >0 & DIR == sens opposé à la zone & barrière ouverte) {
	on ferme la barrière ;
}

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

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 :

  • Bounce2
  • SPI
  • mcp.can

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 :

virtual type nomFonction(signature)=0 ;

Constructeur :

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 :

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

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

void ouverture(); 	// méthode qui commande l’ouverture de la barrière
void fermeture(); 	// méthode qui commande la fermeture de la barrière
void manoeuvre(); 	// méthode qui commande le déplacement de la barrière
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 :

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 :

void ouverture(); 	// ouvre la barrière
void fermeture(); 	// ferme la barrière
void manoeuvre(); 	// simulation de la manœuvre d’ouverture
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 :

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 :

void ouverture(); 	// ouvre la barrière
void fermeture(); 	// ferme la barrière
void manoeuvre(); 	// manœuvre d’ouverture
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 :

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 :

void ouverture(); 	// ouvre la barrière
void fermeture(); 	// ferme la barrière
void manoeuvre(); 	// manœuvre d’ouverture
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 INO l’instanciation des servos  (Servo servo1) ;
et dans le setup faire l’attachement des servos
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 :

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 :

void ouverture(); 	// ouvre la barrière
void fermeture(); 	// ferme la barrière
void manoeuvre(); 	// manœuvre d’ouverture
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 :

feux(int pin, bool cde) ; 
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 :

int broche(); 	// renvoie la pin des feux du passage à niveau
void ON(); 	// allume les feux
void OFF(); 	// éteint les feux
bool etatON(); 	// vrai si en phase ON
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 :

capteur(int pin);
capteur(int pin,char* nom);
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 :

int broche(); 		// renvoie la broche du capteur
String nom(); 		// renvoie le nom du capteur
bool actualiser();	// mise à jour du capteur
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 :

zone(char* nom);

  • nom : un nom

Méthodes :

bool add(capteur&);	// ajoute un capteur a la zone
void print(); 		// affiche la configuration de la zone, si mode console
char* nom; 		// renvoie le nom de la zone
bool actualiser();	// met à jour les capteurs de la zone
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 :

voie();
voie(char* nom);
  • nom : un nom

Méthodes :

char* nom();	// renvoie le nom de la voie
int etat(); 	// renvoie l’état de la voie, nombre de demandes de passage
bool demandeFermeture();// renvoie si il y a une demande de fermeture (vrai si demande)
void config(zone1,zone2,zone3,zone4,nom(optionnel));	
	// les 4 zones, un nom (optionnel)
	// pour la configuration d’une voie bidirectionnelle; 
void config(zoneGauche, zoneFerme, zoneDroite, char* name);	
	// les 3 zones et un nom (optionnel)
	// pour la configuration d ’une voie unidirectionnelle; 
bool print(); 	// affiche la configuration, si mode console
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 :

passage(feux &fanal ) ;  
passage(feux &fanal, char* nom ) ;  
passage(barriere &barrier) ;  
passage(barriere &barrier, char* nom) ;  
passage(barriere &barrier,feux & fanal) ; 
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 :

void add(voie& _voie); // ajoute une voie au passage à niveau
void addCAN(int CS,int debit, int mode, int IDlocal, int IDdistant); 
	// 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
void updateCAN(); 	// mis à jour du bus CAN
void print(); 		// affiche la configuration du passage à niveau, si mode console
void reception(); 	// affiche les messages reçus, si mode console
void emission(); 	// affiche les messages émis , si mode console
char*nom(); 		// renvoie le nom du passage a niveau
void Loop(); 		// boucle sur l’ensemble de la configuration, 
	// détermine le fonctionnement du passage à niveau
void addReset(pin);	// ajoute la pin reset au passage à niveau 
	// 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 :

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 :

bool init(int filtre, int ID); 		// initialise le bus CAN
void receptionMessage(); 		// réception des messages depuis le bus
bool lireCode(unsigned char& code);// réception d’un code depuis le TCO
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 :

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

Constructeur :

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

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

bool init(int masque,int filtre) ;
bool init(int mask0, int filter0, int filter1, int mask1, int filter2, int filter3, int filter4, int filter5) ;
void receiveMessage() ; 		// reception des messages depuis le bus
bool readMessage (messageCAN & message) ; // lecture d’un message CAN
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

#include "includes.h"  // inclus l'ensemble des classes utiles

#define CONSOLE		// à enlever si pas d’affichage
#define DEDIT_CONSOLE 9600

/*********************************************
 * parametres du bus CAN
 * *************************************************/
 
#define CS 10                   // la broche CS 10: NANO/MINI/UNO, CS = 53 : MEGA
#define DEBIT 500               // debit du bus
#define ID_MODE 0               // 0 : mode normal, 1 : mode etendu
#define ID_LOCAL 0x01           // ID du passage a niveau
#define ID_DISTANT 0x02         // ID du TCO

/*************************************************
 * l'interruption pour le bus CAN
 * ****************************************************/
 
volatile bool FlagReceive = false;
void CAN_ISR(){FlagReceive = true;}

/**************************************************
 * definition des capteurs (pin, nom) en pull_up
 ***************************************************/

capteur CDG1(3,"Dde voie1 gauche");         
capteur CFG1(5,"Fermeture voie1 gauche");
capteur CFD1(7,"Fermeture voie1 droite");
capteur CDD1(A1,"Dde voie1 droite");
capteur CDG2(4,"Dde voie2 gauche");
capteur CFG2(6,"Fermeture voie2 gauche");
capteur CFD2(8,"Fermeture voie2 droite");
capteur CDD2(A0,"Dde voie2 droite");

/***********************************************************
 * definition des zones de detection (nom)
 ***********************************************************/
 
zone zone1GaucheDde("demande Gauche");
zone zone1GaucheFerme("fermeture Gauche");
zone zone1DroiteDde("demande Droite");
zone zone1DroiteFerme("fermeture Droite");
zone zone2GaucheDde("demande Gauche");
zone zone2GaucheFerme("fermeture Gauche");
zone zone2DroiteDde("demande Droite");
zone zone2DroiteFerme("fermeture Droite");

/************************************************
 * instances de voie tranversant le passage
 ******************************************************/
voie voie1; 
voie voie2;

/*********************************************************
 * definition de la barriere a relais (pin ouvre, pin ferme, delai activation)
 * commenter les versions non utilisées (ici test avec relais)
 *********************************************************/
 
relais cdeRelais(A2,A3,LOW,5000);    
// HIGH : relais active au plus, LOW : relais active au moins

//bobine cdeBobines(A2,A3,LOW,500,4000); // HIGH : bobine active au plus, LOW : bobine active au moins

//pas_a_pas cdeSteps(A2,A3,A4,A5,90,5000);// les 4 pins, ouverture en degre, vitesse de deplacement en us   
 
//Servo servo1;
//Servo servo2;
//servomoteur cde1Servo(servo1,A2,1000,2000,20,75);
//servomoteur cde2Servos(servo1,A2,servo2,A3,1000,2000,20,75);

/***********************************************************
 * definition des feux (pin, cde, pas du fading)  // pas = 10 par defaut
 *************************************************************/

feux fanal(9, LOW);         // high : actif au plus, LOW actif au moins

/**********************************************************
 * definition du passage a niveau (barriere,feux,nom)
 ********************************************************/

passage PAN(cdeRelais,fanal,"PN Locoduino bus CAN");

/******************************************************
 * definition de la pin RESET
 ***********************************************************/

int pinReset = A6;

b) Le setup

void setup() {

 /***************************************************
  * pour le bus CAN
 *******************************************************/
 
  PAN.addCAN(CS,DEBIT,ID_MODE,ID_LOCAL,ID_DISTANT);
  attachInterrupt(0,CAN_ISR,FALLING);
  
 /************************************************************************
  * affectation des capteurs aux zones de detection
  **************************************************************************/
  
  zone1GaucheDde.add(CDG1);
  zone1GaucheFerme.add(CFG1);
  zone1DroiteDde.add(CDD1);
  zone1DroiteFerme.add(CFD1);
  zone2GaucheDde.add(CDG2);
  zone2GaucheFerme.add(CFG2);
  zone2DroiteDde.add(CDD2);
  zone2DroiteFerme.add(CFD2);

  /******************************************************************
   * affection des zones aux voies
   ************************************************************************/
   
voie1.config(zone1GaucheDde,zone1GaucheFerme,zone1DroiteDde,zone1DroiteFerme,"voie1");
voie2.config(zone2GaucheDde,zone2GaucheFerme,zone2DroiteDde,zone2DroiteFerme,"voie2");

/*******************************************************************
 * affectation des voies au passage a niveau
 **************************************************************************/

  PAN.add(voie1);PAN.add(voie2);

  /********************************************************
   * attachement de  la pin reset
   *************************************************************/

  PAN.addReset(pinReset);

/***************************************************
 * affichage de la configuration
 ******************************************************/
 
 #ifdef CONSOLE
  Serial.begin(DEDIT_CONSOLE);   // la console
  Serial.println(F("Configuration du passage a niveau"));
  Serial.println();
  PAN.print();
  Serial.println();
 #endif
}

c) La boucle

void loop() {

if (FlagReceive) {
    FlagReceive = false; 
    PAN.updateCAN();  // mise a jour du bus CAN
    }    
PAN.Loop();              // on boucle sur le passage a niveau
#ifdef CONSOLE
  PAN.reception();                                          // affiche les messages reçus
  PAN.emission();                                           // affiche les messages émis
 #endif
}

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

#include "CANbusInterface.h"   // interface simplifiant l'utilisation du bus CAN
// option pour la console
#define CONSOLE                     // a supprimer pour une utilisation autonome 
#define DEBIT_CONSOLE 9600          // debit pour la console      

/******************************************************** 
*  parametres du bus CAN
*********************************************************/
 
#define CS 10                     // la broche CS 10 pour NANO/MINI/UNO, 53 pour MEGA
#define DEBIT 500                 // debit du bus CAN
#define ID_MODE 0                 // mode 0 : normal, 1 : etendu
#define ID_DISTANT 0x01          // ID du passage a niveau
#define ID_LOCAL 0x02            // ID du TCO
#define MASK 0xFFF               // masque integral, on ne prend que l'ID du passage a niveau

// les codes des commandes
#define RESET 0x01              // code emission du du reset
#define TRIAGE_ON 0x02          // code emission triage ON
#define TRIAGE_OFF 0x03         // code emission triage OFF
#define RESET_CONF 0x04         // code reception confirmation reset
#define TRIAGE_ON_CONF 0x05     // code reception confirmation triage ON
#define TRIAGE_OFF_CONF 0x06    // code reception confirmation triage OFF
#define LED_ON 0x07             // code reception led ON
#define LED_OFF 0x08            // code reception led OFF

// une instance du bus CAN
CANbusInterface can(CS,DEBIT,ID_MODE);

// les messages pour le bus CAN
messageCAN messageR;
messageCAN messageS;

/********************************************************
* les composants du TCO
* *********************************************************/

// bouton pour le mode triage
int pinCdeTriage = 3;
bool triage = false;

// bouton pour le reset
int pinCdeReset = 4;
bool reset =  false;

// led temoin de l'etat du passage a niveau
int pinLed = 5;

// led temoin du mode triage
int pinTriage = 6;

b) Les méthodes pour le bus CAN

/********************************************************
 * les methodes du bus CAN
 **********************************************************/

/////////   la routine d'interruption du bus CAN

volatile bool FlagReceive = false;  // drapeau d'IT du bus CAN
void MCP2515_ISR() {FlagReceive = true;} // mise a jour du drapeau d'IT sur arrivee d'un message

///////////   initialisation du bus CAN

void initCAN () {
  while (true) {
    if (can.init(MASK,ID_LOCAL)) {
      attachInterrupt(0,MCP2515_ISR,FALLING);        // attachement de la routine d'IT sur la pin 2 (IT0)
        #ifdef CONSOLE
          Serial.println(F("Initialisation reussie"));

        #endif
      break;}
    else {
      #ifdef CONSOLE
        Serial.println(F("initialisation impossible"));
        Serial.println();
      #endif
      }
  }
}

///////    / gestion des codes recus depuis le passage a niveau

void processMessage() 
          {
      switch (messageR.buf[0]) {
        case RESET_CONF : {digitalWrite(pinTriage,HIGH);digitalWrite(pinLed,HIGH);      // confirmation de reset
                          #ifdef CONSOLE
                          Serial.println(F("TCO <== PAN : CONFIRMATION RESET"));
                          #endif
                          break;}
        case TRIAGE_ON_CONF : {digitalWrite(pinTriage,LOW);                           // confirmation du mode triage
                          #ifdef CONSOLE
                          Serial.println(F("TCO <== PAN : CONFIRMATION MODE TRIAGE ACTIF"));
                          #endif
                          break;}
        case TRIAGE_OFF_CONF : {digitalWrite(pinTriage,HIGH);                         // confirmation arret du mode normal
                        #ifdef CONSOLE
                        Serial.println(F("TCO <== PAN : CONFIRMATION MODE TRIAGE INACTIF"));
                        #endif
                        break;}
        case LED_ON : {digitalWrite(pinLed,LOW);                                    // led temoin allumee
                      #ifdef CONSOLE
                      Serial.println(F("TCO <== PAN : BARRIERES FERMEES"));
                      #endif
                      break;}
        case LED_OFF : {digitalWrite(pinLed,HIGH);                                  // led temoin eteinte
                      #ifdef CONSOLE
                      Serial.println(F("TCO <== PAN : BARRIERES OUVERTES"));
                      #endif
                      break;}
      }
}

//////////// envoie des messages CAN au passage a niveau

void sendMessage() {
// test si envoie d'une demande de mode triage
  if ((digitalRead(pinCdeTriage) == LOW) && (!triage)) {messageS.buf[0] = TRIAGE_ON; can.writeMessage(messageS); 
                                                         #ifdef CONSOLE
                                                         Serial.println(F("TCO ==> PAN :  MODE TRIAGE ACTIF")); 
                                                         #endif
                                                         triage = true;}
                                                         
  // test si envoie de l'arret du mode triage
  if ((digitalRead(pinCdeTriage) == HIGH) && (triage)) {messageS.buf[0] = TRIAGE_OFF; can.writeMessage(messageS);
                                                        #ifdef CONSOLE
                                                        Serial.println(F("TCO ==> PAN :  MODE TRIAGE INACTIF"));
                                                        #endif
                                                        triage = false;}
                                                                                                               
   // test si envoie d'un reset                             
  if ((digitalRead(pinCdeReset) == LOW)&& (!reset)) {messageS.buf[0] = RESET; can.writeMessage(messageS);
                                                        digitalWrite(pinTriage,HIGH); 
                                                        digitalWrite(pinLed,HIGH);
                                                        #ifdef CONSOLE
                                                        Serial.println(F("TCO ==> PAN : RESET")); 
                                                        #endif
                                                        reset = true;}
                                                        
   // stop le reset
  if (digitalRead(pinCdeReset) == HIGH) {reset = false;}
}
/**************************************************
 * affichage de la configuration
 *************************************************/

void affiche() {
  Serial.println(F("Configuration du TCO du passage a niveau"));
  Serial.println();
  Serial.print(F("switch du mode triage sur pin : pin")); Serial.println(pinCdeTriage);
  Serial.print(F("bouton reset sur pin : pin")); Serial.println(pinCdeReset);
  Serial.print(F("Led temoin passage ferme sur pin : pin")); Serial.println(pinLed);
  Serial.print(F("Led temoin mode triage ON sur pin : pin")); Serial.println(pinTriage);
  Serial.println();
 }

c) Le setup

void setup() {

  /********************************************
   * pour la console
   ***********************************************/
   
  #ifdef CONSOLE
  Serial.begin(DEBIT_CONSOLE);
  affiche();
  #endif

  /*************************************************
   * initialisation des broches
   ******************************************************/
   
  pinMode(pinCdeTriage,INPUT_PULLUP);
  pinMode(pinCdeReset,INPUT_PULLUP);
  pinMode(pinLed,OUTPUT); digitalWrite(pinLed,HIGH);
  pinMode(pinTriage,OUTPUT); digitalWrite(pinTriage,HIGH);

  /*******************************************************
   * initialisation du bus CAN
   *******************************************************/
   
  initCAN();
  
  //preformattage des messages CAN 
  
  messageS.id = ID_DISTANT;       // un seul ID, le passage a niveau
  messageS.len = 1;               // une donnee sur un octet, le code
}

d) La boucle

void loop() {

  /***********************************************************
   * reception des messages du bus CAN
   ************************************************************/
   
  if (FlagReceive) {
    FlagReceive = false; 
    can.receiveMessage();
  }   // si message recu du bus les mettre dans le buffer circulaire

  /***************************************************************
   * lecture des messages arrivees en attente
   *****************************************************************/
   
  if (can.readMessage(messageR)){
    processMessage();
  }  // si message en attente de traitement
  
/********************************************************************
 * envoie des commandes au passage à niveau
 ******************************************************************/
 sendMessage();
}

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).

6 Messages

  • Etude d’un passage à niveau universel 17 octobre 2019 19:56, par Frederic Cudel

    Bonjour,

    Pour la commande des servomoteurs, je suis perdu
    Les paramètres d’appel font références aux sorties analogiques A2 et A3 et pas aux sorties PWM
    J’utilise des servos de type SG90

    Merci pour vos éclaircissements

    Frederic

    Répondre

    • Etude d’un passage à niveau universel 18 octobre 2019 10:12, par Dominique

      Les pins A2 et A3 peuvent être analogiques en entrée ou digitales et seulement digitales en sortie. Là elles sont utilisées en digital pour commander des relais en tout ou rien. Si vous voulez commander des servos en PWM, vous devez changer l’affectation des pins de l’Arduino selon vos besoins.

      Répondre

  • Etude d’un passage à niveau universel 18 octobre 2019 18:33, par Frederic Cudel

    Bonjour,

    Merci pour votre réponse votre site est très didactique, la prise en main de l’arduino dans ce contexte n’est pas forcement simple lorsque l’on débute dans ce domaine, et moyennant une bonne lecture on peut progresser rapidement
    Mon passage à niveau est prévu pour un train de jardin LGB, évolution vers une voie en double sens(en mode analogique pour le moment)
    Les servos SG90 fonctionnent bien sur les sorties 2 et 4
    J’ai remarqué que certains servos ne fonctionnaient pas correctement, je ne m’explique pas le phénomène avec des mouvements aléatoires
    Il me reste à gérer la sonorisation du PaN, je crois que vous avez publié quelque chose sur ce sujet

    Encore merci pour vos précieux conseils

    Frédéric CUDEL

    Répondre

  • Etude d’un passage à niveau universel 19 octobre 2019 17:30, par Frederic Cudel

    Bonjour,

    Oui cela se produit avec certains servos et pas d’autres
    Ils sont tous identiques et classiques de type SG90 achetés dans le même lot
    je vais écrire un bout de code pour les tester individuellement (j’en ai 2 sur 5 qui fonctionnent correctement)
    Le code utilisé est celui du projet passage à niveau universel LOCODUINO PN testlocal que j’ai adapté pour mon usage (c’est à dire une seule voie sans TCO avec 4 interrupteurs ILS et deux servos synchrones pour les barrières et LED de signalisation)
    Le fonctionnement est parfaitement conforme aux spécifications de votre article et très satisfaisant
    Les 2 servos sont connectés sur les sorties 2 et 4 de ma carte UNO, une alimentation 5V stabilisée est dédiée pour les servos avec masse commune sur le gnd de la carte UNO
    La commande de servos est writeMicroseconds avec la valeur angle passée comme argument)
    L’angle de rotation est de 90 degré conforme à mes position ouvert / fermé de barrière
    Je vais investiguer et je vous ferai un retour, cela pourrait être utile pour d’autres membres du forum qui travailleraient sur le même projet
    J’ai eu de la chance d’avoir lors de mes essais un servo sur deux qui se comportait de manière adaptée, plus facile pour le debugage ... Cela m’a permis de voir que le problème était indépendant de la sortie de la carte en procédant par échange de servo
    Peut être un problème sur le driver du servos / valeurs envoyées par la commande

    Merci pour vos retours

    Frédéric CUDEL

    Répondre

  • Etude d’un passage à niveau universel 15 mars 2020 16:09, par jacques

    Bonjour,
    J’essai de réaliser le passage à niveau universel. N’étant pas informaticien, je suis bloqué ! Je n’ai pas trouvé sur le site comment organiser les différents blocs de programme. Alors, j’ai mis tous les programmes dézippés dans un même fichier appelé TestLocal. La compilation ne se fait pas et je récupère une liste d’erreurs abominable !!
    Pouvez-vous m’indiquer comment organiser les différents sous programmes ?

    Merci d’avance
    Cordialement

    Voir en ligne : Etude d’un passage à niveau universel

    Répondre

Réagissez à « Etude d’un passage à niveau universel »

Qui êtes-vous ?
Votre message

Pour créer des paragraphes, laissez simplement des lignes vides.

Lien hypertexte

(Si votre message se réfère à un article publié sur le Web, ou à une page fournissant plus d’informations, vous pouvez indiquer ci-après le titre de la page et son adresse.)

Rubrique « Projets »

Les derniers articles

Les articles les plus lus