Ou échanger des données entre deux microcontroleurs par l’intermédiaire d’un protocole “bas niveau” existant (SPI, I2C ou RS232 par exemple).

Comment échanger des données entre deux systèmes communicants ?

NIVEAU 3

Objectifs

  • Etablir un protocole de communication de haut niveau pour échanger des données numériques entre deux noeuds

Pré-requis

Quelques ressources supplémentaires

Différentes couches protocolaires

L’échange d’informations entre deux systèmes (PC-uC ou uC-uC) repose sur la mise en place d’un protocole de communication afin que les deux systèmes (ou plus) se comprennent.

Protocoles de bas niveau

Il existe une multitude de protocoles de communication de “bas niveau” permettant de transmettre des données numériques sur un support physique :

  • Réseaux de terrain : Ethernet, RS232, SPI, I2C…
  • Réseaux de communication : Ethernet, Logical Link Control (LLC), Media Access Control (MAC), Point-to-point protocol (PPP)…

Ces protocoles permettent de garantir le transfert d’une série de données numériques, qu’on appellera trame, en normalisant certains aspects de la communication (vitesse de transfert, nombre d’octets transmis par paquet, niveaux de tension…)

Protocoles de plus haut niveau

Les protocoles précédents ne s’occupent que des informations binaires à transmettre d’un noeud A à un noeud B et leur codage, ils n’ont pas à gérer le contenu de ces paquets.

Ces contenus proviennent de couches protocolaires plus hautes.

Or pour que deux systèmes (dans l’exemple précédent, deux responsables de services différents) veulent communiquer des informations utiles, ils doivent suivre des étapes hiérarchiques particulières et des outils de communication à leur portée.

Parmi les protocoles de plus haut niveau, on peut citer le protocole Internet (IP), utilisant les protocoles de plus bas-niveau Ethernet et MAC (par exemple) et faisant appel à des couches de plus haut niveau type TCP/UDP pour la transmission de paquets sur un réseau.

Mise en place d’un protocole de communication

Définition des besoins

Avant de se lancer dans la communication inter-systèmes, il est donc intéressant de faire le point sur :

  • le type de données à transmettre
  • la quantité de données à transmettre
  • la direction de ces données (unidirectionnel ou bidirectionnel)
  • la vitesse de transmission

En fonction de ces informations, on choisira le protocole de bas niveau en conséquence.

Il faudra ensuite définir l’ordre dans lequel on envoie les différentes données et s’il est nécessaire, selon la taille des données, d’ajouter des caractères spécifiques pour séparer les données.

Acquittement et code de protection

Il est également intéressant d’ajouter au protocole de haut niveau une méthode de vérification que l’information a bien été reçue et correctement par le destinataire.

Certains protocoles de bas niveau intègrent déjà ce type de fonctionnalité (Ethernet, CAN…).

Lorsqu’on veut intégrer un acquittement dans les couches applicatives, il est alors nécessaire d’utiliser une couche physique (niveau bas de protocole) qui permette un échange bidirectionnel des informations. Par la suite, lorsqu’on transmettra une trame de données, le destinataire devra, si l’information a bien été reçue intégralement (d’où l’ajout de caractères spécifiques en début et fin de trame par exemple), il renverra une donnée de validation.

Pour garantir une meilleure efficacité de la transmission, on peut également ajouter des données supplémentaires calculées à partir des données à transmettre selon un algorithme prédéfini. On appelle cela un code correcteur d’erreur (ou au moins ici de validation des données transmises). Ces données sont également transmises, ce qui ralentit la communication utile entre les deux noeuds. Le destinataire reproduit le même calcul que l’émetteur et vérifie que la donnée est ainsi correctement arrivée sans erreur de transmission. Un acquittement est alors possible si la donnée est valide.

Exemple d’échanges entre deux systèmes

Exemple simple entre un PC et une carte Nucléo

Protocole de “haut niveau”

Dans cet exemple simple d’application, on souhaite transmettre deux caractères distincts du PC à la carte Nucléo afin d’allumer (caractère ‘a’) ou d’éteindre (caractère ‘e’) une LED placée sur la carte Nucléo. La carte Nucléo acquittera de la bonne réception par deux caractères différents : ‘o’ lorsque la LED sera allumée et ‘b’ lorsqu’elle sera éteinte.

Protocole de “bas niveau”

Pour cela, on utilisera le protocole RS232 (via la liaison USB – port série virtuel) pour transmettre les informations numériques. Sur l’ordinateur, on pourra utiliser dans un premier temps un logiciel de type “console série” qui permet de visualiser et de transmettre des caractères sur ce type de liaison. La réception des données sur la carte Nucléo se fera par l’intermédiaire d’une interruption sur la réception du port série.

Code de la carte Nucléo

#include "mbed.h"

// inputs and outputs configuration
DigitalOut  debug_led(LED1);
Serial      rs232(USBTX, USBRX);

// System functions
void ISR_get_data(void);

// Variables
char data_received = 0;

// Main function
int main() {
    rs232.baud(115200);
    rs232.attach(&ISR_get_data);
    while(1) {    }
}

void ISR_get_data(){
    data_received = rs232.getc();
    switch(data_received){
        case 'a':
            rs232.printf("o\r\n");
            debug_led = 1;
            break;
        case 'e':
            rs232.printf("b\r\n");
            debug_led = 0;
            break;
        default:
            debug_led = debug_led;            
    }
}

Programme en Python pour la commande de ce système

On peut remplacer le logiciel “console série” par une application faite de toute pièce permettant de récupérer les données sur la liaison série. L’intérêt est de pouvoir gérer au mieux les échanges et en particulier les acquittements et les erreurs de transmission possible.

On propose ici un script en Python 3.6/7 utilisant les bibliothèques pyserial pour la communication RS232 et time pour la gestion du temps. Ce code a été testé sous Windows 10. Il est probablement compatible avec d’autres versions de Python et plateformes (MAC, Linux). Ce code est téléchargeable ici : https://lense.institutoptique.fr/ressources/_projets/Spectro/IHM_PythonTkInter_RS232_simple/acquisition.py

Ce code est décomposé en 4 parties : 3 fonctions (serial_ports, sendA et sendE) et le code principal.

  • la fonction serial_ports se base sur la bibliothèque pyserial et permet d’afficher la liste des ports de communication RS232 disponibles sur l’ordinateur ;
  • les fonctions sendA et sendE sont équivalentes. Elles permettent :
    • d’ouvrir la connexion série à une vitesse de 115200 bauds
    • de vérifier que la connexion est bien établie
    • de transmettre le caractère ‘a’ ou ‘e’
    • de vérifier que l’acquittement est bien arrivé (caractère ‘o’ ou ‘b’) dans un délai de 10ms
    • de renvoyer 1 si le transfert s’est bien déroulé ou -1 le cas échéant.
  • le code principal permet :
    • de lister les ports disponibles par l’intermérdiaire de la fonction serial_ports
    • de demander à l’utilisateur de saisir le port de communication de la carte Nucléo
    • de transmettre le caractère ‘a’ et d’afficher un message de validation de l’envoi
    • de transmettre le caractère ‘e’ et d’afficher un message de validation de l’envoi

MInE Prototyper Prototyper avec Nucleo et MBED

Nucléo – Echanger des données entre un PC et un uC