Protocole PIC - Matlab - Labview

Protocole PIC <=> MATLAB <=> LABVIEW

Transmission de données

Communication entre un microcontrôleur PIC et un PC exécutant Labview ou Matlab.

I) Objectif

Concevoir un outil permettant de suivre graphiquement l'évolution de différentes variables d'un programme tournant dans le microcontrôleur. Ces variables peuvent être des valeurs capturées par les Convertisseur Analogique Numérique (CAN) ou d'autres périphériques interne ou externe au microcontrôleur. Ces valeurs pourront être traitées ou analysées dans un algorithme de traitement (Matlab ou Labview) dont on pourra visualiser graphiquement les résultats en temps réel. Cela permet de prototyper des algorithmes rapidement avant de les développer pour le microcontrôleur. On s'affranchit ainsi lors des difficultés inhérentes à la programmation sur microcontrôleur : précision des calculs, place mémoire, optimisation.

II) Fonctionnement général

La transmission d'une série d'octets par le port, série est facilement réalisable entre le microcontrôleur et le PC. Cependant, la réception d'une série d'octets ne permet pas de suivre l'évolution de différentes variables du programme du microcontrôleur. Une couche de protocole supplémentaire est nécessaire. Celle-ci va définir, pour chaque donnée envoyée, un canal et le type de donnée transmise (octet ou mot). Il est alors possible de monitorer différentes variables du microcontrôleur en traçant leurs évolutions respectives au cours du temps.

La configuration de la transmission série doit être identique dans le pic et au niveau de l'ordinateur réceptionnant les données sous Matlab ou Labview. J'utilise la transmission série à des vitesses variant de 9600 bauds à 115 200 bauds, sans bit de stop, avec un bit de start et sans contrôle de flux. Toute autre configuration est possible.

Le protocole réalisé permet d'attribuer à chaque variable émise l'un des 16 canaux ainsi que l'un des 4 types de données.

Trois programmes ont été réalisés :

- les fonctions écrites en C pour le microcontrôleur.

- Un programme décodant la trame ainsi qu'une interface utilisateur permettant d'effectuer du traitement sur les données reçues en temps réel sous matlab. On dispose de toute la puissance de calcul de matlab ainsi que de ses capacités graphiques. Il est aussi possible de traiter les données dans un schéma Simulink.

- Un programme décodant la trame sous labview. Les données peuvent ainsi être injectées dans un VI (Virtual Instrument).

Les deux modules réalisés pour Labview et pour Matlab sont indépendants. Chacun permet d'analyser les données reçues. Les différences sont les suivantes :

  Matlab Labview
Temps réel
n'est pas conçu pour cela
++
Graphiques
plus souple
meilleur pour l'affichage graphique simple en temps réel
Calculs
calcul vectoriel, algorithme .m
nécessite de réaliser un schéma
Enregistrement de données
très rapide à réaliser : >>save nomVariable
L'aspect temps réel de Labview permet de logger des données pour des laps définis
Interface dédiée pour une application du microcontrôleur
difficile

Possibilité de réaliser des faces avant controlants
- des paramètres de l'algorithme du microcontrôleur.
- Le déclenchement d'un enregistrement
- Visualise l'évolution des variables

Un module a été développé sous labview permettant d'écrire des paramètres dans le microcontrôleur, notamment dans l'EEPROM permettant ainsi d'ajuster des paramètres de calculs. Ce module n'a pas été porté sous matlab.

III) Protocole au niveau binaire

Le microcontrôleur transmet les variables en spécifiant pour chacune son type et le canal auquel elle est rattachée. L'octet contrôle précédant chaque donnée à la structure suivante :

Lorsque la donnée est composée de plusieurs octets, l'octet de poids faible est émis en premier.


fig1. Exemple d'une trame de donnée

La trame de donnée présenté sur la figure 1 représente les valeurs (int16) 8CB8h et (char) AAh émises respectivement sur le canal 0 et 1. Seule deux des quatres types de données possible sont actuellement utilisé :

Ces données peuvent être interprétées comme étant signé ou non signé à la réception.

IV) Fonction d'émission de données du microcontrôleur

Les fonctions écrites pour le pic permettent de construire et d'envoyer les trames de données comme celle de la figure 1. Deux contraintes vont orienter la manière d'implanter ces fonctions. La première est la place mémoire programme et RAM disponible dans le microcontrôleur. Celle-ci étant limité, il faut en utiliser un minimum afin de laisser de la place au programme principal. La seconde contrainte est l'aspect temps réel. L'émission sur le port série du PIC ne doit pas bloquer l'exécution du programme principal. Un tel blocage modifierait le comportement du programme principal lorsque celui-ci à des contraintes de temps à respecter. La fonction d'émission doit être rapide et non bloquante.

Deux fonctions et une interruption sont utilisées :

void initRS232e(unsigned char ValSPBRG) : permet de configurer le périphérique série du PIC. Cette fonction appelée une unique fois pendant la phase d'initialisation du microcontrôleur peut nécessiter une adaptation préalable pour être utilisé sur différents PIC. La valeur ValSPBRG configure la vitesse de l'interface série.

bit send232Buff(int valeur, unsigned char cannal) : construit la trame à envoyer et la mémorise dans un buffer circulaire. Lorsque le buffer circulaire ne dispose de pas assez de place pour y placer la nouvelle donnée, la fonction retourne '0' et la variable n'est pas émise. Si l'on veut s'assurer que la variable sera bien émise, il faut utiliser la fonction ainsi :

while(send232Buff( valeur , cannal ));

//--Variables à ajouter en global : 
	unsigned char  RS232Tab[16];
	unsigned char  RS232PtrHaut = 0;
	unsigned char  RS232PtrBas = 0;

bit send232Buff(int valeur, unsigned char cannal) {
	unsigned char Tmp;
	unsigned char Tmp2;
	Tmp = ~(RS232PtrHaut - RS232PtrBas);   // Tmp = 7 - (Haut - Bas) modulo 16
	Tmp = Tmp & 0b00001111;
	
	Tmp2 = (cannal & 0b00000011)+2; // Nbr bits à envoye
	if (Tmp >= Tmp2) {              // Si on a la place ds le buffer d'envoye 
     RS232Tab[RS232PtrHaut] = ((cannal << 2) & 0b11111100) | 1;
               // envoie 6 derniers bits du canal et bit 1=0 ; bit 0=1
               // signature octet controle en poids faible
			RS232PtrHaut = (RS232PtrHaut + 1) & 0b00001111;
	
     for(Tmp=1; Tmp < Tmp2 ; Tmp++) {
			RS232Tab[RS232PtrHaut] = valeur & 0b11111111;
			valeur = valeur >> 8;
			RS232PtrHaut = (RS232PtrHaut + 1) & 0b00001111;
		}
		Tmp = 0;		// bufferisation réussit
		TXIE = 1;		// enable interrupt

	} else Tmp = 1;

	return Tmp;
}

void interrupt IntVector(void) { if (TXIE && TXIF) : L'interruption Tx qui est appelée à chaque fin d'émission d'octet par la périphérique série du PIC envoie les octets du buffer circulaire un à un jusqu'à ce qu'il soit vide.

#pragma interrupt_level 0
	void interrupt IntVector(void)
	{
		if (TXIE && TXIF) {
			if  ( RS232PtrHaut != RS232PtrBas ) {
				TXREG = RS232Tab[RS232PtrBas];
				RS232PtrBas = (RS232PtrBas + 1) & 0b00001111;
				if (RS232PtrHaut == RS232PtrBas)
					TXIE = 0;	// enleve interrupt 
			} else TXIE = 0;	// enleve interrupt 
		}
	}

L'utilisation d'une interruption permet de ne pas monopoliser le microcontrôleur pendant l'émission des octets. L'exécution de son programme peut ainsi continuer pendant que le buffer est transmis. La routine d'interruption est très simple donc très rapide perturbant très peu les interruptions du programme principal. L'interruption peut être placée en "low priority" sur les pic 18f.

V) Réception sous Matlab


Matrice Rn
- 2 channel
- 10 premières variables reçu

Matlab acquiert pendant un laps de temps défini par l'utilisateur inférieur à la seconde la trame de données en provenance du microcontrôleur. Le décodage optimal de la trame est ensuite réalisé et génère une matrice. Chaque variable reçue est indexée chronologiquement. Chaque colonne de la matrice créée correspond à son n° de canal, et chaque ligne correspond à l'indexe de la variable reçue. Chaque ligne de la matrice contient l'unique variable ayant l'indexe de son le n° de la ligne. Lorsque la matrice à plusieurs colonnes ( plusieurs canaux), elle est complétée par des "Not a Number" : 'NaN'.

Sur l'interface utilisateur présenté sur la figure 2, le transfert série se fait à 57600 bauds sur le COM 5. Les 5000 dernières lignes de la matrice sont enregistrés dans la variable R, et la variable Rn contient les dernières 1000 lignes. La réception d'une trame et son analyse s'effectuent toutes les 0,1 secondes. Enfin, à droites de l'interface se trouvent les indications de la transmission en cours. On voit ainsi que la dernière trame de données reçues contenait 135, soit un débit réel de 11956Kb/s ce qui signifie que le microcontrôleur n'émet pas les variables de manière continue. Ces 135 octets une fois décodés génèrent une matrice de 45 lignes, soit 45 variables, qui est concaténée à Rn et à R. La variable R contient actuellement 3119 lignes et 2 colonnes qui correspondent aux deux cannaux.


fig 2. Interface de réception Matlab


2 axes de l'accéléromètre ADXL 213
recueillis avec Matlab
unité y arbitraire et x en seconde.

Les ports COM disparaissant peu à peu des PC et notamment des portables, on peut utiliser des adaptateurs série=>USB avec leur driver de port série virtuel. Un tel adaptateur a été ici utilisé : le port COM 5 est un port COM virtuel.

Les commandes matlab traitant la matrice R ou Rn sont écrites dans le carré blanc central. Il est aussi possible d'appeler des fichiers de commandes .m permettant de sauver les algorithmes et de bénéficier de la coloration syntaxique de l'environnement matlab. L'extension "statistical toolbox" peut être utile ici pour effectuer des calculs sur les matrices contenant des 'NaN'. Une fonction a été écrite afin de construire une nouvelle matrice ne comprenant plus de 'Nan''.

La flexibilité et la puissance de Matlab sont très appréciables dans beaucoup d'applications. Cependant, la visualisation de données en temps réel est saccadée comme le montre l'animation ci-dessus. La réalisation d'interfaces pour paramétrer un algorithme du microcontrôleur est très compliquée du fait de la difficulté à réaliser des interfaces graphiques avec matlab. C'est pourquoi un algorithme équivalent a été réalisé sous Labview.

VI) Réception sous Labview

Le schéma de réception réalisé sous laview est utilisé comme un sous bloc inclus dans un autre VI. À chaque appel de ce bloc, celui-ci lit puis décode la trame de données arrivées depuis le précédent appel du VI.


PIC_Labview.vi

Le VI prend comme entrée

Les sortis sont :


demo_PIC_Labview.vi

Le schéma ci-contre affiche les données reçues sur les canaux 2 et 3. Il est constitué d'une boucle "while" contenant le bloc "PIC_Labview.vi". Celui-ci lit une trame constituée d'au minimum 24 octets, décode et renvoie les données décodées. Celles-ci sont ensuite converties du format unsigned 16 en signed 16 et sont affichées. La connexion série est ouverte avant l'entrée dans la boucle. À l'arrêt de la boucle, la connexion série est refermée, libérant cette ressource pour l'ordinateur. L'animation ci-dessous montre la face avant du VI. L'animation est ici saccadée, mais le tracé défile sous Labview de manière fluide.


demo_PIC_Labview : face avant
2 axes de l'accéléromètre ADXL 213 cablés sur un PIC 18f1320
unité y arbitraire et x : n° du sample

Les fonctions décrites pour le PIC, sous Matlab et sous Labview permettent au microcontrôleur de transmettre des données vers un ordinateur. Pour pouvoir modifier ou optimiser des paramètres de l'algorithme tournant dans le microcontrôleur, il faut pouvoir lui transmettre les modifications à effectuer.

VII) Changement en Temps réel de paramètres stockés dans le microcontrôleur

Des fonctions de lectures-écriture de paramètres permettent de modifier avec Labview des paramètres de l'algorithme s'exécutant dans le microcontrôleur pendant le fonctionnement de celui-ci. Certains paramètres sont enregistrés dans l'EEPROM du microcontrôleur permettant ainsi d'être persistant même après une réinitialisation. D'autres paramètres peuvent être stockés dans la RAM. La lecture ou écriture de paramètres satisfait les contraintes suivantes :

Trois types de séquences d'octets permettent au PC de lire et écrire des paramètres dans le microcontrôleur. Ces séquences ne sont pas symétriques dans le sens où deux séquences sont destinées à être envoyées uniquement par le PC alors que la troisième est destinée à être envoyée par le microcontrôleur. Le PC est le maître de ces opérations.

Les deux séquences émises par le PC sont :


commande écriture

Le checksum et la signature d'une commande d'écriture permettent de limiter les erreurs d'interprétation de commande d'écriture.

La séquence émise par le microcontrôleur est :


lecture
sur le canal 0

Cette dernière séquence est constituée de 2 X 2 octets qui peuvent être vue comme deux int16. Il est possible de transmettre ces deux int16 par l'un des canaux du protocole définit précédemment (on utilisera par défaut le canal 0). Ce protocole sert de couche infèrieur à la transmission. Ainsi, le microcontrôleur dispose d'un canal dédié à la gestion de paramètres avec Labview et de quinze autres canaux pour visualiser l'impacte de modification de paramètres sur les algorithmes de filtrages où autre implantés dans le pic.

Le microcontrôleur peut interpréter des adresses de paramètres comme correspondant à des emplacements dans l'EEPROM ou dans la RAM.

Deux raisons nous poussent à réduire le nombre de transmissions de paramètres du PC vers le pic. D'une part, l'EEPROM d'un microcontrôleur ne peut n'effectuer qu'un nombre limité de cycles d'écriture. De plus, moins on envoie de données vers le microcontrôleur, moins on perturbe l'exécution de son programme. Pour minimiser le nombre d'écritures, on crée deux tableaux de 256 int16, chacun représentant l'ensemble des paramètres. Le premier tableau correspond aux paramètres définis graphiquement par l'utilisateur via la face avant du VI. L'autre tableau est une copie des paramètres contenus dans le microcontrôleur. À l'initialisation, les 256 paramètres du microcontrôleur sont lus avec la commande de lecture et enregistrés dans ce second tableau. Le VI analyse alors les différences entre les deux tableaux. Pour chaque paramètre qui diffère, le VI envoie au microcontrôleur une commande d'écriture suivie d'une commande de lecture qui permettra de mettre à jour le second tableau.

La réception se fait dans le microcontrôleur à l'aide de l'interruption RX placé en "low priority" sur les PIC 18f. L'interruption qui est déclenché lors de la réception d'un octet se contente de l'enregistrer dans un buffer circulaire de 8 octets définit en variable global. Ce buffer est analysé et vidé au fur et à mesure par une tache de fond. Ainsi, le déroulement du programme principal est très peu perturbé. En revanche, le PC doit émettre les données doucement pour laisser le temps à la tache de fond de les traiter. La vitesse d'arrivé des octets par le port série est cependant faible devant les 10MIPS affichées par un PIC cadence à 40Mhz.

La routine d'analyse du buffer détecte aussi l'arrivée consécutive de 10 valeurs 10h. Ceci permet à l'excellent bootloader tinybld de réinitialiser le microcontrôleur et de le reprogrammer sans avoir à toucher au montage électronique.

VIII) Exemples d'utilisation et ressources

Le protocole PIC ==> Labview est utilisé par les projets décrits aux pages suivantes :

Il a servi dans de nombreux autres projets électroniques dont le mixeur 2 axes ou le pilote automatique non décrits ici. Les microcontrôleurs testés avec ce protocole sont : PIC 16f628 16f648 16f877 18f1320. Mais il est adaptable à tous les autres microcontrôleurs y compris les dsPIC 30f. À noté que le nouveaux microcontrôleur microchip (18f4550 et 18f2550) supporte directement l'USB. Il est donc possible de transmettre des données via l'USB au travers d'une émulation de port série. Ce système permet d'atteindre des débits bien supèrieur à ceux obtenus avec une vraie liaison série.

Ressources : bientôt ici