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 (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)
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.
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 :
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 :
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 :
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 :
Documentations :
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 :
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 :
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 :
libpcan
dans /usr/lib/
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);
}
Ê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