Mise en oeuvre d’un réseau de terrain CAN/NMEA2000

Expression du besoin

De plus en plus d’appareils utilisent maintenant la norme NMEA2000 pour échanger des données en réseau. La station météo mise en oeuvre ici fournit ses mesures via un bus CAN en respectant les spécifications de cette norme.

Le bus CAN

Le bus CAN (Controller Area Network) est un bus de terrain. Il couvre les couches 1 (Physique) et 2 (Liaison) du modèle OSI. La couche 7 (Application) n’est pas obligatoire. Plusieurs couches applications ont été définies sur la norme CAN comme CANOpen.

Le bus CAN est le fruit de la collaboration entre l’Université de Karlsruhe et Bosch. Il fut d’abord utilisé dans le secteur de l’automobile, mais est actuellement utilisé dans la plupart des industries comme l’aéronautique, la marine (NMEA 2000) via des protocoles standardisés basés sur le CAN. Il a été normalisé avec la norme ISO 11898.

Il met en application une approche connue sous le nom de multiplexage, et qui consiste à raccorder à un même câble (un bus) un grand nombre de calculateurs qui communiqueront donc à tour de rôle. Cette technique élimine le besoin de câbler des lignes dédiées pour chaque information à faire transiter (connexion point-à-point). Dès qu’un système (voiture, avion, réseau téléphonique…) atteint un certain niveau de complexité, l’approche point-à-point devient impossible du fait de l’immense quantité de câblage à installer et de son coût (en masse, matériaux, main d’oeuvre, maintenance).

Remarque : L’introduction des bus multiplexés (principalement le CAN) dans l’automobile avait pour objectif de réduire la quantité de câbles dans les véhicules (il y avait alors jusqu’à 2 km de câbles par voiture), mais elle a surtout permis l’explosion du nombre de calculateurs et capteurs distribués dans tout le véhicule, et des prestations correspondantes (baisse de consommation, dépollution, sécurité active/passive, confort, détection des pannes…), tout en diminuant les longueurs câblées.

Caractéristiques : (cf. fr.wikipedia.org)

  • bus de données série bidirectionnel half-duplex.
  • cablage avec une paire torsadée (blindée ou non), impédance 120 ohms.
  • nécessite des “bouchons” aux deux extrémités du bus (des résistances de 120 ohms).
  • chaque équipement connecté est appelé un noeud et communique avec tous les autres (broadcast). Le bus CAN n’utilise pas d’adressage pour les noeuds.
  • pour un bus CAN « low-speed », le nombre de noeuds est limité à 20. Pour un bus CAN « high-speed », il est limité à 30.
  • méthode d’accès CSMA/CD (Carrier Sense Multiple Access with Collision Avoidance) : écoute de chaque station avant de parler (pas de tour de parole), résolution des collisions par priorité (arbitrage sur le champ identifiant)
  • la longueur maximale du bus dépend du débit et varie entre 30 m (1 Mbits/s) à 5000 m (à 10 kbits/s).
  • encodage de type NRZ (non retour à 0).
  • système de priorité basé sur « ET câblé » où l’état logique « 0 » est l’état « dominant » et l’état logique « 1 » est l’état « récessif ».
  • brochage normalisé utilisant un connecteur DB-9 (broche 2 : CANL et broche 7 : CANH).
  • les trames possèdent un identifiant pour la donnée transportée dans le champ de données (de 0 à 8 octets max).
  • deux standards : CAN 2.0A -> CAN standard et CAN 2.0B -> CAN étendu
  • deux tailles d’identifiant : identifiant standard sur 11 bits (CAN 2.0A) et étendu sur 29 bits (CAN 2.0B)
  • 4 types de trames : données, requête, erreur et surcharge

La trame CAN :

Remarque : Le champ d’arbitrage est composé de 11 bits d’identification pour CAN 2.0A et 29 bits pour CAN 2.0B suivis par le bit RTR (Remote Transmission Request) qui est dominant pour une trame de données et récessif pour une trame de requête. Le champ de commande contient 2 bits à usage réservé et le DLC (Data Length Code) sur 4 bits (de pods faible) qui indique la longueur en octet du champ de données.

NMEA2000

La National Marine Electronics Association (NMEA), association américaine de fabricants d’appareils électroniques maritimes, définit et contrôle des normes techniques utilisables par les équipements marins qu’ils produisent.

Elle a publié les normes suivantes :

  • La norme NMEA 0183 qui utilise une simple communication série pour transmettre une “phrase” composée de caractères ASCII à un ou plusieurs écoutants.

  • La nouvelle norme, NMEA 2000 (en), qui permet plusieurs “discussions” avec un débit plus rapide.

La norme est propriétaire et payante. Toutefois, la plus grande partie du protocole a été récupérée grâce à des sources publiques et à l'utilisation de la rétro-ingénierie (reverse engineering).

Site officiel : www.nmea.org

La norme NMEA 2000 d’octobre 2001 spécifie les caractéristiques suivantes :

  • le bus CAN en mode étendu (CAN 2.0B)
  • le nombre de noeuds limité à 50
  • la longueur jusqu’à 200 m
  • le débit à 250 kbits/s
  • les identifiants sur 29 bits sont structurés et définis (PGN)
  • les données sur 8 octets

Les messages NMEA 2000 sont organisés en PG (Parameter Group) qui sont identifés par un PGN (Parameter Group Number) qui apparairaît dans le champ ID (IDentifier) d’un message CAN.

La structure des identifiants étendus (29 bits) des messages NMEA 2000 est la suivante :

  • Priorité (3 bits)
  • PGN (18 bits = 2 bits libres + 16 bits fixés par la norme)
  • Adresse source (8 bits)

Chaque appareil du réseau doit posséder une adresse source sur 8 bits. Les adresses 0 à 251 (soit un total de 252 adresses disponibles) sont réservées à cet usage. L’adresse 255 est une adresse globale qui spécifie un envoi à tous les noeuds du réseau (broadcast). Les autres adresses ont été réservées à un usage futur.

Documentations :

Station météo Maretron WSO100

La station météo Maretron WSO100 mesure la vitesse et la direction, température de l’air, la pression barométrique et l’humidité relative. La mesure du vent est réalisée en utilisant des capteurs à ultrasons, ce qui signifie qu’il n’y a pas de pièces mobiles susceptibles de s’user ou de se coincer.

La station météo Maretron WSO100 communique par bus CAN en respactant la norme NMEA 2000.

La station météo WSO100 émet cycliquement 2 messages NMEA 2000 contenant les données mesurées :

  • Wind Data (10 trames/s) contient la vitesse et la direction du vent (PGN 130306)
  • Environmental Parameters (2 trames/s) contient la température, l’humidité et la pression atmosphérique (PGN 130311)

Documentations :

PGN 130306 : Wind Data

Ce message contient la vitesse (x 10 mm/s) et la direction du vent (x 0,0001 radians). Il est identifié par le PGN 130306. Les octets de données dans la trame NMEA2000 sont transmis dans l’ordre little-endian.

Remarque : les données telles que les nombres entiers peuvent être représentées sur plusieurs octets. L’ordre dans lequel ces octets sont organisés en mémoire ou dans une communication est appelé endianness. De la même manière que certains langages humains s’écrivent de gauche à droite, et d’autres s’écrivent de droite à gauche, il existe en Informatique une alternative majeure : l’orientation big-endian et l’orientation little-endian.

Remarque : un champ qui contient la valeur 0x7FFF signifie que les données ne sont pas disponibles (data not available).

Exemple de décodage pour la direction de vent :

PGN 130311 : Environmental Parameters

Ce message contient contient la température (x 0.01 °K), l’humidité et la pression atmosphérique. Il est identifié par le PGN 130311. Les octets de données dans la trame NMEA2000 sont transmis dans l’ordre little-endian.

Remarque : les données telles que les nombres entiers peuvent être représentées sur plusieurs octets. L’ordre dans lequel ces octets sont organisés en mémoire ou dans une communication est appelé endianness. De la même manière que certains langages humains s’écrivent de gauche à droite, et d’autres s’écrivent de droite à gauche, il existe en Informatique une alternative majeure : l’orientation big-endian et l’orientation little-endian.

Remarque : un champ qui contient la valeur 0x7FFF signifie que les données ne sont pas disponibles (data not available).

Exemple de décodage pour la température :

Programmation

Pour dialoguer avec la station météo, on va utiliser l’adaptateur PCAN-USB de la société PEAK SYSTEM qui permet une connectivité aux réseaux CAN.

Le fabricant fournit une bibliothèque pcan pour Linux :

  • bibliothèque libpcan dans /usr/lib/
  • fichier d’en-tête libpcan.h dans /usr/include/

Cette API (Application Programming Interface) permettra d’accéder au fichier périphérique (/dev/pcanusb0, …).

Pour fabriquer un exécutable qui utilise la bibliothèque pcan, il faudra ajouter à l'édition de liens l'option -lpcan. Dans un projet Qt, il faudra ajouter cette ligne dans le fichier .pro : LIBS += -lpcan

Le code ci-dessous permet la connexion au réseau CAN de la station météo :

#include <libpcan.h>

HANDLE          handle; // descripteur sur l'interface
unsigned short  wBTR0BTR1; // pour fixer le débit
int             nExtended; // étendu ou standard

// préparation NMEA2000
wBTR0BTR1 = 0x011c; // 250 kbits/s -> NMEA 2000
nExtended = CAN_INIT_TYPE_EX; // Etendu -> NMEA 2000

// ouverture du périphérique 
handle = LINUX_CAN_Open("/dev/pcan0", O_RDWR);

// ouverture réussie ?
if(handle)  
{
    // initialisation réussie ?
    if(CAN_Init(handle, wBTR0BTR1, nExtended))
    {
        cout << "Connexion réussie" << endl;
    }
    else
    {
        cerr << "Erreur initialisation ! (CAN_Init)" << endl;
    }
}
else
{
    cerr << "Erreur ouverture ! (LINUX_CAN_Open)" << endl;
}

// etc ...

// fermeture du périphérique
CAN_Close(handle);

La réception des messages pourrait être assurée par la fonction suivante :

TPCANRdMsg msg; // le message CAN à recevoir
int status, erreur; 
   
if (LINUX_CAN_Read(handle, &msg)) 
{
    cerr << "Erreur réception CAN ! (LINUX_CAN_Read)\n";
    return -1;
}

if (msg.Msg.MSGTYPE & MSGTYPE_STATUS) 
{
    status = CAN_Status(handle);
    if ((int)status < 0) 
    {
        erreur = nGetLastError();
        cerr << "Erreur CAN " << erreur << " !\n";
        return erreur;
    }
}

// affichage du message CAN reçu
int pgn = (msg.ID & 0x03FFFF00) >> 8;

printf("<%u.%u> ", msg.dwTime, msg.wUsec);   

printf("message %s %d 0x%08x %1d ", 
  (msg.MSGTYPE & MSGTYPE_EXTENDED) ? "ext" : "std",
   pgn,
   msg.ID, 
   msg.LEN); 

for (i = 0; i < msg.LEN; i++)
    printf("0x%02x ", msg.DATA[i]);

printf("\n");

// etc ...

Ensuite, il suffit d’extraire et décoder les données reçues. Par exemple, le décodage de la direction du vent dans le message PGN 130306 :

int dataDirectionVent = 0;
double directionVent = 0.;

// trame Wind Data ?
if(pgn == 130306)
{
    // Attention : little endian !
    dataDirectionVent = ( ((msg.DATA[4] & 0x00FF) << 8) | (msg.DATA[3] & 0x00FF)) & 0x0000FFFF; // en rad

    printf("message.DATA[3] = 0x%02x\n", msg.DATA[3]);
    printf("message.DATA[4] = 0x%02x\n", msg.DATA[4]);
    printf("dataDirectionVent = %d\n", dataDirectionVent);

    if(dataDirectionVent == 0xFFFF)
       return 0.;
       
    directionVent = ( ((double)dataDirectionVent * 0.0001)*360./(2.*M_PI) );

    printf("directionVent = %.2f °\n", directionVent);
}

Le décodage de la température dans le message PGN 130311 :

int dataTemperature = 0;
double temperature = 0.;

// trame Environmental Parameters ?
if(pgn == 130311)
{
    // Attention : little endian !
    dataTemperature = ( ((msg.DATA[3] & 0x00FF) << 8) | (msg.DATA[2] & 0x00FF)) & 0x0000FFFF;

    printf("message.DATA[2] = 0x%02x\n", msg.DATA[2]);
    printf("message.DATA[3] = 0x%02x\n", msg.DATA[3]);
    printf("dataTemperature = %d\n", dataTemperature);

    temperature = ( ( ((double)dataTemperature*0.01) ) - 273.15 );
   
    printf("temperature = %.2f °C\n", temperature);
}

Travail demandé

Être capable d’afficher les mesures en provenance de la station météo dans une application GUI.

Remarque : l’affichage des mesures utilise des widgets de la bibliothèque qwt.

Vous devez installer la bibliothèque qwt : $ sudo apt-get install libqwt-dev

Code source fourni : activite-wso-100.zip

  1. Tester l’application fournie.
  1. Compléter le programme afin de lire et décoder les messages CAN en provenance de la station météo et afficher avec leur unité l’ensemble des données extraites et décodées.

Retour au sommaire