LOCODUINO

Aide
Forum de discussion
Dépôt GIT Locoduino
Flux RSS

mardi 19 mars 2024

Visiteurs connectés : 36

SGDD : Système de Gestion DD (3)

Test du bus CAN

.
Par : DDEFF

DIFFICULTÉ :

Cet article fait suite aux articles SGDD : Système de Gestion DD (1) et SGDD : Système de Gestion DD (2).

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.

<

Les essentiels du bus CAN :

Le bus CAN a déjà fait l’objet d’articles sur Locoduino Mise en oeuvre du Bus CAN entre modules Arduino (1) et Mise en oeuvre du Bus CAN entre modules Arduino (2), mais j’y ajouterai la communication entre deux bibliothèques différentes, du fait des processeurs SAM et AVR qui sont différents, et une autre structure des messages.

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.

   
//-------------------------- Up_down --------------------------------
void up_down (byte ordre, byte pin_bouton)
{
    mesure[ordre]        = analogRead(ordre + pin_bouton);
    nombre_mesures[ordre] = nombre_mesures[ordre] + 1;
    
    if (((tension_moyenne[ordre] > 750) 
       || (tension_moyenne[ordre] < 250))
    && (nombre_mesures[ordre] > 2))
    {
        tension_finale[ordre]   = tension_moyenne[ordre];
        nombre_mesures[ordre] = 0;
        tension[ordre]        = 0;
        valid[ordre]          = true;
    }
    else
    {
        tension[ordre]        = tension[ordre] + mesure[ordre];
        tension_moyenne[ordre] = tension[ordre] / nombre_mesures[ordre];    
    }
}


Le principe est très simple :

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.

   
            if (compteur_aiguille[numero_aiguille] == 0)
            {
                if ((droite[numero_aiguille] == true)
                  || (position_aiguille[numero_aiguille] == 0))
                {
                    position_aiguille[numero_aiguille] = 0x80;
                    droite[numero_aiguille] = true;
                }
                else
                {
                    position_aiguille[numero_aiguille] = 0x40;
                    droite[numero_aiguille] = false; 
                } 
                compteur_aiguille[numero_aiguille] = 1; 
                valid_aiguille = true;
            }
            if (compteur_aiguille[numero_aiguille] == 2)
            {
                if ((droite[numero_aiguille] == true) ||
                   (position_aiguille[numero_aiguille] == 0))
                {
                    position_aiguille[numero_aiguille] = 0x40;
                    droite[numero_aiguille] = true;
                }
                else
                {
                    position_aiguille[numero_aiguille] = 0x80;
                    droite[numero_aiguille] = false; 
                }
                compteur_aiguille[numero_aiguille] = 0;
                valid_aiguille = true;
            }

Cas de l’Arduino DUE :

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.

12 Messages

Réagissez à « SGDD : Système de Gestion DD (3) »

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 »

LaBox, Une Centrale DCC polyvalente et abordable (1)

LaBox, Une Centrale DCC polyvalente et abordable (2)

LaBox, Une Centrale DCC polyvalente et abordable (3)

Comment piloter trains et accessoires en DCC avec un Arduino (1)

Comment piloter trains et accessoires en DCC avec un Arduino (2)

Comment piloter trains et accessoires en DCC avec un Arduino (3)

Comment piloter trains et accessoires en DCC avec un Arduino (4)

La PWM : Qu’est-ce que c’est ? (1)

La PWM : Qu’est-ce que c’est ? (2)

La PWM : Qu’est-ce que c’est ? (3)

La PWM : Qu’est-ce que c’est ? (4)

Mise en oeuvre du Bus CAN entre modules Arduino (1)

Mise en oeuvre du Bus CAN entre modules Arduino (2)

Un gestionnaire en C++ pour votre réseau (1)

Un gestionnaire en C++ pour votre réseau (2)

Un gestionnaire en C++ pour votre réseau (3)

Un gestionnaire en C++ pour votre réseau (4)

Réalisation de centrales DCC avec le logiciel libre DCC++ (1)

Réalisation de centrales DCC avec le logiciel libre DCC++ (2)

Réalisation de centrales DCC avec le logiciel libre DCC++ (3)

Contrôleur à télécommande infrarouge pour centrale DCC++

Gestion d’une gare cachée (1)

Gestion d’une gare cachée (2)

Gestion d’une gare cachée (3)

La carte Satellite V1 (1)

La carte Satellite V1 (2)

La carte Satellite V1 (3)

La carte Satellite V1 (4)

La carte Satellite V1 (5)

Chenillard de DEL

Enseigne de magasin

Feux tricolores

Multi-animations lumineuses

L’Arduino et le système de commande numérique DCC

Un décodeur d’accessoire DCC versatile basé sur Arduino

Un moniteur de signaux DCC

Une barrière infrarouge

Un capteur RFID

Un TCO xpressnet

Une animation sonore

L’Arduino au coeur des systèmes de pilotage analogiques ou numériques

Calcul de la vitesse d’un train miniature avec l’Arduino

La génèse d’un réseau 100% Arduino

Une horloge à échelle H0

Simulateur de soudure à arc

Un automatisme de Passage à Niveau

Automatisation du pont FLEISCHMANN 6152 (HO) avec un ESP32 (1)

Identifier et localiser vos trains avec le RFID/NFC et un bus CAN.

Etude d’un passage à niveau multivoies

La rétro-signalisation sur Arduino

Décodeur pour aiguillage à solénoïdes sur Arduino

Un décodeur DCC pour les signaux à deux ou trois feux sur Arduino NANO/UNO

Etude d’un passage à niveau universel

Réalisation pratique d’un système de mesure de vitesse à l’échelle N

Une Passerelle entre le bus S88 et le bus CAN pour la rétro signalisation

Un décodeur DCC pour 16 feux tricolores

Block Automatique Lumineux avec la carte shield "Arduino 4 relays"

Réalisation d’un affichage de gare ARRIVEE DEPART

Ménage à trois (Ordinateur, Arduino, réseau)

Réalisation d’un va-et-vient automatique et réaliste

Souris et centrale sans fil

Communications entre JMRI et Arduino

Annonces en gare avec la RFID

Une croix de pharmacie animée avec Arduino UNO

Réalisation d’un wagon de mesure (distance et vitesse)

Passage à niveau géré par Arduino (1)

Passage à niveau géré par Arduino (2)

Passage à niveau géré par Arduino (3)

Passage à niveau géré par Arduino (4)

Passage à niveau géré par Arduino (5)

Une manette simple et autonome pour LaBox

Éclairer le réseau (1)

Éclairer le réseau (2)

Block Automatique Lumineux à 8 cantons analogiques

Un décodeur DCC pour les plaques tournantes Fleischmann et Roco

Éclairer le réseau (3)

Éclairer le réseau (4)

Éclairer le réseau (5)

JMRI pour Ma première centrale DCC

Rocrail pour Ma première centrale DCC

CDM-Rail pour Ma première centrale DCC (1)

CDM-Rail pour Ma première centrale DCC (2)

Banc de test pour les décodeurs DCC

Ma première manette pour les aiguillages DCC

Mon premier décodeur pour les aiguillages DCC

Boitier 3D pour la station DCC minimale

Va-et-vient pour deux trains

Un programme pour régler facilement les servos moteurs avec un ESP32

Affichage publicitaire avec Arduino (1)

Affichage publicitaire avec Arduino (2)

TCO Web interactif avec des ESP32 et des ESP8266 (1)

TCO Web interactif avec des ESP32 et des ESP8266 (2)

TCO Web interactif avec des ESP32 et des ESP8266 (3)

TCO Web interactif avec des ESP32 et des ESP8266 (4)

TCO Web interactif avec des ESP32 et des ESP8266 (5)

Les derniers articles

LaBox, Une Centrale DCC polyvalente et abordable (3)


Thierry

LaBox, Une Centrale DCC polyvalente et abordable (1)


Thierry

LaBox, Une Centrale DCC polyvalente et abordable (2)


Dominique, msport, Thierry

Un programme pour régler facilement les servos moteurs avec un ESP32


bobyAndCo

TCO Web interactif avec des ESP32 et des ESP8266 (5)


utpeca

TCO Web interactif avec des ESP32 et des ESP8266 (4)


utpeca

TCO Web interactif avec des ESP32 et des ESP8266 (3)


utpeca

TCO Web interactif avec des ESP32 et des ESP8266 (2)


utpeca

TCO Web interactif avec des ESP32 et des ESP8266 (1)


utpeca

Affichage publicitaire avec Arduino (2)


catplus, Christian

Les articles les plus lus

Réalisation de centrales DCC avec le logiciel libre DCC++ (3)

La PWM : Qu’est-ce que c’est ? (1)

La rétro-signalisation sur Arduino

Block Automatique Lumineux à 8 cantons analogiques

Réalisation d’un va-et-vient automatique et réaliste

Mon premier décodeur pour les aiguillages DCC

Chenillard de DEL

Réalisation de centrales DCC avec le logiciel libre DCC++ (1)

LaBox, Une Centrale DCC polyvalente et abordable (1)

Mise en oeuvre du Bus CAN entre modules Arduino (2)