LOCODUINO

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

samedi 27 mai 2017

43 visiteurs en ce moment

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

1ère partie : Qu’est-ce que c’est que ça ?

. Par : Dominique, Jean-Luc

Le CAN, pour Controller Area Network, est un bus initialement développé pour l’automobile mais qui, depuis s’est répandu dans d’autre secteurs comme l’avionique [1] ou comme bus de terrain dans les automatismes industriels.

Une discussion sur le bus CAN a démarré sur le Forum Locoduino, avec la conception par Jean-Luc d’une petite carte d’interface CAN "Locoduino" de 5 cm de cotés (La carte réalisée est visible sur le fil : BreakoutBoard CAN).

J’avoue que j’ai craqué pour cette carte et ce bus CAN qui me semble aujourd’hui le meilleur choix pour faire communiquer plusieurs Arduino entre eux. Dans mon réseau précédent j’avais utilisé l’I2C, certes mieux intégré au processeur mais moins facile à garantir une certaine sérénité des communications et un arbitrage "maitre-esclave" pas très pratique.

L’objet de cet article est de donner tous les ingrédients à intégrer dans votre programme pour un fonctionnement garanti des échanges entre plusieurs Arduino, cas qui se présente dans nos projets de train miniature car la répartition des tâches, matérielles avant tout, nécessite de les répartir en plusieurs cartes, avec, comme développement ultime, un central "gestionnaire du réseau" pour piloter le tout.

La première partie est consacrée à une présentation rapide du bus CAN et des principes d’échanges. Une suite est consacrée ensuite à la réalisation.

Le développement du bus CAN remonte à 1983 chez Robert Bosch, l’accessoiriste automobile. L’ISO a standardisé le CAN entre 2003 et 2013 (ISO 11898-1 à 11898-2). C’est un bus aujourd’hui largement utilisé et de nombreux fabricants de circuits intégrés proposent des composants, contrôleurs CAN indépendants ou intégrés dans des micro-contrôleurs.

Le bus CAN possède plusieurs caractéristiques intéressantes. Il est :

  • Temps-réel. C’est à dire que les temps de transmission sont déterministes et peuvent être calculés à priori.
  • Peu coûteux. Les contrôleurs CAN sont soit disponibles en tant que composant destiné à être connecté à un micro-contrôleur, soit intégrés directement dans un micro-contrôleur. La quantité de logiciel nécessaire pour le faire fonctionner est relativement succincte. Les composants CAN sont fabriqués en grand nombre, ce qui abaisse leur coût.
  • Multi-maître asynchrone. pas d’arbitre centralisé, pas d’horloge globale, une station peut émettre dès que le bus est libre.
  • Priorité entre les messages. les collisions, quand plusieurs contrôleurs CAN émettent sur le bus simultanément, sont résolues sans destruction du message le plus prioritaire.
  • Messages de taille limitée. 8 octets de données au plus.
  • Fiable :
    • Une détection d’erreur est incluse. La probabilité qu’une erreur reste non détectée est inférieure à 4,7 10-11 [2].
    • Le protocole définit une surveillance très stricte du bus.
    • La cohérence des données est garantie. Un message est soit accepté par tous les contrôleurs CAN du réseau, soit rejeté par tous.
    • Acquittement des messages par toutes les stations, le signalement d’erreur émis par une station est reçu par toutes les stations.
    • Retransmission automatique des messages après signalement d’erreur.
    • Le confinement des erreurs. Un contrôleur CAN gère de façon autonome les erreurs temporaires qu’il détecte.

Les performances

Le bus CAN propose des débits allant de 100kbits/s à 1Mbits/s.
La distance maximale entre 2 noeuds dépend de cette vitesse : 100 m à 500kb/s, ou 500 m à 125 kb/s, ce qui ne pose aucun problème pour nos réseaux, même excessivement grands !

Où trouve-t-on des bus CAN autour de nous ?

Tout d’abord dans pratiquement toutes les automobiles et c’est une tendance lourde qui favorise le développement d’automatismes de plus en plus sophistiqués (détection d’obstacles, créneaux automatiques, jusqu’à la conduite automatique expérimentée par Google, Tesla, …).

Dans les engins de chantier comme ceux de la société Caterpillar.

Dans l’aviation également.

… et de la documentation

Elle est très abondante.

Tout d’abord le Wiki ;

Pour ceux qui voudraient entrer dans les détails, il y a la fiche produit du MCP2515 de Microchip.

Initiation rapide au bus CAN

Le bus CAN est un bus série (les bits se suivent à la queue leu leu sur 2 fils). Il sert à raccorder à un même câble (un bus sous la forme d’un simple câble téléphonique par exemple) un grand nombre de calculateurs qui communiqueront donc à tour de rôle, pratiquement sans hiérarchie.

Le CAN est un bus de données série bidirectionnel half-duplex. Chaque équipement connecté, appelé « nœud », peut communiquer avec tous les autres. Chaque nœud est connecté au bus par l’intermédiaire d’une paire torsadée (blindée ou non). Les deux extrémités du bus doivent être bouclées par des résistances de 120 Ω. Les noeuds peuvent être raccordés par de simples câbles téléphoniques.

Chaque station écoute avant de parler, sans tour de parole imposé. La résolution des collisions se fait par priorité de l’identifiant, ce qu’on verra plus loin.

Toute la complexité du protocole est gérée par l’interface (le circuit externe MCP2515 dans notre réalisation sur 328 ou 2560, le Due quand à lui, en possède 2 intégrées), on n’a donc pas besoin de connaitre les détails.
Il faut simplement savoir que chaque station reçoit et émet des messages avec toutes les autres stations . Il n’y a pas de maitre ni d’esclave. Pour éviter de polluer une station par des messages qui ne la concernent pas, des filtres présentés ci-après permettent à la station de choisir ceux qu’elle attend vraiment.

Qu’est-ce qu’un message ?

Quand on construit un système avec un bus CAN, on définit une messagerie : l’ensemble des messages qui vont transiter et leur identifiant.

Les messages CAN sont courts, 94 bits maximum. Il n’y a pas d’adresse explicite donc aucun système de routage de messages entre un émetteur et un récepteur. Tout le monde reçoit tout et doit filtrer pour ne traiter que ce qui le concerne.

La partie "données" d’un message contient un identifiant de 11 bits (mode standard) ou 29 bits (mode étendu qu’on utilisera pas dans cette application) et des données de 0 à 8 octets. L’identifiant est indispensable, les données non. Dans mon application, je n’utilise pratiquement qu’un seul octet de données, en plus de l’identifiant. Seuls quelques cas spécifiques comme les messages de configuration utilisent plusieurs octets.

Comme dans tout système de transmission, il y a d’autres bits de contrôle et de calcul d’erreur qui servent uniquement au circuit d’interface MCP2515, donc il n’est pas besoin d’en parler, « ça se débrouille tout seul » !

L’identifiant joue un rôle particulièrement important : il sert à plusieurs choses :

  • l’arbitrage en cas de contention, c’est à dire quand 2 ou plusieurs messages sont émis sur le bus simultanément,
  • le filtrage, c’est à dire la possibilité pour le récepteur de ne garder que ce qui l’intéresse,
  • l’adressage qui n’est pas un adressage classique de messagerie, mais qui est utilisé dans ce but, d’abord au moyen du filtrage, puis par le récepteur pour déterminer à quel fonction le message est destiné.

En cas de contention, chaque émetteur regarde si un identifiant émis est plus prioritaire que le sien. Si oui, il stoppe d’émettre et attend son tour. Celui qui a l’identifiant le plus prioritaire continue d’émettre comme si de rien n’était. Il n’y a donc pas de perte de temps !

La règle de priorité est simple : le plus prioritaire est le plus petit !

Une autre règle en découle, qui est que 2 émetteurs différents ne doivent pas émettre de messages avec un même identifiant.

Par exemple, supposons que le Central du réseau veuille envoyer des ordres à des moteurs d’aiguillage (donc à la carte de commande d’aiguilles) et d’autres ordres à des signaux (donc à la carte de commande des signaux) et d’autres encore à la traction (donc la carte générateur du DCC   ou du PWM  ) . On va donc définir une série d’identifiants pour les messages destinés exclusivement aux commandes d’aiguille, par exemple la série de 16 identifiants de Id = 0x40 à 0x4F, une autre série d’identifiants pour les commandes de signaux, par exemple Id = 0x50 à 0x5F, et une autre pour la traction, par exemple Id 0x30 à 0x3F.

On remarque au passage qu’on ne s’intéresse qu’aux messages reçus par la carte CAN dont il faut définir les masques et les filtres.

On va rester en trame standard, donc les identifiants font 11 bits. Les valeurs de 1 à 2047 sont largement suffisantes pour tous les types de messages possibles.
Supposons qu’au maximum il y ait 19 moteurs d’aiguillage et quelques dételeurs : 5 bits suffiront dans un unique octet de message pour désigner un moteur d’aiguilles ou un dételeur, les 3 bits supplémentaires permettant de définir les types de commande qui s’appliquent aux aiguilles.

Les réponses de la carte d’aiguilles vers le gestionnaire de réseau et/ou d’autres cartes étant filtrées par leur destinataire, les Id des messages émis seront donc pris dans la liste des Id qu’elles acceptent de recevoir.

Par exemple, pour gérer mes aiguilles, les commandes reçues seront décodées en fonction de l’octet de données qui a la forme suivante :

  • les bits 0 à 5 définissent le numéro de l’aiguille ;
  • les bits 6 et 7 portent la consigne à appliquer.
  • - bit 7 = 1, bit 6 = 1 : sens « droit »
  • - bit 7 = 1, bit 6 = 0 : sens « dévié »


Comme la carte de commande d’aiguilles ne doit réagir qu’aux ordres émis par le central (avec l’Id = 0x40) et comme le TCO permet de positionner les aiguilles "à la main" avec des clés, chaque fois qu’un opérateur tournera une clé d’aiguille sur le TCO, la demande du TCO sera d’abord adressée au Central. Ce dernier devra la valider avant de l’envoyer à l’aiguille si l’opération est possible.

Dans ce schéma, le TCO enverra les même données que dans les commandes ci-dessus mais avec un Id = 0x11 (dans la plage des Id acceptés par le Central). Dès que le Central les aura validées, ce dernier les renverra alors avec l’Id = 0x40 et elles seront exécutées par la carte de commande d’aiguilles. Ensuite les réponses de la carte d’aiguilles avec l’Id = 0x12 seront reçues par le central (pour la mise à jour des tables de positions ou des objets aiguilles) et ce dernier enverra un message vers le TCO avec l’Id 0x20 pour l’allumage de la diode verte qui représente la position d’aiguille (et l’extinction de l’autre Led) à coté de la clé de commande.

Le schéma des échanges est le suivant pour une commande d’aiguille :

Demande TCO -> Id=0x11-> Central -> Commande -> Id=0x40 -> Aiguilles
Réponse état Aiguilles -> Id=0x12 -> Central -> Etat -> Id=0x20 -> TCO

Dans le projet de réseau, il faut donc étudier tous les échanges possibles et dresser le tableau des Id et des données de tous les messages.

Rappel : ce qui compte, c’est de rassembler les identifiants des messages reçus dans une plage qui permet de définir les masques et filtres de façon pratique.

Et les filtres alors ?

On l’a entrevu dans la routine de SETUP : il y a 2 masques et 6 filtres.

Les masques définissent les bits de l’identifiant qui sont significatifs (sinon ils sont ignorés par le filtre).

Les filtres font que seuls les identifiants présentés sont acceptés

Les bits du masque travaille avec les bits des filtres de même position.
Un bit « 0 » du masque permet d’accepter n’importe quel bit de l’identifiant (pas de filtre). Cela permet d’éviter de filtrer tous les bits et donc d’accepter des plages entières d’identifiants.
Un bit « 1 » du masque autorise le filtrage : pour qu’un bit de l’identifiant soit accepté, il doit être identique à celui du filtre. Tous les bits de l’identifiant doivent être acceptés pour que l’identifiant soit accepté.
Exemple :
Filtrage total pour accepter seulement l’Id = 0x317 dans un buffer

  • - Masque = 111 1111 1111
  • - Filtre = 011 0001 0111

Filtrage partiel pour accepter une plage d’Id de 0x310 à 0x317

  • - Masque = 111 1111 1000
  • - Filtre = 011 0001 0xxx

Pas de filtrage du tout

  • - Masque = 000 0000 0000
  • - Filtre = xxx xxxx xxxx

Dans mon cas, je n’ai qu’une carte de commande d’aiguilles, le masque est fixé à 0x7F0 et les filtres définissent les identifiants des seuls messages attendus : 0x40 à 0x4F.

Quel matériel faut-il pour réaliser un bus CAN ?

Tout d’abord, une interface CAN.
Les Arduino Uno, Nano, Mega (pour ne citer qu’eux) ne contiennent pas d’interface CAN. On utilise l’interface série SPI   intégrée et un couple de circuits externes :

  • MCP2515 pour la gestion du protocole
  • MCP2551 pour l’interface physique avec le réseau

Pour le Due, c’est différent !
Celui-ci contient déjà 2 interfaces CAN intégrées : c’est l’équivalent du MCP2515 qui est intégré. Mais l’interface ligne reste nécessaire, soit le MCP2551 seul, soit une carte bon marché avec un simple SN65HVD230/231/../234.

Quelle bibliothèque faut-il installer ?

De même, pour la série Uno, Nano, Mega, on utilisera la bibliothèque de Seeed-Studio CAN_BUS_Shield.

Pour le Due, on utilisera la bibliothèque Due_Can

Les détails d’installation et de mise en oeuvre sont décrits dans l’article suivant.

Comment envoie-ton un message CAN ?

La bibliothèque CAN_BUS_Shield permet d’envoyer des messages avec l’instruction CAN.sendMsgBuf(Id, ext, len, *buf) où les paramètres sont :
- Id est un identifiant de 11 bits (mode standard) ou 29 bits (mode étendu qu’on utilise pas ici),
- ext permet de choisir le format standard (valeur 0) ou étendu (non utilisé ici),
- len est le nombre d’octets du message,
- *buf est le pointeur sur le message buf[8]

Exemple avec la bibliothèque de Seeed Studio, pour envoyer un message ou « commande » avec l’Id 0x12 et contenant un seul octet de donnée :

  1. void CANMessage(byte Commande)
  2. {
  3. unsigned char bufS[8];
  4. bufS[0] = Commande;
  5. CAN.sendMsgBuf(0x12, 0, 1, bufS);
  6. }

Comment reçoit-on les messages CAN ?

C’est décrit dans la 2ème partie !

Dans la suite de cet article Mise en oeuvre du bus CAN - 2ème partie, nous décrivons tous les ingrédients logiciels nécessaires pour intégrer le bus CAN dans un projet Arduino.

On vous avait promis de ne pas vous faire attendre trop longtemps !

[1Un Airbus A380 est équipé d’une quarantaine de bus CAN destinés à diffuser les données des capteurs situés dans les ailes notamment

[2Autrement dit 1 chance sur 20 milliards

Réagissez à « Mise en oeuvre du Bus CAN entre modules Arduino (1) »

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 »

Un 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

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

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)

SGDD : Système de Gestion DD (1)

SGDD : Système de Gestion DD (2)

SGDD : Système de Gestion DD (3)

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)

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)

Les derniers articles

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


Jean-Luc

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


Christian Bézanger

Réalisation d’un affichage de gare ARRIVEE DEPART


Gilbert

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


Daniel

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


Jean-Luc

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


bobyAndCo

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


Pierre59

Un décodeur DCC pour 16 feux tricolores


Dominique, JPClaude, Thierry

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


bobyAndCo

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


Dominique

Les articles les plus lus

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

La rétro-signalisation sur Arduino

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

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

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

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

Une barrière infrarouge

Un automatisme de Passage à Niveau

Un chenillard de DEL

Réalisation d’un affichage de gare ARRIVEE DEPART