LOCODUINO

SGDD : Système de Gestion DD

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

  • SGDD : Système de gestion DD (3) 2 mars 2016 16:18, par Bern 69

    bonjour Denis
    Petites questions bêtes d’un "ignare" :
    Un bus CAN est-il toujours linéaire ? une disposition en étoile des nœuds n’est pas envisageable ?
    Par ailleurs, CAN lent et CAN rapide (pour la traction) : quelles fréquences ? quoique ma question est un peu sans fondement pour un réseau de dimensions modestes (2m par 070 en N )les temps de transmission ne doivent pas influer bcp sur le contrôle PWM

    Répondre

  • Bonjour Bernard (si c’est ça ...)

    Le bus n’est pas forcément linéaire, il peut être en étoile.
    Une seule chose est interdite : faire une boucle.
    Sur chaque branche, il doit rester une partie "en l’air" (en fait, avec une résistance de 120 Ω qui est la terminaison de la branche)
    Les débits les plus courants sont, pour le lent, de 100-125 kb/s et, pour le rapide, de 250 kb/s à 1 000 kb/s.
    Pour du 1 000 kb/s, tu peux aller jusqu’à 30 m. Donc, pas de problème pour ton réseau.

    Répondre

    • SGDD : Système de gestion DD (3) 2 mars 2016 17:22, par Jean-Luc

      Je ne pense pas. Seule la topologie en bus est admise avec un terminateur 120Ω à chaque bout. Par ailleurs, il ne faut pas multiplier les terminateurs 120Ω. Il en faut un à chaque bout et c’est tout. Sinon on diminue la résistance entre les deux fils et les contrôleurs seront à la peine pour établir un bit dominant.

      Sur un réseau de train qui est tout de même dans un espace assez restreint, il suffit de déterminer le chemin le plus court passant par les stations CAN du réseau.

      Répondre

  • SGDD : Système de gestion DD (3) 2 mars 2016 21:50, par Bern 69

    Si je comprends bien le consensus reste sujet à discussion.En fait un pb pourrait se poser si mon réseau était comparable à celui de Miniworld-lyon... Ce n’est pas le cas (malheureusement ?....) Donc tant que les distances restent "raisonnables", cad <2m, la configuration en étoile ou linéaire reste "possible" sous réserve des résultats expérimentaux ; je rejoins Claude Bernard et ma branche d’origine (Science Ex et médecine...)(bien vieux et sûrement inconnu !)
    bonsoir à tous. je vais boire ma tisane... de jouvence !

    Répondre

  • Non, je suis entièrement d’accord avec Jean-Luc.
    Il faut brancher en une seule ligne, allant de module en module et seulement une 120Ω à chaque bout.
    On n’est pas limité par la longueur (tu vas avoir du mal à trouver 30 m sous ton réseau ... :-) ).
    Le plus simple est de le faire en câble ethernet, comme je l’ai fait dans mes test (le câble blanc qu’on voit sur les photos).

    Répondre

  • Déploiement Can bus DUE 11 mars 2020 22:45, par jean-claude Chanfreau

    Bonjour,

    je suis débutant et je cherche vainement comment déployer des liaisons can avec des arduino DUE mais toutes ces fonctions et lignes de commande me sont étrangères.
    Comment arriver à intégrer ces fonctions de cette bibliothèque et savoir comment les architecturer.
    Avez vous de surcroît des exemples très explicités, des livres etc.
    J’ai lu attentivement vos articles "mise en oeuvre du bus can 1 et 2 mais même si je connais les principes généraux de ces bus comment comprendre toutes ces lignes de commande.

    D’avance merci

    Répondre

  • SGDD : Système de Gestion DD (3) 12 mars 2020 09:21, par DDEFF

    Bonjour,
    Nous sommes un site dédié à l’Arduino pour le train miniature.
    Et aussi un site "DIY" (Do It Yourself = faites-le vous mêmes)
    Donc, nous cherchons à faire progresser nos lecteurs pour qu’ils puissent eux-même accéder aux joies de la programmation.
    Cet article n’est pas une bibliothèque.
    Tel quel, il ne sert qu’à allumer des LED via un bus CAN. Mais il doit permettre à ceux qui veulent utiliser un bus CAN pour leur réseau d’avoir une base pour développer leur programme.
    Pour apprendre la programmation de l’Arduino, je vous conseille de démarrer par les bases et vous trouverez sur ce site de nombreux articles qui devraient vous faire progresser.
    Une question : vous dites "des Arduino DUE". Dans quel domaine utilisez vous plusieurs Arduino DUE ?

    Répondre

  • SGDD : Système de Gestion DD (3) 18 août 2023 15:18, par Roland

    Bonjour,
    Pour mieux comprendre le Système de Gestion DD j’essaie de télécharger les fichiers ZIP proposés dans les trois modules, mais malheureusement ces fichiers sont en échec de téléchargement.
    Est-ce que c’est du à mon portable ou que ces fichiers ne sont plus accessibles ?
    Merci de me tenir au courant.
    Roland J.

    Répondre

    • SGDD : Système de Gestion DD (3) 18 août 2023 18:05, par DDEFF

      Bonjour,
      Je n’ai pas eu de soucis de téléchargement dans les 3 modules.
      Il s’agit de modules de test de la faisabilité du bus CAN pour les trains miniatures.
      Les idées développées datent de 2016 et j’ai bien évolué depuis, sur le forum. Cherche "Le système de Denis"
      Malheureusement, notre forum a un problème actuellement (en cours de résolution).
      Denis

      Répondre

  • SGDD : Système de Gestion DD (3) 18 août 2023 15:42, par msport

    Pas de souci pour télécharger le zip programme de test 2 ...

    Répondre

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 »

Les derniers articles

Les articles les plus lus