Réalisation d’une interface EIB/KNX TP1 sur base de microcontrôleurs PIC.

 

 

Petit modèle

 

Le petit modèle sera comparable à un BCU1 ou 2 en terme de capacité :

-          Maximum 32 objets = MAXOBJ.

-          Maximum 128 adresses de groupe (y compris plusieurs fois la même, si liée à plusieurs objets différents) = MAXADR.

-          Maximum 15 adresses de groupe par objet = MAXASO.

-          Maximum 128 bytes pour la valeur des objets (= 4 bytes/obj. en moyenne) = MAXVAL.

 

Comme base de ce remplacement de BCU / BIM pour petite application (capteur ou acteur standard), nous utiliserons un PIC 16F877 (éventuellement A).

Tout le code présenté sera écrit pour un  PIC 16F877A mais le portage vars un composant légèrement différent ne devrait pas poser de gros problème[, sauf peut-être la gestion de l’écriture en flash qui peut changer entre les anciens circuits et les nouveaux « A »].

Pour rappel, le PIC 16F877A possède 368 bytes de RAM, 256 bytes d’EEPROM et 8192 « words » de 14 bits en FLASH.

 

 

Pour la connexion du PIC au bus EIB, nous utiliserons une puce TP-UART de Siemens

 

 

 

Comment organiser la mémoire utilisée par le stack EIB ?

 

Remarques préliminaires :

-          Par facilité, il ne sera fait usage que de bytes complets pour le stockage d’information, même si le nombre de bits utiles est inférieur.

-          Dans le même ordre d’idée, dans le cas de stockage en mémoire flash, seuls les 8 bits de poids faible seront utilisés même si l’espace en compte 14 réellement.

-          Ces deux restrictions facilitent l’écriture du code et son portage vers une autre famille de microcontrôleurs mais gaspillent pas mal de mémoire, il faudra peut-être revenir sur ce choix si les ressources en mémoire s’avèrent trop limitées pour écrire le stack EIB et les applications utiles.

-          Attention, tous les pointeurs sont relatifs au numéro de ligne du tableau vers lequel ils pointent, ils NE pointent PAS directement vers une case mémoire.

-          Les limites imposées sous forme de « MAX-quelque chose » sont modifiables si pour l’un ou l’autre projet une valeur plus grande était nécessaire mais il faut bien mesurer l’impact sur la place occupée en mémoire.

-          L’organisation de la mémoire est avant tout orientée par la nécessité de rechercher la présence ou non d’une adresse de groupe spécifique en un temps très limité, moins de 1,5 ms en principe mais beaucoup moins en pratique si on veut garder une performance acceptable dans le cas ou le bus EIB est très chargé.

-          Les zones non utilisées seront mises à zéro à la programmation des adresses de groupes et des paramètres des objets.

 

 

 

Tableau 1 :

Informations uniques de l’objet.

Trié selon l’ordre croissant du numéro d’objet.

A placer en mémoire flash.

1 entrée par objet à MAXOBJ lignes = 32 lignes.

Que contient chaque ligne ?

o       A) Les attributs de l’objet (communication, read, write, transmit, update, init ...) = 6 bits, ainsi que sa priorité (normal, high, alarm ou system) = 2bits.
Taille totale = 8 bits.

o       B) Pointeur vers le premier pointeur d’adresse de groupe dans le tableau 2, avec ce pointeur on sait à partir d’où lire séquentiellement le tableau 2, la première adresse de groupe obtenue ainsi sera l’adresse d’écriture vers le bus, les éventuelles suivantes sont uniquement pour la mise à jour de l’objet à partir du bus.
Taille = taille de MAXADR = 7 bits.

o       C) Le nombre de pointeurs d’adresses pour cet objet dans le tableau 2 :
Taille = taille de MAXASO = 4 bits.

o       D) Pointeur vers l’emplacement RAM qui contient la valeur des l’objet :
Taille = taille de MAXVAL = 7 bits.

o       E) La longueur (en bytes) de la valeur de l’objet (va de 1 à 14 bytes) :
Taille = 4 bits.

Au total : 8 + 7 + 4 + 7 + 4 = 30 bits.

Pour plus de facilité, il sera codé sur 5 bytes (1 par élément), ce qui donne :
160 bytes.

On le consulte sur base du numéro de l’objet x 5 comme index relatif.

Attention : il faut ajouter 1 ou 2 bit(s) à chaque ligne si on désire implémenter le tableau 5, voir plus bas pour plus d’information.

 

 

Tableau 2 :

Liste de pointeurs vers les lignes du tableau 3 (toutes les adresses de groupe), il s’agit en fait d’un index sur le tableau 3, ordonné selon les numéros d’objet.

A placer en mémoire flash.

1 entrés par adresse de groupe à MAXADR lignes = 128 lignes.

Que contient chaque ligne :

o       A) Un pointeur sur une ligne du tableau 3 :
Taille = taille de MAXADR = 7 bits.

Au total : 7 bits.

Il sera codé sur 1 byte, ce qui donne :
128 bytes.

On utilise l’info « 1B » pour y pointer et on le parcourt séquentiellement durant « 1C » lignes pour lire toutes les adresses de groupes liées à un même objet.

 

 

 

Tableau 3 :

Liste de toutes les adresses de groupe utilisées, triée par ordre croissant.

Attention, si une adresse de groupe est liée à plusieurs objets différents, elle sera stockée autant de fois, séquentiellement, dans le tableau 3.

A placer en mémoire flash, avec un accès en lecture le plus rapide possible.

1 entrée par adresse de groupe à MAXADR lignes = 128 lignes.

Que contient chaque ligne ?

o       A) Adresse de groupe :
Taille = taille de « 15.15.255 » = 16 bits.

o       B) Le numéro de l’objet lié à cette ligne :
Taille = taille de MAXOBJ = 5 bits.

Au total : 5 + 16 = 21 bits.

Pour plus de facilité, il sera codé sur 3 bytes, ce qui donne :
384 bytes.

Afin de faciliter le calcul des adresses en mémoire lors de la recherche, il peut être intéressant de séparer le contenu de chaque ligne dans deux espaces mémoire différents, ce qui donnera un tableau 3a avec toutes les adresses de groupe et un 3b avec les numéros d’objet qui y correspondent.

Si l’on connaît déjà le numéro d’objet, il faudra utiliser 2 x « 2A » comme index relatif pour trouver l’adresse de groupe dans le tableau 3a ; par contre, si on est en mode de recherche, dans le tableau 3a, de correspondance d’adresse sur base d’un message en provenance du bus, il faudra diviser par 2 l’index relatif de l’adresse de groupe retrouvée pour obtenir le numéro de l’objet dans le tableau 3b.

 

 

Tableau 4 :

Valeurs de chaque objet, triées par ordre croissant du numéro d’objet.

A placer en RAM.

1 entrée par objet, mais longueur variable à MAXVAL bytes, pas de lignes.

Ceci n’est pas un tableau au sens propre car les éléments ont une taille/longueur variable, c’est juste une zone mémoire qui contient la valeur de chaque objet stockée séquentiellement.

La taille de cette zone mémoire sera fixée arbitrairement selon la RAM disponible (et dans certains cas le type d’objets utilisés par le programme), c’est la valeur MAXVAL.

Fixer MAXVAL en dessous de « 2 x MAXOBJ » bytes n’a pas de sens, il vaut alors mieux réduire MAXOBJ et, partant, MAXADR aussi.

La plus grande valeur utile pour MAXVAL étant « 14 x MAXOBJ » puisque le plus long objet EIB fait actuellement 14 caractères, mais c’est sans doute bien trop en pratique, particulièrement pour un petit module d’accès au bus qui utilisera principalement des objets de 1 ou 2 bytes.

Une bonne moyenne est de définir MAXVAL = 4 x MAXOBJ, ce qui donne :
128 bytes.

Ce choix permet de conserver un bon espace RAM disponible pour le programme d’application.

Attention, dans les PIC 16F876/877(A), on ne dispose pas d’un espace RAM de 128 bytes d’un seul tenant, une zone de 77 bytes et une de 64 bytes seront donc utilisées : 120h – 16Ch en bank2 et 1A0h – 1DFh en bank3. Normalement 2 x 64 bytes suffisent mais on ajoute 13 bytes à la première zone afin de ne pas scinder la valeur d’un objet sur 2 banks différentes ; si un objet de 14 bytes débute en position 15Fh, il faudra 13 bytes supplémentaires pour le stocker séquentiellement en entier dans la bank2.

L’index 1D) devra donc être « re-traité » en conséquence lors de l’accès à une valeur d’objet : le bit 6 servira de sélection de bank (0 à bank2, 1 à bank3) puis sera mis à zéro et ensuite la valeur 20h (ou 120h ou 1A0h, cela n’a pas d’importance) sera ajoutée pour obtenir un pointeur sur la valeur de l’objet voulu.

 

 

 

Tableau 5 :

POUR L’INTANT, LE TABLEAU 5 NE SERA PAS IMPLEMENTE !

Valeurs de chaque objet, triées par ordre croissant du numéro d’objet, pour le stockage à long terme des valeurs, lors des coupures d’alimentation et/ou du bus EIB.

A placer en EEPROM (ou bien FLASH si elle à une grande endurance en effacement/écriture).

Le tableau 5 est identique au tableau 4, seul son emplacement en mémoire change.

L’usage et l’implémentation du tableau 5 sont facultatifs, il n’est utile que si l’on désire sauvegarder certaines (ou toutes) les valeurs des objets lors d’une coupure d’alimentation et/ou du bus EIB.

Si le tableau 5 est implémenté, il faudrait aussi ajouter 1 ou 2 bit(s) à chaque ligne du tableau 1 afin de stocker l’information « Faut-il sauvegarder la valeur de l’objet en cas de coupure de ... ? » ; 1 bit suffit si on dérive l’alimentation depuis le bus EIB, il faudra 2 bits si on utilise un alimentation externe ; mais attention, ETS ne considère pas cette information comme faisant partie des paramètres des objets mais bien des paramètres du programme d’application, donc en pratique ces 2 bits supplémentaires sont programmés dans les BCU/BIM en même temps que les paramètres du programme, ils devront être stockés dans une zone mémoire séparée du tableau 1.

POUR L’INTANT, LE TABLEAU 5 NE SERA PAS IMPLEMENTE !

 

 

Tableau 6 :

Champ de doubles bits qui indique si la valeur d’un objet a été mise à jour par un télégramme reçu du bus et si cette valeur a été modifiée.

A placer en RAM.

1 entrés par objet à MAXOBJ x 2 bits = 64 bits.

Coder 2 bits sur un byte serait du gaspillage de RAM, nous utiliserons donc 8 bytes pour stocker nos 64 bits.
8 bytes.

On utilise le numéro de l’objet divisé par 4 pour y pointer, l’objet 0 correspondant au 2 bits de poids faible (bit 0 et bit 1) du byte à l’adresse mémoire la moins élevée, l’objet 1 au bits 2 et 3 du même byte, et ainsi de suite.

Le bit de poids le + faible indique si l’on a reçu par le bus une valeur pour cet objet (ce bit à 0 indique que rien n’a été reçu).

Le bit suivant indique si la valeur de l’objet stockée en mémoire était différente ou non, si elle l’était, cette valeur a été écrasée par celle reçue depuis le bus (ce bit à 0 indique que la valeur n’a pas été modifiée/écrasée).

La routine de réception des télégrammes se charge de mettre à 1 les bits correspondants au télégramme reçu.

Le programme d’application remettra les bits à 0 lors de la lecture de la valeur de l’objet correspondant.

Il faut penser à masquer les interruptions durant la séquence :

§         lecture des 2 bits

§         lecture de la valeur de l’objet

§         mise à zéro des 2 bits

On peut aussi enfermer le tout dans une « fonction » du stack EIB.

 

 

 

 

 

Autres variables : 

En plus de ces tableaux, plusieurs variables à stocker en FLASH sont nécessaires :