Canbus: à la decouverte du bus CAN et du shield CanDIY

Le CanDiy Shield permet de brancher un Arduino sur un bus CAN.
CanDIY shield disponible chez MC Hobby
Ce shield permet, en autre, de brancher un Arduino sur un réseau Marklin ou sur le bus CAN d'un véhicule. Voyez un précédent article "RAILUINO : Hacker/Piloter du Marklin avec Candiy et Arduino".

Dans cet article, nous allons explorer CAN bus pour rendre la technologie plus accessible.

Vulgariser le bus CAN
Ce bus CAN, cela à l'air compliqué... mais uniquement dans les apparences.
CAN (Controller Area Controller) est un bus système de type série. principalement utilisé par les fabricants de véhicule pour transporter des informations entre les différentes unités de contrôles (les ECU / calculateurs). CAN permet à plusieurs ECU raccordé sur le même bus de communiquer à tour de rôle.
La longueur max du bus CAN dépend surtout du débit utilisé. A 10 Kbit/s, le bus peut atteindre 5000m (5 Km!) alors qu'a 1 Mbit/s cette distance est réduite à seulement 30 m (voir cet article wikipedia pour les autres débits).

CAN est maintenant disponible dans tous les véhicules et utilisé dans de nombreux autres domaines comme la communication avec les Central Station des train Marklin.

CAN utilise un signal différentiel sur deux fils:
CAN High (CANH) et CAN Low (CANL).
CAN utilise un signal différentiel, cela signifie que pour lire les bits transmis, il faut mesurer la différence de tension entre CANL et CANH.
Comme les perturbations électromagnétiques altérerons les deux fils de la même façon, la différence de tension restera identique à l'autre bout.
Les signaux différentiels sont utilisés dans les les projets devant être tolérant aux parasites et bruits présents dans l'environnement (comme dans les voitures).

Les tensions sur le CAN:
Au repos, sur un CAN standard, les signaux CANH et CANL sont à 2.5 Volts. Lorsqu'un bit doit être transmit, CAN augmente le signal CANH de 1 Volt et diminue le signal CANL de 1 Volt.
Le transceiver présent sur le périphérique CAN vérifie que les signaux CANH et CANL sont tout deux déclenchés/mouvementés. Si ce n'est pas le cas, le transciever rejettera le paquet comme "un bruit".

La tension entre CANH et CANL doit donc varier entre 3.5V et 1.5V.
  • Un bit 0 = différentiel de 2V entre CANH et CANL
  • Un bit 1 = différentiel de 0V entre CANH et CANL
La terminaison du bus:
Comme indiqué dans la documentation CAN, le bus CAN doit être terminé par une résistance de 120 Ohms (voir R1) placée entre CANH et CANL.
Broadcast des paquets:
Le standard CAN définit la structure des paquets transmis sur le bus CAN.
Il y a deux types de paquets sur un bus CAN, les paquet CAN standard et les paquets étendu (extended).
Sur un bus CAN, les paquets sont broadcastés! Tous les contrôleurs CAN sur le même réseau voient chaque paquet transmis. C'est un peu comme les paquet UDP broadcastés sur un réseau Ethernet.
Par conséquent, sur un bus CAN, n'importe quel contrôleur CAN peut espionner n'importe quel autre contrôleur. N'importe quel contrôleur CAN peut également se faire passer pour un autre contrôleur CAN.
C'est d'ailleurs cette particularité qui permet à un Arduino + logiciel Railuino de se faire passer une "Control Station Marklin" :-)

Format des paquets CAN bus:
Il y a deux types de paquets sur un bus CAN, les paquet CAN standard et les paquets étendu (dit "extended", avec un espace supplémentaire pour contenir des IDs).
CAN standard Packet - source: The Car hacker's Handbook on publicism.info

Un packet CAN bus est prévu pour transporter 8 octets de données même si le reste du paquet est assez conséquent.

Chaque paquet contient 4 éléments clés:
  • Arbitration ID - Contient l'ID du périphérique essayant de communiquer sur le bus. Le standard CAN prévoit 11 bits. Ces 11 bits permettent également d'établir la priorité du message. Si deux paquets sont envoyés en même temps sur le bus alors le paquet avec l'ID le plus bas est prioritaire.
    CAN prévoit une détection de collision et un arbitrage en cas de collision.
  • IDE (Identification Extension) - ce bit est toujours à 0 sur un paquet standard. Il est placé à 1 pour les paquets étendus.
  • DLC (Data Length Code) - Ces 4 bits permettent d'indiquer la longueur du paquet de donnée (de 0 à 8 octets).
  • Data - les données à transporter sur le bus CAN avec un maximum de 8 octets (donc 64 bits). Ceci dit, il arrive que certaines implémentations CAN forcent la taille à 8 octets quitte à faire du padding. 
les autres éléments du paquet CAN
  • SOF (Start Of Frame) - Ce bit marque le début d'un message. Il est aussi utilisé pour synchroniser les contrôleurs CAN après une période idle (de repos, sans transmission)
  • CRC - checksum CRC 16 bits (15 bits plus délimiteur) des données transmisses. Permet de détecter et corriger une erreur de transmission.
  • ACK (Acknoledgment Slot bit) - Chaque contrôleur recevant un message correcte modifie ce bit du message original indiquant qu'un message a été reçu. Si le message reçu est détecté comme incorrect (le bit ACK non modifié) alors le contrôleur d'origine renvoi le message après une reabritation.
    A noter que ce bit est accompagné d'un second bit délimiteur (Ack delimiter)
  • EOF (End of Frame) - 7 bits marquent la fin du message.
  • IFS (Inter Frame Space) - ces bits "interframe" (entre deux transmissions) permettent aux contrôleurs CAN de déplacer le message reçu dans une mémoire tampon (un buffer)
Détection de collision et arbitrage
Le protocole de communication CAN est un protocole avec détecteur de portée (carrier-sense), multi-accès avec détection de collision et arbritage de la proorité des messages (CSMA/CD+AMP). CSMA signifique que chaque contrôleur CAN sur le bus est tenu d'attendre un certain temps d'inactivité avant avant d'essayer d'envoyer un message. CD+AMP signifie que les collisions sont résolues via une arbitration binaire (qui s'applique au niveau des bits), basé sur une priorité pré-programmée dans le champs d'identification (arbitration id) de chaque message.

Plus d'information

Le CanDIY shield
Le CanDIY shield pour Arduino utilise le schéma de raccordement suivant :

Le shield utilise un MCP2515 comme contrôleur CAN et un MCP2551 comme transciever. Chacun de ces composants à un rôle précis.

Le MCP2515 - contrôleur CAN
Le MCP2155 (fiche technique) prend en charge l'émission et réception des 8 octets de données sur le BUS CAN de l'implémentation du protocol CAN en paquet standard (et paquet extended). Le contrôleur met en place un système de masque et filtres permettant de limiter le transfert vers le MCU (votre Arduino), une façon commode de limiter la charge pour votre Micro-contrôleur.
Ce contrôleur offre également des buffers (mémoire tampon) pour l'émission et la réception de message vers/depuis le bus CAN.
Le contrôleur CAN utilise un transciever (le MCP2551) pour la gestion des signaux CANH et CANL sur le bus.

Pour terminer, le contrôleur CAN MCP2515 offre une interface SPI au microcontrôleur. Interface disponible sur de nombreux micro-contrôleur (comme Arduino) et nano-ordinateur (comme le Pi).

Note:
Bien que cela ne correspond pas directement au CanDIY, j'ai trouvé la bibliothèque avr-can-lib (Universelle CAN Blibiothek) CAN pour le MCP2515, AT90CAN, SJA1000 pour AVR. Son implémentation est utile pour se faire une idée de l'implémentation interne de CAN pour MCP2515 (voir can_private.h).

Le MCP2551 - le transceiver CAN
Le MCP2551 (fiche technique) prend en charge l'interface entre le contrôleur CAN et le bus CAN (jusqu'à 1Mbits/s, ISO-11898). Il gère donc les traitement des signaux CANL et CANH et offre toute une série de protection.
Le MCP2551 permet de connecter jusqu'à 112 noeuds sur le bus.

Voici quelques caractéristiques clés:
  • protection contre les conditions de court-circuit.
  • un noeud non alimenté (ou chute de tension / brown-out) ne perturbe pas le bus CAN
  • conception immunisé contre le bruit électromagnétique
  • résistant aux effets transitoires (jusqu'à 250V selon la fiche technique)
  • capable de fonctionner avec des bus CAN 12 et 24V.
    A noter que le shield CanDIY respecte le standard CAN (mode par défaut du transciever) avec un tension de repos à 2.5V et signaux différentiels de Vrepos+1V à Vrepos-1V.
  • Capable de supporter une tension CAN jusqu'à 42V (voir fiche technique).
  • Détection des problèmes de masse.
Ce qu'il reste encore à explorer
Cet article, assez synthétique, est destiné à mettre le lecteur en confiance avec la technologie CAN.
Nous sommes loin d'avoir exploré le monde du bus CAN... d'autres articles seraient nécessaires pour aborder les paquets CAN "extended", les divers implémentations de CAN (ex: openCAN) et outils de communication (socketCAN)... et pourquoi pas, la communication de plusieurs Arduino sur un même bus CAN:-)
 
Ressource