Maintenant que nous avons un "cerveau" pour commander nos trains, il va falloir le doter d’une moelle épinière (le bus CAN) et d’organes sensoriels ou de commande (les modules).
Dans cet article, je vais m’attacher à décrire la façon d’utiliser le bus CAN en réalisant une maquette de test et ses programmes associés.
Il n’est pas nécessaire d’avoir lu les articles précédents, mais l’architecture décrite auparavant sera en trame de fond des programmes de tests qui auront pour vocation d’être intégrés dans le programme général.
Dans une trame CAN (on se reportera à la datasheet du MCP 2515) qui la décrit en détails (en anglais), on retiendra 3 éléments fondamentaux :
1°) Un identifiant sur 11 bits (il existe la possibilité d’avoir un identifiant sur 29 bits, sans intérêt pour nous). Cet identifiant permet de dialoguer avec 2048 objets, ce qui est plus que nécessaire ici.
J’appelle "objet" un bouton poussoir, une LED, bien sûr, mais aussi un canton, une aiguille ou un module.
2°) Des octets de données qui sont dans la trame et dont le nombre peut varier de 1 à 8.
Ce sont les informations que l’on va passer avec l’identifiant.
Par exemple, pour l’objet "module 4 aiguilles", on va pouvoir envoyer (ou recevoir) un octet par aiguille.
3°) La longueur de la trame, dans la norme, qui correspond au nombre d’octets transmis.
Pour le module aiguille, la "longueur" sera de 4 puisque l’on envoie 4 octets.
On a tout loisir d’organiser les échanges d’infos sur son réseau et cet article ne fait état que de la solution retenue pour le mien, tout comme les articles cités plus haut présentent d’autres façon de communiquer, toutes aussi personnelles.
Le matériel pour les tests :
J’ai trois Arduino à gérer :
1°) Le premier est un Arduino DUE qui est le gestionnaire ; dit aussi "cerveau".
Il reçoit des infos brutes du réseau, les traite et envoie des commandes en fonction des décisions qu’il prend.
2°) Un Arduino NANO qui fait partie du module 4 aiguilles.
Pour les tests, il a 8 LED qui correspondent aux 8 positions possibles des 4 aiguilles
Il gère aussi 4 BP (boutons poussoirs) qui simulent la présence d’un train sur l’aiguille concernée.
3°) Un Arduino NANO qui simule le module TCO.
Dans l’avenir, ce sera un MEGA, apte à gérer 64 "fonctions" (LED ou BP).
Pour les tests, il a 8 LED qui correspondent aux 8 positions possibles des 4 aiguilles
Il gère aussi 4 BP (boutons poussoirs) qui permettent de demander le changement de position des aiguilles.
Architecture simplifiée pour les tests :
Le bus CAN étant un bus d’échange de messages, chacun envoie l’information (événement ou commande) à tous les modules et chaque module prend ce qui l’intéresse.
Si la trame envoyée par le module émetteur est traitée par un autre module, ce dernier modifie un bit dans la trame (dans les bits de contrôle).
Lorsque le module émetteur voit monter ce bit, c’est que quelqu’un a traité son message et il arrête d’émettre.
Si, par contre, ce bit de contrôle ne monte pas (encombrement, défaillance, …), c’est que personne n’a traité son message et il réémet la trame, automatiquement.
Ce sont les couches basses du bus CAN qui gèrent cet accusé de réception, c’est à dire le circuit MCP2515, sans que l’on ait à s’en préoccuper. C’est transparent pour nous et c’est une bonne chose.
Je ne suis pas parti de rien : notre ami Jean-Luc a déjà traité le sujet d’une carte 6 aiguilles sur son site et particulièrement bien développé la gestion des servos pour les commander et je n’ai eu que quelques adaptations à faire pour mon réseau.
Le programme de Jean-Luc a été conçu au départ pour un PIC à 40 pattes et permet de gérer 6 aiguilles, ce qui n’est pas possible avec un NANO, si on veut les mêmes possibilités pour les aiguilles.
Autre adaptation : je gère aussi l’occupation individuelle des aiguilles.
On sera donc ici limité à 4 aiguilles par module.
Mais il serait dommage qu’un tel travail (pas moins de 16 articles !) et un tel résultat soit méconnus. Ils méritent une juste mise en lumière.
Pour cet article, je me suis inspiré de celui-ci pour l’analyse du problème, mais les programmes qui suivent sont les miens.
Concernant ce test, je ne vais décrire que ce qui est utile ici.
Trame émise par le module 4 aiguilles :
Identifiant : 11 bits de la forme 011000nnnnn
011000 : c’est un module d’aiguille que l’on pourra discriminer par un masque (pas utilisé ici).
nnnnn : les 5 bits correspondants au numéro de module.
J’ai en effet 100 aiguilles maximum, soit 25 modules de 4 aiguilles maximum. Il faut donc 5 bits pour identifier chaque module.
Pour ce test, je n’ai qu’un seul module. L’identifiant sera donc 011 0000 0001, ce qui se lit 0x301 en hexadécimal.
Quand un identifiant 0x301 sera émis sur le bus CAN, je saurais que le module 4 aiguilles numéro 1 a quelque chose à dire.
Octets de données : 1 octet par aiguille
Ici, pour les tests, je ne traite que l’occupation de l’aiguille.
Un octet pour 1 bit, c’est extrêmement luxueux. Mais ça prépare l’avenir.
J’ai décidé que l’occupation serait portée par le bit de poids fort de l’octet (le bit n°7).
Trame reçue par le module 4 aiguilles :
Identifiant : 11 bits de la forme 011001nnnnn
Ici, je n’ai qu’un module et l’identifiant sera donc 011 0010 0001, soit 0x321 en hexadécimal.
Quand un identifiant 0x321 sera émis sur le bus CAN, je saurais qu’il est destiné au module 4 aiguilles numéro 1.
Octets de données : pour le test, je "limite" à 1 octet par aiguille.
Là encore, c’est très luxueux puisqu’il n’y a que 2 informations à transmettre :
Bit n°7 à 1 = tout droit (c’est le bit de poids fort)
Bit n°6 à 1 = dévié
Seul l’un des 2 bits 6 et 7 doit être à 1. Sinon, c’est une condition d’erreur.
Trame émise par le module TCO :
Identifiant : 11 bits de la forme 0100000nnnn
nnnn pour le numéro de module de TC0.
Chaque module sera dans l’avenir géré par un MEGA.
On peut au maximum gérer 8 octets dans une trame, soit 64 bits qui tiennent bien sur un MEGA.
Que doit-on gérer au maximum ?
1°) En détection de présence, on a 100 LED (aiguilles)+ 155 LED (cantons) maximum.
2°) Pour chaque aiguille, on a au maximum :
(1 BP + 2 LED de position) x 100 aiguilles = 300 objets à gérer.
Soit un total maximum de 255 + 300 = 555 objets.
Il faut donc 555/64 = 9 MEGA et donc 4 bits pour gérer le numéro du MEGA.
Ce nombre est colossal !
Imaginez-vous : un TCO avec 100 BP et 455 LED !
Mais comme on a de la place dans la trame, il suffit de la réserver.
Ici, on n’aura qu’un seul module et l’identifiant sera donc 010 0000 0001, soit 0x201 en hexadécimal.
Quand un identifiant 0x201 sera émis sur le bus CAN, je saurais que le module TCO numéro 1 a quelque chose à dire : on a appuyé sur un BP.
Octets de données : 8 octets, dont un seul rempli. Et encore, à moitié ! Il n’y a en effet que 4 BP.
Ici, on n’aura donc à gérer que les 4 bits de poids fort (bits n°7 à 4).
Trame reçue par le TCO :
Identifiant : 11 bits de la forme 0100001nnnn
Ici, je n’ai qu’un module et l’identifiant sera donc 010 0001 0001, soit 0x211 en hexadécimal.
Quand un identifiant 0x211 sera émis sur le bus CAN, je saurais qu’on veut dire quelque chose au module TCO numéro 1 : allumer une LED.
Octets de données : 8 octets, dont 4 remplis.
J’ai choisi, pour le test, de travailler sur 4 octets (un par aiguille)
Dans chaque octet :
Le bit n°7 pour la position tout-droit
Le bit n°6 pour la position déviée
Le bit n°5 pour la présence sur l’aiguille
Cette option n’assure pas la densification optimale, mais c’est une démo et c’est plus facile à programmer.
Ce tableau résume les choix pour ce test (identifiants, nombre d’octets et, en vert, les traitements du gestionnaire) :
Passons maintenant à la partie matérielle :
On se servira avantageusement du brochage des NANO représenté par cette figure :
Cas du module 4 aiguilles :
On a, dès le départ, un certain nombre de broches qui sont imposées par le bus SPI qui communique avec la carte CAN :
Ne pas oublier les cavaliers : sur cette platine, il faut mettre les 3 et éventuellement la terminaison 120 ohms.
Puis, comme on va commander des servos pour les aiguilles, il faut réserver des broches PWM :
Comme on va récupérer la détection de présence sur une entrée analogique, on va choisir, parmi les broches analogiques :
Il reste les interrupteurs de fin de course des servos :
On notera qu’il va falloir gérer le cas de la broche 1, qu’on évite d’habitude (avec la 0) car elles sont communes avec le port USB. Mais si on n’a pas le choix, il faudra prendre soin de les débrancher (avec un strap enlevé) pendant les opérations de téléversement de logiciel.
Mais pour le test, je me suis abstenu.
Cas du module TCO :
Beaucoup de ressemblance, évidemment (bus SPI).
Ne pas oublier les cavaliers sur la platine CAN, il faut mettre les 3 et éventuellement la terminaison 120 ohms.
Pour un TCO, on n’a que des LED et des BP avec seulement un numéro d’ordre.
Gestion des BP :
Avant de se lancer dans la programmation, je vais faire un détour par un cas intéressant que j’ai résolu d’une manière originale.
Traditionnellement, on met les BP sur des entrées digitales, en utilisant la résistance pull-up de l’Arduino.
On connait le problème des rebonds, inévitables, et on utilise quasi toujours une bibliothèque (Bounce2 ou autre) pour éliminer les rebonds. Elle est basée sur le fait qu’on mesure une première fois le niveau, puis on attend quelques millisecondes (souvent 5 à 10 ms), puis on mesure une deuxième fois et on le valide s’il n’a pas changé.
Évidemment, plus on attend longtemps, plus la réponse est nette.
Là, sur une entrée analogique, on ne peut pas utiliser cette bibliothèque.
Autre contrainte : je n’avais pas envie de gérer des interruptions (ce qui n’est pas possible sur les entrées analogiques) qui auraient pu gêner celles du bus CAN.
J’ai donc trouvé une solution qui n’utilise aucune interruption et qui ne prend que le temps nécessaire à formuler une réponse claire, le plus court possible.
A chaque tour de la loop(), je fais une mesure, je compte le nombre de passages et je fais la moyenne des tensions recueillies.
Inexorablement, la moyenne va dépasser 750 par excès ou 250 par défaut.
Je saurais que j’ai un "1" si je suis entre 750 et 1023 et un "0" entre 0 et 250.
Rappelons, pour mémoire, qu’une entrée analogique donne un nombre entre 0 et 1023.
Si les rebonds sont catastrophiques (et c’est peut-être le cas des détections de présence), je mettrais plus de temps que si un BP n’a que quelques rebonds. Mais j’aurais une réponse nette.
Pour info, mes BP (neufs) n’ont que 3 ou 4 rebonds (vus à l’oscillo) et je donne le résultat en 2 ms.
Gestion de la bascule (position des aiguilles) :
Je tiens à utiliser un BP pour changer la position d’une aiguille.
Deux LED associées me donnent la position de l’aiguille au TCO.
Cela suppose de gérer une bascule, ce qui s’est révélé plus dur que prévu à programmer.
En effet, un appui trop long était interprété comme deux appuis successifs, ce qui faisait clignoter les LED (et les servos si j’avais laissé en l’état).
Ma méthode revient à trouver la parité des impulsions.
Les impulsions impaires correspondent à une position de l’aiguille et les impaires à l’autre position.
Là, pas besoin du schéma, le branchement n’a que 4 fils vers la carte CAN !
Les broches RX et TX sont référencées CANRX et CANTX sur le Due.
A noter qu’on ne croise pas : CANRX du Due va sur RX de la carte CAN et CANTX du Due sur TX de la carte CAN.
Et, là aussi c’est très simple : on ne met aucun cavalier, sauf éventuellement la terminaison 120 ohms. Cette terminaison ne doit être posée qu’aux 2 extrémités du bus CAN.
L’analyse du problème étant bien établie, il reste à programmer.
Il va, bien évidemment, y avoir 3 programmes puisqu’il y a 3 cartes Arduino.
Dans les NANO, gérés par un ATmega328, il faut utiliser la bibliothèque "CAN_BUS_Shield" (enlever le mot MASTER après téléchargement).
Dans le DUE, géré par un SAM3X8E ARM Cortex-M3, il faut utiliser la bibliothèque "due_can".
Ces deux bibliothèques s’entendent mutuellement car elles gèrent le même protocole : le standard CAN.
Leur fonctionnement interne est très différent, car le Due intègre l’équivalent du circuit MCP2515, mais c’est transparent pour nous (heureusement).
Je joins les 3 programmes, abondamment documentés, que j’espère clairs, sur les différentes fonctions, dans cette archive :
Je vous propose mêmet une video !
Je reste à votre disposition pour tout éclaircissement.