Vous êtes sur la page 1sur 73

BRUYERE Philippe 2002-2003

GOMBERT Benjamin
VENCE Eric

Gp. P205

PROJET DE 2ème ANNÉE

CONCEPTION ET RÉALISATION D’UN MODULE


P.I.D. À SORTIE ANALOGIQUE
SOMMAIRE

A – DESCRIPTION DU PROJET 04

CAHIER DES CHARGES 04

PRINCIPE DE FONCTIONNEMENT 04

GUIDE D’UTILISATION 06

B – CONCEPTION MATÉRIELLE 08

CHOIX DES COMPOSANTS 08

SCHÉMA BLOC 09

DÉTAILS TECHNIQUES 09
Adaptateur d’entrée 09
CAN 11
Microcontrôleur 18
Afficheur et Driver 19
Clavier 19
CNA 20
Adaptateur de sortie 27

RÉALISATION 29
Nomenclature 29
Schéma de câblage 30
Procédures de tests 31
Montage final 33

ESME Sudria p.1/72


2003
C – CONCEPTION LOGICIELLE 34

ORGANISATION DU PROGRAMME
ET FORMATAGE DES DONNÉES 34

CONFIGURATION DU PIC 38
Affectation des entrées/sorties 39
Assignation des registres de configuration 40

MISE EN PLACE DE MACROS 43

DÉCLARATION DES CONSTANTES 43

ALLOCATION DE L’ESPACE MÉMOIRE 44

DÉTECTION ET TRAITEMENT DES INTERRUPTIONS 45

INITIALISATIONS 54
Initialisation des ports 54
Initialisation des registres d’interruptions 55
Initialisation des variables 55

ROUTINES 56
CAN 56
Addition 57
Soustraction 58
Multiplication 58
Calcul du P.I.D. 60
Conversion de chiffres en digits 66
Conversion des paramètres en digits 68
Affichage (transmission série des données) 69

PROGRAMME PRINCIPAL 71

D – SYNTHÈSE 72

AMÉLIORATIONS ENVISAGÉES 72

E – SOURCES 73

ESME Sudria p.2/72


2003
A – DESCRIPTION DU PROJET

Cahier des charges

L'objectif de ce projet est de concevoir un module effectuant les fonctions de


corrections numériques P.I.D. d’un signal d’entrée analogique. Les valeurs Kd,
Kp et Ki sont réglables ou réinitialisables par l’utilisateur à tout instant et
affichées sur un écran LCD à 4 chiffres. Le signal de sortie est analogique. La
structure générale de l’application est celle du schéma ci-dessous:

e e Micro- s
+ CNA MCC
- Contrôleur

r
Capteur

Les composants à utiliser sont :

- Microcontrôleur PIC 16F876


- Contrôleur LCD de référence MM5452
- Afficheur LCD 4 digits
- Convertisseur Numérique-Analogique 8 bits

Principe de fonctionnement

Le module de correction P.I.D. (Proportionnelle Intégrale Dérivée) à réaliser


propose le réglage des valeurs Kp, Ki et Kd (paramètres du correcteur) par
l'utilisateur grâce à un clavier (touches “plus” et “moins” pour incrémenter et
décrémenter les valeurs et touche de validation). Les réglages sont visualisés
sur un afficheur LCD à 4 chiffres (ou digits) contrôlé par un driver.
Les corrections sont effectuées par un microcontrôleur qui prend en charge la
conversion analogique-numérique du signal d'entrée. Le signal numérique
corrigé est ensuite reconverti en signal analogique par un convertisseur
numérique-analogique. Enfin le signal est amplifié a l'aide d'un amplificateur de
gain avant de commander une machine à courant continue (MCC).

ESME Sudria p.3/72


2003
La réponse est récupérée en sortie de la MCC et une fois filtrée elle est
comparée au signal d'entrée afin de déterminer l'erreur pour effectuer la
correction souhaitée.

Un correcteur alliant la combinaison des trois actions P.I.D. peut être assimilé à
un correcteur série au sein d’un système.

Détails sur les 3 corrections :

La première consiste à dire que plus l'erreur est grande et positive et plus il faut
augmenter la tension aux bornes du moteur (pour rattraper cette erreur). La
tension aux bornes du moteur est alors directement proportionnelle à l'erreur.
On a donc : u( t ) = K p .e( t )
Kp étant un coefficient de proportionnalité.

On voit cependant apparaître des problèmes. Il faut une certaine tension aux
† du moteur pour que celui-ci puisse se lancer. En régime permanent,
bornes
l'erreur ne sera plus assez grande pour pouvoir faire avancer le moteur. Il y aura
donc une erreur qui subsistera et nous n'atteindrons pas exactement la position
souhaitée (erreur d'ordre 0). De même, pour qu'il puisse y avoir un mouvement,
il sera nécessaire que le moteur soit alimenté, et donc qu'il y ait une erreur.
C'est pourquoi, on ajoute un autre élément qui va augmenter la tension aux
bornes du moteur lorsque l'erreur reste constante. À chaque période, on va
sommer l'erreur (intégration de l'erreur). Donc, si l'erreur reste constante, sa
somme va augmenter au fil du temps. On a alors :
1 t
u( t ) = K p .e( t ) + Ú e(t )dt
Ki 0
La valeur Ki est un coefficient qui va déterminer l'influence de ce paramètre
intégral.
† une tension au moteur, il met un certain temps à réagir
Lorsque l'on applique
(constante de temps mécanique). Pendant ce temps l’erreur continue à
augmenter et la tension aux bornes du moteur croît alors que cela n'est pas
nécessaire. Pour diminuer ce phénomène, nous introduisons un 3ème élément
qui permet d'en limiter les effets (il est souvent fait référence pour ce terme à la
notion de viscosité, en augmentant ce terme c'est comme si on augmentait la
viscosité de la réaction, on trempe le tout dans un liquide de plus en plus
visqueux). On se base sur la différence (la variation) de l'erreur entre 2
mesures. Il s'agit de la dérivée de l'erreur. On obtient au final l’équation du
P.I.D. :
1 t de ( t )
u( t ) = K p .e( t ) + Ú
Ki 0
e(t ) dt + K d
dt
Avec Kd étant le coefficient du paramètre dérivé.

Chacun des paramètres Kp, Ki et Kd corrige le système en vitesse, stabilité et


précision. Par†exemple avec un correcteur de type proportionnel on peut rendre
le système plus rapide mais il devient en revanche moins stable. Il faut donc
trouver un compromis entre rapidité, stabilité et précision. D’où la nécessité
d’utiliser un correcteur élaboré dont la programmation sera détaillée par la suite.

ESME Sudria p.4/72


2003
Guide d’utilisation

Pour s’assurer du bon fonctionnement du module d’asservissement, il faut


suivre “scrupuleusement” les étapes suivantes lors de sa mise en marche.

Tout d’abord vérifier le câblage d’alimentation. Les bornes de couleurs bleu,


jaune, rouge et noire sont directement reliées aux composants (PIC, CAN,
driver LCD, AOP) et les alimentent. Les douilles jaune et bleue fournissent
respectivement +12 et –12V pour les AOP et la douille rouge +5V pour le reste
des composants.

Il faut s’assurer que toutes les alimentations sont bien branchées, surtout au
niveau du +12 et –12V (jaune et bleue) afin de ne pas créer de différences de
potentiels trop importantes au sein du circuit général. C’est à partir de ce
moment-là que l’on peut allumer l’alimentation et basculer l’interrupteur général
du montage sur la position ON.

Après avoir réglé le GBF, on le relie à l’aide de câbles coaxiaux branchés sur
les fiches BNC. On branche un oscilloscope en sortie pour visualiser le signal
corrigé. Le signal d’entrée ne peut excéder +5V et –5V et il doit rester en basses
fréquences (50 Hz par exemple).

Une fois la maquette alimentée et un signal d’entrée injecté, il faut appuyer sur
le bouton “Reset” pour démarrer la conversion analogique-numérique et par
conséquent la correction P.I.D. Les paramètres sont directement visualisés sur
l’afficheur LCD. Quatre digits sont utilisés, de gauche à droite : Kp, Ki, Kd et la
limite d’intégration de l’asservissement. Le clavier est composé de 3 boutons
(“+”, “-“, “v” pour valider). Une première pression sur “v” permet d’activer le
mode de sélection du paramètre à modifier. On se déplace sur l’afficheur à
l’aide des boutons “+” pour aller à gauche, et “-“ pour aller à droite. Une fois le

ESME Sudria p.5/72


2003
choix du paramètre à modifier effectué, on le valide par pression sur “v”. Ainsi
on passe dans le mode de sélection de la valeur du paramètre qui peut varier
par pas de 1 entre 0 et 9. Le “+” et le “-“ permettent d’incrémenter ou
décrémenter la valeur que l’on valide avec la touche “v”. L’opération de
modification du ou des paramètres de corrections peut être effectué à tout
instant. Lorsque l’on appuie sur la touche “Reset”, tous les paramètres sont
remis à 0. On peut ainsi réaliser un nouvel asservissement.

ESME Sudria p.6/72


2003
B - Conception matérielle

Choix des composants

Le cahier des charges nous impose d’utiliser certains composants. Ils ont été
choisis pour leurs caractéristiques techniques et les performances nécessaires
à la bonne exécution du système.

Le microcontrôleur est le cœur du système. Il doit effectuer en permanence le


calcul de la correction P.I.D., mais il doit aussi gérer l’envoi de données au
driver LCD afin d’effectuer un affichage cohérent des paramètres du correcteur.
Le PIC doit également prendre en compte les interruptions engendrées par les
modifications possibles des paramètres à l’aide de boutons-poussoirs. Il est de
plus équipé d’un convertisseur analogique-numérique (CAN) 10 bits en entrée.
En sortie du PIC nous avons choisi d’utiliser un convertisseur numérique-
analogique (CAN) 8 bits de référence AD557. Il délivre en sortie un signal
compris entre [0V ; +2,5V]. Ce convertisseur est placé avant l’adaptateur de
sortie.

L’utilisation de ce PIC et du CAN impose quelques contraintes. Il ne peut


recevoir en entrée qu’un signal compris entre 0 et 5 Volts. Or nous effectuons
l’asservissement d’une machine à courant continue, nous avons donc un signal
compris entre –5 et +5 Volts en entrée du PIC.
Il faut alors utiliser deux montages d’adaptation. Un en entrée pour réduire
l’amplitude du signal de [-5V ; +5V] à [0V ; +5V] et un autre en sortie pour
augmenter l’amplitude de [0V ; +2,5V] – sortie du CAN – à [-5V ; +5V].

ESME Sudria p.7/72


2003
Schéma bloc

Détails techniques

Adaptateurs d’entrée
Conversion [+5v ; -5v] => [+5v ; 0v]

Il faut adapter le signal d’entrée. Nous devons diminuer l’amplitude du signal de


[+5v ; -5v] à [+5v ; 0v].

Équation à réaliser : Vs =
(Ve + 5)
2

Pour réaliser cette opération, on utilise deux amplificateurs opérationnels (AOP)


en série. Le premier est utilisé en montage amplificateur inverseur ; le second
en montage†soustracteur recevant sur sa borne V- (borne inverseuse) la sortie
du premier AOP et sur sa borne V+ (borne non-inverseuse) le signal d’entrée à
corriger.

ESME Sudria p.8/72


2003
Le choix des résistances est fait de telle sorte que :

R1 = R2 = R5= R6
R3 = R4
R3 = 2 R1

Une fois les calculs théoriques effectués, nous avons simulé l’ensemble du
montage d’adaptation à l’aide du logiciel Design Capture. Voici les courbes que
nous obtenons après simulation :

Le signal d’entrée, une sinusoïde d’amplitude comprise entre –5 et +5 V, a été


adapté pour pouvoir être injecté au PIC.

ESME Sudria p.9/72


2003
CAN

Le principe de la conversion analogique-numérique est d’attribuer une grandeur


numérique correspondant à un état physique. Le CAN convertit donc une
tension dite analogique en une valeur numérique.

Le PIC 16F876 utilisé pour le calcul de la correction P.I.D. intègre un


convertisseur 10 bits. Il ne sera donc pas nécessaire d’utiliser un circuit
supplémentaire pour la conversion analogique-numérique.

Résolution d’un convertisseur analogique-numérique

La résolution d’un CAN correspond à la plus petite mesure réalisable par le


CAN, autrement dit la précision du CAN.

Par exemple, si on utilise un CAN 8 bits, ce CAN ne pourra fournir que 255
valeurs différentes. La plus petite différence de tension mesurable à ses bornes
va être fonction de la plage de mesure en tension utilisée. Si la tension est
comprise entre 0 et 5V, la mesure minimale correspond à : 5/255 = 19,6mV. On
dira que la résolution d’un CAN 8 bits pour une tension de plage de mesure de
5V est de 19,6mV.

D’une façon générale, la résolution est égale à la plage de tension de la mesure


divisée par le nombre de bits du CAN :
plage _ de _ mesure
Résolution =
Nombre _ de _ bits _ du _ CAN

Par conséquent, pour augmenter la résolution d’un système, on a 2 possibilités :



- soit augmenter le nombre bits du CAN utilisé
- soit diminuer la plage de mesure

On utilise dans ce projet un CAN 10 bits (celui contenu dans le PIC 16F876)
pour convertir le signal d’entrée. Néanmoins un CAN 8 bits aurait suffi car on
néglige les deux bits les moins significatif lors de la correction effectuée par le
PIC.

ESME Sudria p.10/72


2003
Échantillonnage de l’information

La première étape du processus de numérisation est l’échantillonnage. Cela


consiste à passer d'un signal à temps continu (un signal électrique en
l’occurrence), en une suite discrète de valeurs (valeurs mesurées à intervalles
réguliers). Cet échantillonnage est de l’ordre de la dizaine de microsecondes.

Une relation existe entre la fréquence maximale du signal d’entrée et la


fréquence échantillonnage. En effet, pour éviter le phénomène de recouvrement
spectral il faut respecter le théorème de Shannon : Fe > 2.Fmax

Détail de fonctionnement du CAN contenu dans le 16F876

Le microcontrôleur 16F876 intègre un module de conversion analogique-


numérique qui est associé à un multiplexeur analogique multivoie des entrées.
Autrement dit on peut réaliser des mesures sur plusieurs voies d’entrée
analogiques (jusqu’à 5). Ces voies analogiques correspondent aux broches du
port A.

Module CAN 10 bits implique que le résultat de la conversion est un nombre de


10 bits, c'est-à-dire compris entre 000H et 3FFH (11 1111 1111 en binaire ou
1023 en décimal). Ceci correspond donc à 1023 niveaux de mesure, ce qui pour
5V donne une résolution de 4,8mV, précision largement suffisante.

Le temps de conversion de ce module est de l’ordre de : 40µs ce qui permet en


pratique de réaliser jusqu’à 25000 mesures par seconde.

ESME Sudria p.11/72


2003
Structure interne du CAN 10 bits des 16F876

Les registres et bits associés au module CAN

Il y a 4 registres associés au module CAN du 16F876 :


- ADRESH : le registre de résultat “Haut”
- ADRESL : le registre de résultat “Bas”
- ADCON0 : premier registre de contrôle du module CAN
- ADCON1 : seconde registre de contrôle du module CAN

ESME Sudria p.12/72


2003
Les registres ADRESH et ADRESL

Le convertisseur Analogique Numérique est 10 bits et par conséquent 1 octet


(=8 bits) ne suffit pas pour contenir le résultat de la mesure. C’est pour cela que
2 registres sont nécessaires et sont donc utilisés. De fait 6 bits restent inutilisés
sur les 16 disponibles. Il est possible de définir la « justification » du résultat au
sein de ces 2 octets à l’aide d’un bit du registre ADCON1 : le bit ADFM. Voici la
disposition des bits de résultats dans les 2 octets en fonction de la valeur du bit
ADFM :

Le registre ADCON0 :

Ce premier registre de contrôle contient plusieurs bits qui configurent le


fonctionnement du module CAN :

- Bits ADCS1, ADCS0 : bits de sélection de l’horloge utilisée pour le module


CAN.

- Bits CHS2, CHS1, CHS0 : les bits de sélection du canal analogique à mesurer.

Avant toute conversion, il faut définir quel est le canal qui va être utilisé pour
cette conversion. Ceci se fait grâce à ces 3 bits selon le tableau suivant :

ESME Sudria p.13/72


2003
- Bit GO/DONE : Le bit de lancement de la conversion et témoin de la fin de
conversion.

Ce bit n’est actif que si le bit ADON=1, c'est-à-dire si le module CAN est actif. Il
sert à lancer la conversion : en mettant ce bit à 1, on lance la conversion à partir
de la voie analogique sélectionnée par les bits CHS2, CHS1 et CHS0.

Une fois que la conversion est terminée, ce bit passe à 0 automatiquement. Il


sera donc possible d’utiliser ce bit pour attendre la fin de la conversion en cours.

- Bit ADON : Le bit “d’allumage” du module CAN.

Ce bit sert à “allumer” le module CAN. Si ADON=0, le module CAN est inactif. Si
le bit ADON=1, le module est opérationnel.

Le registre ADCON0 :

Ce second registre de contrôle contient plusieurs bits qui configurent le


fonctionnement du module CAN :

- Bit ADFM : Configuration du format du résultat.

Ce bit sert à configurer le résultat au sein des 2 registres ADRESL et ADRESH


selon le tableau qui suit :

Les cases vertes représentent le résultat sur 10 bits, X0 correspond au bit de


poids faible et X9 au bit de poids fort.

- Bits PCFG0 , CFG1, PCFG2 et PCFG3 : Bits de configuration des ports A (en
analogique ou numérique).

Les broches des ports A (à l’exception de PA4) peuvent être configurées soit en
analogique soit en numérique.
Lorsqu’une broche de ce port est configurée en analogique, elle devient un des
canaux de mesure utilisables par le CAN. Lorsqu’elle est configurée en
numérique, elle est une broche E/S comme les autres broches des autres ports.

ESME Sudria p.14/72


2003
La configuration de la nature des broches du port A est décrite dans le tableau
suivant :

L’interruption “fin de conversion” associée au module CAN

Il existe également une source d’interruption liée au module CAN : la fin de


conversion. Comme toute interruption, celle-ci doit être activée pour être
opérationnelle ce qui se fait par les bits :

- PEIE=1 (activation des interruptions périphériques)


- ADIE=1 (activation de l’interruption fin de conversion)

Le bit de drapeau associé à cette interruption est ADIF. Il faudra le mettre à 0


avant toute activation de l’interruption. Ce dernier est automatiquement mis à 1
en fin de conversion si l’interruption est activée.

Cette interruption est intéressante uniquement si l’on souhaite optimiser la


vitesse de conversion au maximum.

ESME Sudria p.15/72


2003
Tableau de synthèse issu de la datasheet du 16F876 :

Déroulement d’une conversion analogique-numérique

Étudions comment le module CAN 10 bits réalise une conversion analogique


numérique. Le schéma suivant résume la séquence d’une conversion
analogique-numérique par le module utilisé :

1. L’ensemble de la conversion est lancé lorsque le bit GO/Done est mis à 1


par l’utilisateur.
2. S’en suit un temps de latence interne lié à la présence d’un condensateur
interne.
3. Puis la conversion commence avec le “calcul” des 10 bits
4. Lorsque la conversion analogique-numérique est terminée :
a. le résultat est stocké dans les registres ADRESL et ADREH
b. le bit GO/Done est mis à 0 automatiquement témoignant de la fin
de la conversion
c. le drapeau de l’interruption “fin de conversion” est mis à 1 (si cette
interruption est activée comme expliqué précédemment)

ESME Sudria p.16/72


2003
Microcontrôleur

Le microcontrôleur que nous utilisons est un 16F876. Il a été choisi pour ses
caractéristiques techniques intéressantes.

Il possède une mémoire RAM de 368 octets, une EEPROM de 256 octets ainsi
qu’une FLASH de 8 kilo-octets. Cela nous assure un espace suffisant pour
stocker et exécuter le programme afin de traiter le signal à corriger.
En plus des entrées/sorties programmables et des interruptions, il possède
certaines ressources internes telles que :
- Un convertisseur analogique-numérique 10 bits qui envoie directement les
échantillons du signal à traiter aux registres internes du PIC afin
d’effectuer la correction P.I.D. L’intégration de ce CAN simplifie le
routage, évite des problèmes de compatibilité et fait gagner de la place
au montage.
- Des timers. Nous utiliserons le timer 1 pour gérer le clignotement du
curseur. Le timer 1 est un compteur 16 bits. Lorsqu’il est couplé à notre
oscillateur de 4MHz avec un pré-diviseur égal à 8 on obtient une
interruption toutes les 0,5 secondes. La période de clignotement sera
donc d’une seconde.
- Des liaisons séries SCI, I2C, SPI qui ne sont pas utilisées dans le cadre de
ce projet.
- Des sorties P.W.M. (Modulation de Largeur d'Impulsion) si l’on veut
effectuer une commande numérique par exemple.

Pour fonctionner le PIC réclame une configuration hardware minimale


composée d’un oscillateur et d’un circuit reset :

ESME Sudria p.17/72


2003
Afficheur et Driver

Le driver LCD remplit une double fonction. Il commande l'affichage et d'autre


part se charge de la communication avec l'extérieur.

Il est piloté par le PIC qui lui transmet un signal d’horloge qui cadence l’envoi
des données à afficher.

Le driver peut afficher jusqu’à 32 segments différents, ce qui correspond dans


notre cas à 4 digits à 7 segments ainsi que 4 points situés à gauche des
chiffres. L’afficheur LCD ne pose pas de problème, le routage de chaque digit
se fait par paquet de 8 bits.

Clavier

Le clavier doit permettre la saisie et la modification des paramètres du


correcteur PID : Kp, Ki, Kd et la limite d’intégration.

ESME Sudria p.18/72


2003
Il est constitué de trois boutons-poussoirs avec une capacité de découplage en
parallèle pour limiter le phénomène de rebonds.

Les boutons sont connectés au PIC sur le port B.

CNA

Les convertisseurs numérique-analogique convertissent les signaux logiques en


tensions analogiques. Plusieurs types de convertisseurs sont disponibles dans
chaque catégorie, ils se différencient par leur précision, leur vitesse de
traitement de l'information, leur prix... On devra donc faire des compromis selon
ses besoins.

Il existe principalement deux types de convertisseurs numérique-analogique sur


le marché : les convertisseurs à résistances pondérées, et les convertisseurs à
réseau R/2R (ces derniers sont prédominants). Il existe également des
convertisseurs à réseaux de condensateurs fonctionnant sur le même principe
de base que les réseaux à résistances.

Principe de fonctionnement

Si on fait l'opération inverse de la conversion analogique-numérique, à chaque


valeur numérique on fait correspondre une et une seule valeur analogique; la
tension analogique de sortie varie par "bonds", et non plus continûment comme
dans le signal d'origine. La tension de sortie a une forme d'escalier.

ESME Sudria p.19/72


2003
En pratique, on filtre cette tension pour lisser ces discontinuités et essayer de
se rapprocher au mieux du signal d'origine :

Définitions

Résolution

La résolution du CNA est la variation de tension de sortie correspondant à la


variation d'une unité du nombre binaire en entrée. La définition est équivalente à
celle du CAN.

Plage de conversion

Il y a ici une petite différence avec le CAN, la plage de conversion numérique va


de 0 à 2(N-1), N étant le nombre de bits du convertisseur, et à chaque valeur
numérique correspond une unique valeur analogique de sortie. Par rapport à
celle du CAN, la plage de conversion s'arrête donc un LSB (bit le moins
significatif) plus tôt (sur l'échelle analogique du CAN, ceci correspond à la
dernière transition numérique).

Dynamique

La dynamique d'un signal est le rapport entre la tension maxi et la tension mini
que pourra prendre ce signal.

Mise en relation

D'après ce qui a été dit sur la plage de conversion, la relation entre le pas de
quantification (1 LSB), la plage de conversion VMAX et le nombre de bits du
convertisseur sera légèrement différente de l'équation suivante en pratique. La
figure du paragraphe suivant va éclairer cette équation :

DVMAX
LSB =
2N

ESME Sudria p.20/72


2003
Exemple : CNA 3 bits

Fonction de transfert d'un CNA 3 bits

Cette figure montre la fonction de transfert d'un CNA 3 bits ayant une résolution
de 1V. On voit clairement ici ce qui a été dit pour la plage de conversion : la
plage s'étend de 0 à 7V, et non pas 8V comme pour le CAN, car le dernier état
numérique est "7".

En pratique, pour un CAN supérieur à 8 bits, la différence avec le résultat


théorique donné par l’équation précédente est très faible.

ERREURS DE CONVERSION

Erreur de gain

Le fabricant de convertisseurs Analog Devices définit cette erreur ainsi : c'est


l'écart entre la valeur théorique et la valeur réelle mesurée sur la dernière
transition du convertisseur et exprimé en LSB. Cette mesure suppose que
l'ajustage du zéro soit parfait.

ESME Sudria p.21/72


2003
Illustration de l’erreur de gain.

Erreur d'offset

De même, le code binaire 0 ne correspond pas forcément à une tension


rigoureusement nulle en sortie. Cette tension est la tension de décalage, ou
d'offset.

Erreur d'offset.

ESME Sudria p.22/72


2003
En pratique, Analog Devices définit cette erreur comme étant l'écart entre la
valeur théorique et la valeur réelle mesurée sur la première transition du
convertisseur et exprimé en LSB. En pratique, pour ajuster un convertisseur, on
réglera d'abord l'offset, et ensuite le gain.

Erreurs de linéarité

L'erreur de linéarité est due au fait que la résolution des convertisseurs n'est
pas constante. On distingue deux formes de non-linéarité :

- Le non linéarité intégrale

La non linéarité intégrale (exprimée en LSB) est la différence maximale


constatée sur toute la plage de conversion entre les valeurs théoriques et les
valeurs mesurées.
Cette mesure n'a de sens que si le zéro et le gain sont correctement réglés. La
fonction est représentée dans la figure suivante.

Erreur de linéarité intégrale.

ESME Sudria p.23/72


2003
- La non linéarité différentielle

La non linéarité différentielle concerne la différence de tension obtenue lors du


passage au code numérique immédiatement supérieur ou inférieur.
Théoriquement, cette valeur vaut 1 LSB. La non linéarité différentielle sera la
différence entre l'écart mesuré et le LSB théorique.

Erreur de linéarité différentielle.

La valeur donnée dans les spécifications des constructeurs est la plus grande
valeur constatée sur toute la plage de conversion.

La non linéarité différentielle est plus gênante que la non linéarité intégrale,
surtout dans le cas de mesures comparatives effectuées sur une faible partie de
la plage de conversion. En général, et pour des causes technologiques, le
maximum de non linéarité différentielle se trouve à la moitié de la pleine échelle
(passage du MSB – bit le plus significatif - de 0 à 1), et ensuite à moindre
degré à 1/4 et 3/4 de la pleine échelle. Il faut donc rester vigilant lors de
mesures dans ces zones.

ESME Sudria p.24/72


2003
Monotonicité

Ce phénomène est le même que le précédent, mais poussé à l'extrême : il peut


arriver que la pente de la courbe de conversion change de signe. Pour une
tension analogique de sortie, il n’est pas possible d'attribuer un nombre binaire
correspondant : plusieurs valeurs peuvent être attribuées à une même
combinaison logique.

Monotonicité

Temps d'établissement

Les étages de sortie des CNA sont généralement des amplificateurs


opérationnels. On a vu que la tension de sortie varie "par bonds" quand le code
binaire d'entrée change. De ce fait, l'ampli de sortie va fonctionner en mode
impulsionnel. La stabilisation de la tension de sortie n'est pas immédiate : elle
peut être du type premier ordre ou oscillatoire amortie (deuxième ordre et plus).

ESME Sudria p.25/72


2003
On appelle temps d'établissement (setting time en Anglais) le temps mis par la
sortie pour atteindre un certain pourcentage de la tension finale stabilisée
lorsque l'entrée va varier.

Temps d'établissement

Précision du convertisseur

Pour obtenir la précision globale du convertisseur, on cumule toutes les erreurs


précédemment citées.

En général, ces erreurs sont données soit en % de la pleine échelle, soit en


fraction de quantum (± 1/2 LSB par exemple).

Adaptateur de sortie

Conversion [+2,5v ; 0v] => [+5v ; -5v] :

Nous devons adapter le signal de sortie du CNA. Il faut augmenter l’amplitude


du signal de [+2,5v ; 0v] à [+5v ; -5v] pour alimenter correctement la MCC.

Équation à réaliser : Vs = 4Ve - 5


ESME Sudria p.26/72
2003
On utilise à nouveau deux AOP en série. Le premier en tant qu’amplificateur
inverseur et le second en montage sommateur.
La borne V-, du premier AOP, reçoit en entrée le signal de sortie du CNA, et
celle du second AOP est connectée à la sortie du premier. Les bornes V+ des
deux AOP sont reliées à la masse.

Le choix des résistances est fait de telle sorte que :

R2 = 4 R1
et
R3 = R4 = R5

Une fois de plus après avoir effectué les calculs théoriques nous avons simulé
l’ensemble et voici les résultats obtenus :

ESME Sudria p.27/72


2003
Nous remarquons que le signal est réadapté et l’amplitude du signal de sortie a
bien une amplitude comprise entre –5 et +5 volts, comme le signal injecté à
l’entrée du module.

Réalisation

Nomenclature

Nb Référence Désignation
1 PIC 16F876 Microcontrôleur RISC 8 bits
1 AD557 Convertisseur Numérique Analogique 8 bits
1 MM5452 Contrôleur LCD
1 vi-502 Afficheur LCD 7 segments - 4 digits
1 TL084 AOP jfet (x4 AOP)
1 Support tulipe 28 broches
1 Support tulipe 16 broches (7,5 mm)
2 Support tulipe 40 broches
1 Support tulipe 14 broches (7,5 mm)
6 Support tulipe 8 broches (7,5 mm)
2 Support tulipe barrette de 32 broches
2 470 Ω Résistance
1 5 kΩ Résistance
10 10 kΩ Résistance
3 20 kΩ Résistance
1 50 kΩ Résistance
2 15 pF Condensateur
1 15 pF Condensateur
1 10 nF Condensateur
1 47 µF Condensateur
1 100 µF Condensateur
5 100 nF Condensateur
1 Quartz 4MHz
1 Interrupteur ON/OFF
4 Bouton poussoir
1 Led verte Ø3 mm
1 Led rouge Ø3 mm
15 m Fil rouge (5V)
15 m Fil noir (5V)
15 m Fil vert (5V)
1 Bornier ( IN & OUT coax. / +5v / +12v / -12v / GND )

ESME Sudria p.28/72


2003
Schéma de câblage

ESME Sudria p.29/72


2003
Procédures de tests

Pour tester le bon fonctionnement du CAN, on lui injecte un signal quelconque,


puis on lit le résultat de la conversion en sortie du PIC à l’aide de 8 diodes
placées sur chacun des bits du bus de sortie.

Le test du CNA se fait en même temps que le test du correcteur proportionnel,


quand K vaut 1. Nous injectons en entrée un signal sinusoïdal et nous devons
visualiser sur l’oscilloscope une sinusoïde similaire de même amplitude. Nous
effectuons le même test avec cette fois-ci K égal à 2. Nous devons pouvoir
visualiser une sinusoïde ayant une amplitude 2 fois plus grande que celle
injectée en entrée.

Signaux d’entrée et de sortie pour Kp=3

ESME Sudria p.30/72


2003
Pour tester l’action intégrale du correcteur on injecte un signal carré en entrée et
nous devons visualiser un signal triangulaire sur l’oscilloscope.

Signaux d’entrée et de sortie pour Ki=1

Pour tester l’action dérivée il faut injecter un signal triangulaire en entrée et nous
devons récupérer en sortie un signal carré.

Signaux d’entrée et de sortie pour Kd=9

Pour vérifier le bon fonctionnement de l’afficheur il suffit d’afficher différentes


valeurs afin d’essayer toutes les possibilités d’affichage.

ESME Sudria p.31/72


2003
Montage final

Maquette réalisée durant toute la durée du projet.

Recto

Verso

ESME Sudria p.32/72


2003
C – PROGRAMMATION
Organisation du programme

Avant de procéder à l’élaboration du programme contenu dans le PIC, il est


préférable d’établir au préalable un algorithme qui définisse son principe de
fonctionnement.

L’organigramme suivant décrit sommairement l’organisation du programme. Il


modélise l’effet d’un reset, représente la détection et le traitement des
interruptions, et enfin décrit la boucle principale réalisant la correction.
L’asservissement se fait en trois phases : l’échantillonnage, le calcul du PID et
l’émission du résultat sur le port C.

ESME Sudria p.33/72


2003
La réalisation d’un asservissement PID se résume à l’application de la formule :
u(k) = Kp e(k) + Ki [ u(k-1) + e(k) ] + Kd [ e(k) - e(k-1) ]
L’organigramme suivant illustre le traitement de la correction.

ESME Sudria p.34/72


2003
Formatage des données

La tension du signal d’entrée du module P.I.D. réalisé varie entre -5V et +5V. Il
est donc nécessaire grâce à un adaptateur d’étalonner ce signal entre 0 et 5V
pour l’injecter dans le CAN. À chaque valeur de tension correspondra une
valeur numérique. Le paragraphe suivant à pour but d’expliquer le processus de
formatage des données et les correspondances entre les valeurs analogiques et
numériques.

Le CAN échantillonne sur 10 bits un signal initial compris entre -5V et +5V.

e (k) : +5V 1023

-5V 0

Le résultat de la conversion analogique-numérique est stocké dans les registres


ADRESH (bits de poids fort) et ADRESL (bits de poids faible).
Si l’on choisit de mettre le bit ADFM = ‘0’ (bit 7 du registre ADCON1), alors on
choisit d’effectuer la justification à gauche, c’est-à-dire que le registre ADRESH
reçoit les 8 bits de poids fort de la conversion, et ADRESL récupère les 2 bits de
poids faible restants.
On fait abstraction des 2 bits de poids faible (ADRESL) pour faciliter le calcul de
la correction. On obtient donc une conversion sur 8 bits :

e (k) : +5V (ADRESH) : 255

-5V 0

Pour appliquer la formule de correction, on doit recentrer le signal sur 0. On


soustrait donc 127 au registre ADRESH :

e (k) : +5V (ADRESH-127) : 128

-5V -127

=> ADRESH – 127 = a . e (k) (avec a = 128/5)

Pour effectuer la correction, on travaille avec [ a . e (k) ] plutot que de travailler


directement avec e (k) car les valeurs des échantillons sont comprises entre
-5V et +5V, et ces valeurs sont trop petites pour avoir une résolution suffisante.
En effet, on ne peut pas travailler avec des valeurs décimales.
On utilise donc une valeur proportionnelle à e (k) pour faire la correction :
[ a . e (k) ] .

ESME Sudria p.35/72


2003
- Correction avec [ a . e (k) ] :

u(k) = Kp . e (k) + Kd . [e (k) - e (k-1) ] + Ki . [e (k) + u(k-1) ]


e (k) a e (k)
a u(k) = Kp . a e (k) + Kd . [ a e (k) - a e (k-1) ]
+ Ki . [ a e (k) + a u(k-1) ]

On constate qu’en effectuant la correction avec [ a . e (k) ] , on obtient :


[ a . u(k) ] .

Avec : -127 ≤ a . u(k) ≤ 128

On réadapte le résultat pour l’injecter en sortie du Pic (8 bits).


Pour cela, on ajoute 127 à [ a . u(k) ] :
0 ≤ a . u(k) + 127 ≤ 255

[ a u(k) + 127 ] : 255 +5V

0 -5V

ESME Sudria p.36/72


2003
La programmation d’un microcontrôleur PIC 16F876 se fait en langage
« MPASM ». Il s’agit d’un langage assembleur spécifique créé par Microchip. Ce
langage dispose d’un jeu de 35 instructions assez peu explicites, d’où la
nécessité de bien structurer le programme et de le commenter convenablement.

Configuration du PIC :
Création d’une en-tête regroupant les principales
informations du programme :

Celle-ci est facultative, mais elle peut s’avérer très utile pour la mise en œuvre
du PIC dans un circuit. Elle regroupe des informations essentielles :
- le nom du fichier (celui ci doit être compilé puis injecté dans le PIC),
- la liste des fichiers à inclure dans le projet pour que la compilation soit
possible (dans notre cas, il s’agit du fichier librairie : « P16F876.inc »),
- la fréquence de l’oscillateur externe pour laquelle est conçu ce programme
(ici : 4 MHz),
- l’affectation des ports d’entrées-sorties pour le câblage du PIC.

;***************************************************************************************
;* *
;* Réalisation d'un asservissement PID *
;* *
;***************************************************************************************
;* *
;* NOM: projet.asm *
;* Date: 23/05/2003 *
;* Auteurs: BRUYERE Philippe - GOMBERT Benjamin - VENCE Eric *
;* Groupe de projet : P205 *
;* *
;***************************************************************************************
;* *
;* Fichiers requis: P16F876.inc *
;* *
;***************************************************************************************
;* *
;* Notes: On utilise un oscillateur 4 MHz *
;* Les 8 bits de sortie sont disponibles après correction sur le PORTC *
;* L'affichage des paramètres est transmis par la sortie série du PORTB *
;* Les boutons poussoir génèrent des interruptions sur les entrées *
;* RB4 à RB6 du PORTB *
;* *
;***************************************************************************************

ESME Sudria p.37/72


2003
Déclaration du modèle de PIC utilisé et appel de la librairie
en vigueur :

LIST p=16F876 ; Définition du processeur


#include <p16F876.inc> ; fichier include

Directive “CONFIG” :
La directive CONFIG permet de configurer le compilateur pour que celui-ci
reconnaisse chacun des paramètres de programmation du PIC sans qu’il ne soit
nécessaire de les préciser à chaque fois. Cette directive permet notamment de
déclarer le type d’oscillateur utilisé ainsi que les différents modes de protection
utilisés par le PIC et sa mémoire.

__CONFIG _CP_OFF & _DEBUG_OFF & _WRT_ENABLE_OFF & _CPD_OFF & _LVP_OFF &
_BODEN_OFF & _PWRTE_ON & _WDT_OFF & _XT_OSC
; _CP_OFF Pas de protection
; _DEBUG_OFF RB6 et RB7 en utilisation normale
; _WRT_ENABLE_OFF Le programme ne peut pas écrire dans la flash
; _CPD_OFF Mémoire EEprom déprotégée
; _LVP_OFF RB3 en utilisation normale
; _BODEN_OFF Reset tension hors service
; _PWRTE_ON Démarrage temporisé
; _WDT_OFF Watchdog hors service
; _XT_OSC Oscillateur XT

Affectations des entrées-sorties :


Pour un bon fonctionnement du PIC, il est nécessaire d’attribuer à chacune de
ses pins un statut d’entrée ou de sortie afin que le microcontrôleur sache s’il doit
lire ou écrie sur chaque pin. Ces affectations doivent être faites par rapport aux
fonctions qu’offre chaque pin.
Dans notre cas, nous avons besoin d’une entrée analogique que l’on branche
sur l’entrée RA0 du PORTA. Les 8 bits de sortie sont ceux du PORTC car nous
réservons le PORTB au traitement des interruptions générées par les bouton-
poussoirs (le PORTB étant le seul port à gérer les interruptions). Les signaux de
contrôle du driver LCD sont disponibles sur deux pins encore libres sur le
PORTB (RB0 et RB1).
Les pins non utilisées sont déclarées comme des sorties.

;*********************************************************************************
;* ASSIGNATIONS SYSTEME *
;*********************************************************************************

; DIRECTION DES PORTS I/O


; --------------------------------------
; (1=entrée ; 0=sortie)

ESME Sudria p.38/72


2003
DIRPORTA EQU B'00000001' ; Direction PORTA (registre TRISA)
; RA0 : entrée analogique
; RA1 : N.C.
; RA2 : N.C.
; RA3 : N.C.
; RA4 : N.C.
; RA5 : N.C.
; on récupère le résultat de la conversion A->N
; dans les registres ADRESH (Bank0) et ADRESL (Bank1)

DIRPORTB EQU B'01110000' ; Direction PORTB


; RB0 : sortie CLK série pour le driver LCD
; RB1 : sortie DATA série pour le driver LCD
; RB2 : N.C.
; RB3 : N.C.
; RB4 : entrée BP [+]
; RB5 : entrée BP [-]
; RB6 : entrée BP [V]
; RB7 : N.C.

DIRPORTC EQU B'00000000' ; Direction PORTC


; RC0 à RC7 : 8 bits du bus de sortie

Assignations des registres de configuration :


Il est préférable d’effectuer ces assignations au début du programme, cela
facilite leur modification et évite de devoir parcourir le programme pour retrouver
ces registres.
Ceux définis ci-après permettent d’activer et de paramétrer les différents
modules dont dispose le PIC (dans le cadre de ce projet, nous utiliserons
uniquement le module de conversion analogique-numérique et le module de
détection des interruptions).
Ces valeurs seront chargées lors de l’initialisation par la routine « INIT ».

Configuration du convertisseur analogique–numérique :


Le registre « ADCON1 » permet de choisir le nombre d’entrées analogiques
ainsi que le type de justification. Nous avons besoin d’une seule entrée de ce
type d’où la valeur des bits de configuration du port : PCFGx = ‘1110’. Le
convertisseur intégré dans le PIC effectue une conversion sur 10 bits. Le
résultat est stocké sur 2 octets : « ADRESH » (octet de poids fort) et
« ADRESL » (octet de poids faible). Le processeur ayant une architecture RISC
8 bits, il serait inutile, et assez complexe, de conserver et d’exploiter ce résultat
sur 10 bits. Nous faisons donc abstraction des deux bits les moins significatifs. Il
suffit de choisir une justification à gauche (ADFM = 0), ainsi les 8 bits de poids
forts de la conversion sont stockés dans le registre « ADRESH ». Il ne reste
plus qu’à le lire.
Le registre « ADCON0 » permet de définir la fréquence d’échantillonnage du
PIC, et de choisir la pin sur laquelle sera effectuée la conversion. L’oscillateur
utilisé étant fixé à 4MHHz, la fréquence d’échantillonnage maximum que l’on
puisse choisir est de 500KHz (ADCSx = ‘01’). Pour terminer la configuration du
module de conversion analogique–numérique, il reste à définir le canal d’entrée.
Nous choisissons la pin RAO du PORTA qui correspond au canal « A/D 0 »
(CHSx = ‘000’).
ESME Sudria p.39/72
2003
; REGISTRE ADCON1 (ANALOGIQUE/DIGITAL)
; -------------------------------------------------------------

ADCON1VAL EQU B'00001110' ; Registre ADCON1 (configuration du port A/D)


; PCFG = 1110 => 1 entrée analogique (RA0)
; ADFM = 0 => justification à gauche
; bit0 : PCFG0 : Port ConFiGuration control bit0
; bit1 : PCFG1 : Port ConFiGuration control bit1
; bit2 : PCFG2 : Port ConFiGuration control bit2
; bit3 : PCFG3 : Port ConFiGuration control bit3
; bit4 : Non implémenté
; bit5 : Non implémenté
; bit6 : Non implémenté
; bit7 : ADFM : A/D result ForMat select

; REGISTRE ADCON0 (ANALOGIQUE/DIGITAL)


; -------------------------------------------------------------

; ADCS1 | ADCS0 | Diviseur | Fréquence Max du quartz


; -----------+----------+-------------+----------------------------------------------------------
; 0 | 0 | Fosc/2 | 1.25 MHz
; 0 | 1 | Fosc/8 | 5 MHz => fe = 500 KHz
; 1 | 0 | Fosc/32 | 20 MHz => fe = 125 KHz
; 1 | 1 | Osc RC | Si > 1 MHz, uniquement en mode "sleep"

; CHS = B'000' => choix du canal A/D 0 (pin RA0)

ADCON0VAL EQU B'01000000' ; Registre ADCON0 (configuration du port A/D)


; bit0 : ADON : A/D ON bit
; bit1 : Non implémenté
; bit2 : GO/DONE : A/D conversion status bit
; bit3 : CHS0 : analog Channel Select bit0
; bit4 : CHS1 : analog Channel Select bit1
; bit5 : CHS2 : analog Channel Select bit2
; bit6 : ADCS0 : A/D conversion Clock Select bit0
; bit7 : ADCS1 : A/D conversion Clock Select bit1

Mise en service des interruptions :


Le registre « INTCON » permet de choisir les interruptions standards que l’on
souhaite traiter. Nous disposons de trois bouton-poussoirs branchés sur les pins
RB4 à RB6. Il faut donc activer le masque d’interruption RB4/RB7 (RBIE=1) et
le masque d’autorisation général des interruptions (GIE = 1). Le masque
d’autorisation général des périphériques (PEIE) est mis à ‘1’ pour pouvoir utiliser
le « TIMER1 ».

; REGISTRE INTCON (contrôle interruptions standard)


; --------------------------------------------------------------------
INTCONVAL EQU B'11001000'
; bit0 : RBIF : flag interruption RB4/RB7
; bit1 : INTF : flag RB0/Int
; bit2 : T0IF : flag tmr0
; bit3 : RBIE : masque interruption RB4/RB7
; bit4 : INTE : masque interruption RB0/Int
; bit5 : T0IE : masque interruption tmr0
; bit6 : PEIE : masque autorisation générale périphériques
; bit7 : GIE : masque autorisation générale interruption

ESME Sudria p.40/72


2003
Le « TIMER 1 » est un module de comptage 16 bits de cycles d’horloge. Il peut
être couplé sur un oscillateur externe ou bien sur le même oscillateur que celui
du PIC. Dans notre cas, le timer sera utilisé pour faire clignoter l’afficheur (pour
mettre en relief le « curseur »).
Dans le registre « PIE1 », le bit « TMR1IE » permet s’il est mis à ‘1’, de traiter
les interruptions engendrées par le « TIMER 1 ».

; REGISTRE PIE1 (contrôle interruptions périphériques)


; --------------------------------------------------------------------
PIE1VAL EQU B'00000001'
; bit0 : TMR1IE : masque interruption débordement tmr1
; bit1 : TMR2IE : masque interruption TMR2 = PR2
; bit2 : CCP1IE : masque interruption CCP1
; bit3 : SSPIE : masque interruption port série synchrone
; bit4 : TXIE : masque interruption transmission USART
; bit5 : RCIE : masque interruption réception USART
; bit6 : ADIE : masque interruption convertisseur A/D
; bit7 : PSPIE : Toujours 0 sur le PIC 16F876

Le registre « T1CON » configure le « TIMER 1 ». Le bit « TMR1ON » met en


service ce timer et les bits « T1CKPSx » offrent le choix d’un pré-diviseur. En
utilisant l’oscillateur du PIC et un pré-diviseur égal à 8, nous obtenons un
compteur qui génère une interruption tous les 524288 cycles (soit 8 x 65536 = 8
x 2^16), c’est-à-dire une interruption toutes les 0,5s (avec un oscillateur de
4MHz). Le curseur de notre afficheur clignotera donc avec une période d’une
seconde.

; REGISTRE T1CON (configuration du Timer 1)


; ----------------------------------------------------------
T1CONVAL EQU B'00110001'
; bit0 : TMR1ON : TiMeR 1 ON bit
; bit1 : TMR1CS : TiMeR 1 Clock Source select bit
; bit2 : T1SYNC : Timer 1 external clock input SYNChronisation control bit
; bit3 : T1OSCEN : Timer 1 OSCillator ENable control bit
; bit4 ; T1CKPS0 : Timer 1 oscillator ClocK Prescale Select bit 0
; bit5 : T1CKPS1 : Timer 1 oscillator ClocK Prescale Select bit 1
; bit6 : Inutilisé : lu comme ‘0’
; bit7 : Inutilisé : lu comme ‘0’

; T1CKPS1 | T1CKPS0 | Valeur du pré-diviseur


; -------------+-------------+------------------------------
; 0 | 0 | 1 -> 65536 cycles (65ms à 4MHz)
; 0 | 1 | 2
; 1 | 0 | 4
; 1 | 1 | 8 -> 524288 cycles (0.5s à 4MHz)

ESME Sudria p.41/72


2003
Mise en place de “Macros” :
La définition de macros rends le programme plus structuré et plus simple à
comprendre. Les macros suivantes permettent de sélectionner une banque
particulière en positionnant les 2 bits concernés. Il est évident qu’il n’est pas
toujours nécessaire de repositionner les 2 bits. Néanmoins, l’utilisation de ces
macros ne nécessite qu’une ligne de code supplémentaire, et elle limite
fortement les risques d’erreurs.

;*********************************************************************************
;* MACROS *
;*********************************************************************************
; Changement de banques
; --------------------------------

BANK0 macro ; passer en banque0


bcf STATUS,RP0
bcf STATUS,RP1
endm
BANK1 macro ; passer en banque1
bsf STATUS,RP0
bcf STATUS,RP1
endm
BANK2 macro ; passer en banque2
bcf STATUS,RP0
bsf STATUS,RP1
endm
BANK3 macro ; passer en banque3
bsf STATUS,RP0
bsf STATUS,RP1
endm

Déclaration des constantes :


Pour faciliter la relecture d’un programme, il est préférable d’utiliser des
constantes définies au préalable dont le nom est plus évocateur qu’une valeur
quelconque. Ici sont déclarées les constantes de chaque caractère retranscrit
sur sept segments.

; Déclaration des codes permettant d'afficher chaque chiffre sur 7 segments :


; -------------------------------------------------------------------------------------------------
UN EQU B'00001100' ;1
DEUX EQU B'10110110' ;2 bit0 : Virgule A 1
TROIS EQU B'10011110' ;3 bit1 : A ==== ====
QUATRE EQU B'11001100' ;4 bit2 : B F || || B 6 || || 2
CINQ EQU B'11011010' ;5 bit3 : C || G || || 7 ||
SIX EQU B'11111010' ;6 bit4 : D ==== ==> ====
SEPT EQU B'01001110' ;7 bit5 : E E || || C 5 || || 3
HUIT EQU B'11111110' ;8 bit6 : F || D || || 4 ||
NEUF EQU B'11011110' ;9 bit7 : G ==== ====
ZERO EQU B'01111110' ;0
TRAIT EQU B'10000000' ;-

ESME Sudria p.42/72


2003
Allocation de l’espace mémoire :
Pour traiter les données, il est indispensable d’utiliser des variables. En effet,
celles-ci permettent de stocker des valeurs et elles facilitent la compréhension
du programme si leur nom est choisi judicieusement. Chaque variable doit
disposer d’un espace mémoire dédié. Il faut déclarer chacune d’elles dans une
zone mémoire. Le PIC 16F876 dispose de 80 octets de mémoire RAM par
banque et de 16 octets de mémoire RAM en zone commune.
La mémoire en zone commune est accessible depuis n’importe quelle banque.
Nous l’utiliserons pour faire les sauvegardes de variables temporaires lors du
traitement des interruptions et pour stocker les valeurs de chaque digit car
celles-ci doivent être accessibles à tout moment.

;****************************************************************************
; VARIABLES ZONE COMMUNE *
;****************************************************************************
; Zone de 16 bytes
; -----------------------
CBLOCK 0x70 ; Début de la zone (0x70 à 0x7F)
w_temp : 1 ; Sauvegarde registre W
status_temp : 1 ; Sauvegarde registre STATUS
digit1 : 1 ; définition des 7 segments (+ virgule) du 1er digit
digit2 : 1 ; définition des 7 segments (+ virgule) du 2nd digit
digit3 : 1 ; définition des 7 segments (+ virgule) du 3ème digit
digit4 : 1 ; définition des 7 segments (+ virgule) du 4ème digit
ENDC ; Fin de la zone

Le programme s’exécute principalement dans la banque 0 (hormis lors des


interruptions), donc la majorité des variables est déclarée dans l’espace
mémoire de la banque 0.

;****************************************************************************
;* DECLARATIONS DES VARIABLES *
;****************************************************************************
; Zone de 80 bytes
; ----------------------- ; Allocation de l'espace mémoire de la bank0 et déclaration des variables
CBLOCK 0x20 ; Début de la zone (0x20 à 0x6F)
menu : 1 ; pointeur de menu
choixParam : 1 ; Variable de choix du paramètre à modifier
; u(k) = Kp £(k) + Ki [u(k-1)+£(k)] + Kd [£(k)-£(k-1)]
cligno : 1 ; Variable d'état de clignotement
parametre1 : 1 ; paramètre n°1 : Kp
parametre2 : 1 ; paramètre n°2 : Ki
parametre3 : 1 ; paramètre n°3 : Kd
parametre4 : 1 ; paramètre n°4 : Limite d'intégration
cmpt1 : 1 ; compteur n°1
cmpt2 : 1 ; compteur n°2
resultConv : 1 ; résultat 8 bits de la conversion Analogique -> Numérique
resultConv2 : 1 ; ancien résultat 8 bits de la conversion Analogique -> Numérique
result1 : 1 ; résultat du calcul de la proportionnelle
result2 : 1 ; résultat du calcul de la dérivée
result3 : 1 ; résultat du calcul de l'intégrale
result4 : 1 ; somme de result1 et result2

ESME Sudria p.43/72


2003
resultPID : 1 ; résultat du calcul du PID
resultPID2 : 1 ; ancien résultat du calcul du PID
sourceInt : 1 ; source d'interruption
vartemp : 1 ; variable temporaire
vardigit : 1 ; variable de digit
varparam : 1 ; variable de paramètre
var1 : 1 ; variable n°1
var2 : 1 ; variable n°2
var3 : 1 ; variable n°3
produitH : 1 ; poids fort du résultat 16 bits de la multiplication 8x8bits
produitL : 1 ; poids faible du résultat 16 bits de la multiplication 8x8bits
sommeH : 1 ; poids fort du résultat de l'addition 8 bits (dépassement)
sommeL : 1 ; poids faible du résultat de l'addition 8 bits
diffH : 1 ; poids fort du résultat de la soustraction 8 bits
diffL : 1 ; poids faible du résultat de la soustraction 8 bits
signe : 1 ; bits de signe
resultDep : 1 ; variable de stockage du dépassement des opérations mathématiques 8 bits
ENDC ; Fin de la zone

;*************************************************************************
;* DEMARRAGE SUR RESET *
;*************************************************************************
org 0x000 ; Adresse de départ après reset
goto INIT ; Initialiser

Détection et traitement des interruptions :


Détection des interruptions :
La routine « interruptions » contient tous les tests qui permettent d’aiguiller les
interruptions vers la bonne sous-routine. Tout d’abord elle effectue la
sauvegarde des différents registres.
« w_temp » est la sauvegarde du registre de travail « W ». Ce registre va être
utilisé pour la sauvegarde des autres registres. C’est donc le premier qui doit
être sauvé. Au moment de l’interruption, on ne peut pas savoir comment sont
configurés les bits RP0 et RP1, donc on ne sait pas vers quelle banque ils
pointent. De ce fait, il est impératif de sauvegarder « W » dans la zone de RAM
commune.
« status_temp » doit être sauvegardé car après le traitement des interruptions,
le programme doit reprendre son cours avec le même statut (notamment dans
la même banque).

;*************************************************************************
;* ROUTINE INTERRUPTION *
;*************************************************************************
;sauvegarder les registres
;-------------------------------
org 0x004 ; adresse d'interruption
movwf w_temp ; sauver registre W
swapf STATUS,w ; swap status avec résultat dans w
movwf status_temp ; sauver status swappé
BANK0 ; passer en banque0

ESME Sudria p.44/72


2003
Pour tester les interruptions engendrées par les bouton-poussoirs, il faut avant
tout vérifier que le masque d’interruption sur RB4/7 est activé. Il suffit ensuite de
lire le « flag » d’interruption « RRBIF ». Par sécurité et pour éviter le phénomène
de « rebond », des boucles de test du relâchement de chaque bouton sont
ajoutées. Si une interruption sur RB4/7 est détectée, la sous-routine de
traitement de cette interruption « INTBP » est appelée puis le flag d’interruption
est effacé.

; Test et appel des différentes interruptions


;-----------------------------------------------------
; Interruption RB4/RB7
INT1 ; ---------------------------
btfsc INTCON,RBIE ; tester si interruption RB4/7 autorisée
btfss INTCON,RBIF ; oui, tester si interruption RB4/7 en cours
goto INT2 ; non sauter
call INTBP ; oui, traiter interruption RB4/7
btfsc PORTB,4 ; tester si BP1 [+] appuyé
goto $-1 ; oui, attendre
btfsc PORTB,5 ; tester si BP2 [-] appuyé
goto $-1 ; oui, attendre
btfsc PORTB,6 ; tester si BP3 [V] appuyé
goto $-1 ; oui, attendre
bcf INTCON,RBIF ; effacer flag interruption RB4/7
goto RESTORE ; et fin d'interruption

Pour tester les interruptions générées par le « TIMER1 », il faut vérifier que le
masque d’interruption « TMR1IE » soit activé (attention, ce registre se trouve
dans la banque 1). Il suffit ensuite de lire le « flag » d’interruption « TMR1IF »
(banque 0). Si une interruption sur le timer 1 est détectée, la sous-routine de
traitement « INTTMR » est appelée puis le flag d’interruption est effacé.

; Interruption TMR1
INT2 ; -----------------------
bsf STATUS,RP0 ; sélectionner banque1
btfss PIE1,TMR1IE ; tester si interruption autorisée
goto RESTORE ; non sauter
bcf STATUS,RP0 ; oui, sélectionner banque0
btfss PIR1,TMR1IF ; oui, tester si interruption en cours
goto RESTORE ; non sauter
call INTTMR1 ; oui, traiter interruption TMR1
bcf PIR1,TMR1IF ; effacer flag interruption

Lors de la fin du traitement, « STATUS » et « W » sont restaurés tels qu’ils


étaient avant l’interruption.

; Restaurer registres
RESTORE ; -----------------------
swapf status_temp,w ; swap ancien status, résultat dans w
movwf STATUS ; restaurer status
swapf w_temp,f ; Inversion L et H de l'ancien W sans modifier Z
swapf w_temp,w ; Ré-inversion de L et H dans W (W restauré sans modifier status)
retfie ; return from interruption

ESME Sudria p.45/72


2003
Traitement des interruptions sur RB4/7 :
Chaque interruption détectée sur un bouton poussoir a un effet différent sur le
programme en fonction du menu en cours d’exécution. Le menu en cours est
pointé par la variable « menu ». Un test est donc effectué sur cette variable pour
accéder au menu pointé.
;*************************************************************************
;* INTERRUPTION RB4/RB7 *
;*************************************************************************
INTBP
movf PORTB,w ; Chargement du PORTB
movwf sourceInt ; écriture dans la variable "sourceInt"

Si le menu pointé est le menu n°1, c’est-à-dire le menu de modification du


paramètre Kp, alors le paramètre n°1 est :
- incrémenté si l’interruption provient du BP1 [+] (si le paramètre dépasse 9, on
boucle en le remettant à 0),
- décrémenté si l’interruption provient du BP2 [-] (si le paramètre devient
inférieur à 0, on boucle en le remettant à 9),
- validé si l’interruption provient du BP3 [V] , et la variable « menu » est effacée
pour qu’elle pointe vers le menu n°0.
TESTMENU1
decfsz menu,f ; décrémenter le pointeur de menu
goto TESTMENU2 ; menu != 0 ?
; MENU 1 : Menu de modification du paramètre n°1 : Kp
; ------------------------------------------------------------------------
btfss sourceInt,4 ; bit RB4=1 ?
goto TESTM1
incf parametre1,f ; oui -> interruption sur le PB1 [+] -> on incrémente le paramètre 1
movf parametre1,w
sublw 0x0A
btfsc STATUS,Z ; tester si W = 0
clrf parametre1 ; si parametre1 = 10, on boucle le menu en remettant parametre1 = 0
goto TESTV1
TESTM1
btfss sourceInt,5 ; bit RB5=1 ?
goto TESTV1
movf parametre1,w
btfsc STATUS,Z ; tester si W = 0
movlw 0x0A ; si parametre1 = 0, on boucle le menu en remettant parametre1 = 10
movwf parametre1
decf parametre1,f ; oui -> interruption sur le PB2 [-] -> on décrémente le paramètre 1
TESTV1
movlw 0x01
btfss sourceInt,6 ; bit RB6=1 ?
goto TESTF1
movlw 0x00 ; oui -> interruption sur le PB3 [V] -> on passe au menu 0
clrf choixParam
TESTF1
movwf menu ; passage au menu en vigueur
movf parametre1,w ; conversion de parametre1 (chiffres) en digit1 (7 segments)
movwf vardigit
call CONVDIGIT
movwf digit1
goto FINMENU

ESME Sudria p.46/72


2003
Si le menu pointé est le menu n°2, c’est-à-dire le menu de modification du
paramètre Ki, alors le paramètre n°2 est :
- incrémenté si l’interruption provient du BP1 [+] (si le paramètre dépasse 9, on
boucle en le remettant à 0),
- décrémenté si l’interruption provient du BP2 [-] (si le paramètre devient
inférieur à 0, on boucle en le remettant à 9),
- validé si l’interruption provient du BP3 [V] , et la variable « menu » est effacée
pour qu’elle pointe vers le menu n°0.

TESTMENU2
decfsz menu,f ; décrémenter le pointeur de menu
goto TESTMENU3 ; menu != 0 ?

; MENU 2 : Menu de modification du paramètre n°2 : Ki


; ------------------------------------------------------------------------

btfss sourceInt,4 ; bit RB4=1 ?


goto TESTM2
incf parametre2,f ; oui -> interruption sur le PB1 [+] -> on incrémente le paramètre 2
movf parametre2,w
sublw 0x0A
btfsc STATUS,Z ; tester si W = 0
clrf parametre2 ; si parametre2 = 10, on boucle le menu en remettant parametre2 = 0

goto TESTV2
TESTM2
btfss sourceInt,5 ; bit RB5=1 ?
goto TESTV2
movf parametre2,w
btfsc STATUS,Z ; tester si W = 0
movlw 0x0A ; si parametre2 = 0, on boucle le menu en remettant parametre2 = 10
movwf parametre2
decf parametre2,f ; oui -> interruption sur le PB2 [-] -> on décrémente le paramètre 2
TESTV2
movlw 0x02
btfss sourceInt,6 ; bit RB6=1 ?
goto TESTF2
movlw 0x00 ; oui -> interruption sur le PB3 [V] -> on passe au menu 0
clrf choixParam
TESTF2
movwf menu ; passage au menu en vigueur

movf parametre2,w ; conversion de parametre2 (chiffres) en digit2 (7 segments)


movwf vardigit
call CONVDIGIT
movwf digit2

goto FINMENU

ESME Sudria p.47/72


2003
Si le menu pointé est le menu n°3, c’est-à-dire le menu de modification du
paramètre Kd, alors le paramètre n°3 est :
- incrémenté si l’interruption provient du BP1 [+] (si le paramètre dépasse 9, on
boucle en le remettant à 0),
- décrémenté si l’interruption provient du BP2 [-] (si le paramètre devient
inférieur à 0, on boucle en le remettant à 9),
- validé si l’interruption provient du BP3 [V] , et la variable « menu » est effacée
pour qu’elle pointe vers le menu n°0.

TESTMENU3
decfsz menu,f ; décrémenter le pointeur de menu
goto TESTMENU4 ; menu != 0 ?

; MENU 3 : Menu de modification du paramètre n°3 : Kd


; -------------------------------------------------------------------------

btfss sourceInt,4 ; bit RB4=1 ?


goto TESTM3
incf parametre3,f ; oui -> interruption sur le PB1 [+] -> on incrémente le paramètre 3
movf parametre3,w
sublw 0x0A
btfsc STATUS,Z ; tester si W = 0
clrf parametre3 ; si parametre3 = 10, on boucle le menu en remettant parametre3 = 0

goto TESTV3
TESTM3
btfss sourceInt,5 ; bit RB5=1 ?
goto TESTV3
movf parametre3,w
btfsc STATUS,Z ; tester si W = 0
movlw 0x0A ; si parametre3 = 0, on boucle le menu en remettant parametre3 = 10
movwf parametre3
decf parametre3,f ; oui -> interruption sur le PB2 [-] -> on décrémente le paramètre 3
TESTV3
movlw 0x03
btfss sourceInt,6 ; bit RB6=1 ?
goto TESTF3
movlw 0x00 ; oui -> interruption sur le PB3 [V] -> on passe au menu 0
clrf choixParam
TESTF3
movwf menu ; passage au menu en vigueur

movf parametre3,w ; conversion de parametre3 (chiffres) en digit3 (7 segments)


movwf vardigit
call CONVDIGIT
movwf digit3

goto FINMENU

ESME Sudria p.48/72


2003
Si le menu pointé est le menu n°4, c’est-à-dire le menu de modification de la
limite d’intégration, alors le paramètre n°4 est :
- incrémenté si l’interruption provient du BP1 [+] (si le paramètre dépasse 9, on
boucle en le remettant à 0),
- décrémenté si l’interruption provient du BP2 [-] (si le paramètre devient
inférieur à 0, on boucle en le remettant à 9),
- validé si l’interruption provient du BP3 [V] , et la variable « menu » est effacée
pour qu’elle pointe vers le menu n°0.

TESTMENU4
decfsz menu,f ; décrémenter le pointeur de menu
goto TESTMENU5 ; menu != 0 ?

; MENU 4 : Menu de modification du paramètre n°4 : Limite d'intégration


; ----------------------------------------------------------------------------------------------

btfss sourceInt,4 ; bit RB4=1 ?


goto TESTM4
incf parametre4,f ; oui -> interruption sur le PB1 [+] -> on incrémente le paramètre 4
movf parametre4,w
sublw 0x0A
btfsc STATUS,Z ; tester si W = 0
clrf parametre4 ; si parametre4 = 10, on boucle le menu en remettant parametre4 = 0

goto TESTV4
TESTM4
btfss sourceInt,5 ; bit RB5=1 ?
goto TESTV4
movf parametre4,w
btfsc STATUS,Z ; tester si W = 0
movlw 0x0A ; si parametre4 = 0, on boucle le menu en remettant parametre4 = 10
movwf parametre4
decf parametre4,f ; oui -> interruption sur le PB2 [-] -> on décrémente le paramètre 4
TESTV4
movlw 0x04
btfss sourceInt,6 ; bit RB6=1 ?
goto TESTF4
movlw 0x00 ; oui -> interruption sur le PB3 [V] -> on passe au menu 0
clrf choixParam
TESTF4
movwf menu ; passage au menu en vigueur

movf parametre4,w ; conversion de parametre4 (chiffres) en digit4 (7 segments)


movwf vardigit
call CONVDIGIT
movwf digit4

goto FINMENU

ESME Sudria p.49/72


2003
Si le menu pointé est le menu n°5, c’est-à-dire le menu de choix du paramètre à
modifier, alors « choixParam » est :
- incrémenté si l’interruption provient du BP1 [+] (si le paramètre dépasse 4, on
boucle en le remettant à 1),
- décrémenté si l’interruption provient du BP2 [-] (si le paramètre devient
inférieur à 1, on boucle en le remettant à 4),
- stocké dans la variable « menu » si l’interruption provient du BP3 [V].

TESTMENU5
decfsz menu,f ; décrémenter le pointeur de menu
goto TESTMENU0 ; menu != 0 ?

; MENU 5 : Menu de choix du paramètre à modifier


; -----------------------------------------------------------------
btfss sourceInt,5 ; bit RB5=1 ?
goto TESTM5
incf choixParam,f ; oui -> interruption sur le PB2 [-] -> on incrémente choixParam
movf choixParam,w
sublw 0x05
btfss STATUS,Z ; tester si W = 0
goto TESTV5
movlw 0x01 ; si choixParam = 5, on boucle le menu en remettant choixParam = 1
movwf choixParam
goto TESTV5
TESTM5
btfsc sourceInt,4 ; bit RB4=1 ?
decfsz choixParam,f ; oui -> interruption sur le PB1 [+] -> on décrémente choixParam
goto TESTV5
movlw 0x04 ; si choixParam = 0, on boucle le menu en remettant choixParam = 4
movwf choixParam
TESTV5
movlw 0x05
btfsc sourceInt,6 ; bit RB6=1 ?
movf choixParam,w ; oui => interruption sur le PB3 [V]
; => on passe au menu de modification du paramètre choisi
movwf menu ; passage au menu en vigueur

goto FINMENU

TESTMENU0
; MENU 0 : Menu de statique : attente d'une interruption
; --------------------------------------------------------------------------
btfss sourceInt,6 ; bit RB6=1 ?
goto FINMENU
movlw 0x05
movwf menu ; passage au choix du paramètre à modifier (menu 5)
movlw 0x01
movwf choixParam ; initialisation du pointeur du paramètre à modifier

FINMENU

CALL AFFICHAGE ; routine d'affichage des paramètres sur l'afficheur LCD


; rafraîchissement de l'afficheur

return ; fin d'interruption RB0/RB4

ESME Sudria p.50/72


2003
Si le menu pointé est le menu n°0, c’est-à-dire le menu statique, alors si
l’interruption provient du BP3 [V], la valeur 5 est stockée dans la variable
« menu » pour qu’elle pointe vers le menu n°5, menu de choix du paramètre à
modifier. « choixParam » est alors initialisée à ‘1’.

TESTMENU0
; MENU 0 : Menu de statique : attente d'une interruption
; ------------------------------------------------------------------------
btfss sourceInt,6 ; bit RB6=1 ?
goto FINMENU
movlw 0x05
movwf menu ; passage au choix du paramètre à modifier (menu 5)
movlw 0x01
movwf choixParam ; initialisation du pointeur du paramètre à modifier

Une fois toutes les possibilités de menus testées, et une fois le menu en cours
traité, le programme appelle la routine « AFFICHAGE » pour qu’elle rafraîchisse
les valeurs transmises à l’afficheur LCD.

FINMENU

CALL AFFICHAGE ; routine d'affichage des paramètres sur l'afficheur LCD


; rafraîchissement de l'afficheur

return ; fin d'interruption RB4/RB7

Fin du traitement des interruptions sur RB4/7.

Traitement des interruptions du TIMER 1 :


Toutes les 0,5s le timer 1 génère une interruption. A chacune de ces
interruptions, la variable « cligno » passe alternativement de ‘1’ à ‘2’. Si
« choixParam » est différent de 0 alors le menu en cours est différent du menu
n°0 (menu statique). On fait donc clignoter le curseur. Un test du paramètre
pointé par la variable « choixParam » est effectué afin de déterminer
l’emplacement du curseur. Le digit pointé par « choixParam » reste fixe et les
autres digits sont affichés puis effacés alternativement. Le curseur est alors le
seul digit affiché en permanence.

;*************************************************************************
;* INTERRUPTION TIMER 1 *
;*************************************************************************

INTTMR1
decfsz cligno,f ; tester la valeur de "cligno"
goto TESTPARAM0 ; cligno != 1
movf choixParam,w ; cligno = 1
movwf varparam
movlw 0x02
movwf cligno ; passage au choix du paramètre à modifier (menu 5)

ESME Sudria p.51/72


2003
TESTPARAM1
decfsz varparam,f ; décrémenter le pointeur de paramètre
goto TESTPARAM2 ; choixParam != 0 ?
movf parametre1,w ; conversion de parametre1 (chiffres) en digit1 (7 segments)
movwf vardigit
call CONVDIGIT
movwf digit1
movlw 0x00
movwf digit2 ; digit2 vide
movwf digit3 ; digit3 vide
movwf digit4 ; digit4 vide
goto FINPARAM

TESTPARAM2
decfsz varparam,f ; décrémenter le pointeur de paramètre
goto TESTPARAM3 ; choixParam != 0 ?
movf parametre2,w ; conversion de parametre2 (chiffres) en digit2 (7 segments)
movwf vardigit
call CONVDIGIT
movwf digit2
movlw 0x00
movwf digit1 ; digit1 vide
movwf digit3 ; digit3 vide
movwf digit4 ; digit4 vide
goto FINPARAM

TESTPARAM3
decfsz varparam,f ; décrémenter le pointeur de paramètre
goto TESTPARAM4 ; choixParam != 0 ?
movf parametre3,w ; conversion de parametre3 (chiffres) en digit3 (7 segments)
movwf vardigit
call CONVDIGIT
movwf digit3
movlw 0x00
movwf digit1 ; digit1 vide
movwf digit2 ; digit2 vide
movwf digit4 ; digit4 vide
goto FINPARAM

TESTPARAM4
decfsz varparam,f ; décrémenter le pointeur de paramètre
goto TESTPARAM0 ; choixParam != 0 ?

movf parametre4,w ; conversion de parametre4 (chiffres) en digit4 (7 segments)


movwf vardigit
call CONVDIGIT
movwf digit4
movlw 0x00
movwf digit1 ; digit1 vide
movwf digit2 ; digit2 vide
movwf digit3 ; digit3 vide

goto FINPARAM

TESTPARAM0

ESME Sudria p.52/72


2003
Une fois toutes les possibilités de paramètres testées, et une fois le paramètre
en cours traité, le programme appelle la routine « CONVPARAM ». Elle effectue
la conversion de la valeur numérique de chaque paramètre en une valeur codée
sur 8 bits (7 segments + 1 virgule). Ensuite, la routine « AFFICHAGE » rafraîchit
les valeurs transmises à l’afficheur LCD.

call CONVPARAM

FINPARAM

CALL AFFICHAGE ; routine d'affichage des paramètres sur l'afficheur LCD


; rafraîchissement de l'afficheur

return ; fin d'interruption TMR1

Fin du traitement des interruptions sur TMR1.

Initialisations :
Initialisation des ports :
Dans cette partie, tous les registres nécessaires à la configuration des ports
sont initialisés avec les valeurs qui leur ont été assignées au début du
programme. Ainsi les entrées et sorties de chaque port sont définies (registres
« TRISA », « TRISB » et « TRISC »). L’entrée analogique est configurée par les
registres « ADCON0 » et « ADCON1 ». Les sorties sont mises à ‘0’ pour éviter
les valeurs aléatoires.

;*************************************************************************
;* INITIALISATIONS *
;*************************************************************************

INIT
; initialisation PORTS (banques 0 et 1)
; -------------------------------------------------
BANK0 ; sélectionner la banque0
clrf PORTA ; Sorties PORTA à 0
clrf PORTB ; Sorties PORTB à 0
clrf PORTC ; Sorties PORTC à 0
movlw ADCON0VAL ; Configuration du mode digital/analogique
movwf ADCON0 ; écriture dans le registre de contrôle A/D
bsf STATUS,RP0 ; sélectionner banque1
movlw ADCON1VAL ; PORTA en mode digital/analogique
movwf ADCON1 ; écriture dans le registre de contrôle A/D
movlw DIRPORTA ; Direction PORTA
movwf TRISA ; écriture dans le registre direction
movlw DIRPORTB ; Direction PORTB
movwf TRISB ; écriture dans le registre direction
movlw DIRPORTC ; Direction PORTC
movwf TRISC ; écriture dans le registre direction

ESME Sudria p.53/72


2003
Initialisation des registres d’interruptions :
Tout comme les registres de configuration des ports, les registres d’interruptions
doivent être initialisés avec les valeurs assignées précédemment. Les registres
« INTCON », « PIE1 » et « T1CON » sont donc initialisés pour permettre les
interruptions sur les entrées « RB4/7 » et sur le « TIMER 1 ».

; initialisation des registres d'interruptions (banque 1)


; ---------------------------------------------------------------------
movlw INTCONVAL ; charger valeur registre interruption
movwf INTCON ; initialiser interruptions
movlw PIE1VAL ; Initialiser registre
movwf PIE1 ; interruptions périphériques 1
bcf STATUS,RP0 ; passer en banque 0
clrf TMR1L ; effacer timer1, 8 lsb
clrf TMR1H ; effacer timer1, 8 msb
movlw T1CONVAL ; charger valeur registre interruption
movwf T1CON ; initialiser interruptions

Initialisation des variables :


Lors de chaque mise en marche du circuit, certaines variables doivent être
impérativement initialisées car si elles sont attribuées de façon aléatoire, elles
peuvent compromettre le bon fonctionnement du programme.

; initialisation variables
; -----------------------------
clrf menu ; initialisation de « menu » pour qu’il pointe vers le menu général
clrf choixParam ; initialisation du de la variable de choix du paramètre à modifier
clrf parametre1 ; initialisation du paramètre n°1 : Kp
clrf parametre2 ; initialisation du paramètre n°2 : Ki
clrf parametre3 ; initialisation du paramètre n°3 : Kd
clrf parametre4 ; initialisation du paramètre n°4 : Limite d'intégration
movlw 0x02
movwf cligno ; initialisation de la variable d'état de clignotement
clrf resultConv ; initialisation de la variable de conversion A/N
clrf resultPID2 ; initialisation de la variable de calcul du PID

goto START ; programme principal

Lorsque les initialisations sont terminées, l’exécution se poursuit dans le


programme principal. Celui-ci centralise l’appel des différentes routines, il
coordonne donc les tâches qui permettront d’obtenir le traitement de
l’asservissement. Chacune de ces tâches doit être définie au préalable.

ESME Sudria p.54/72


2003
Routines :
La programmation du module d’asservissement PID nécessite de nombreuses
opérations. La mise en œuvre d’un tel programme est assez complexe, il doit
donc être découpé en plusieurs modules ayant chacun une tâche différente à
accomplir. C’est le rôle des routines qui permettent entre autres de structurer le
programme.

Conversion analogique-numérique :
Cette routine réalise l’échantillonnage sur une entrée analogique. La conversion
se fait en plusieurs étapes :
- la valeur de l’échantillon précédent est mémorisée (car elle est nécessaire au
calcul du PID),
- le convertisseur est activé par la mise à ‘1’ de « ADON »,
- attente de la fin de l’acquisition (le convertisseur intégré au PIC a un temps
d’acquisition Tacq = 19,7µs),
- la conversion analogique numérique débute lors de la mise à ‘1’ de « GO »,
- attente de la fin de la conversion (le convertisseur intégré au PIC a un temps
de conversion Tad = 3,2µs),
- lecture de la valeur de l’échantillon. Chaque échantillon est stocké sur 10 bits
dans la paire de registres « ADRESH » et « ADRESL ». La justification étant
faite à gauche, et pour des raisons de commodité, on n’exploite que les 8 bits
de poids fort que l’on trouve dans le registre « ADRESH ».

;*****************************************************************
;* CONVERSION Analogique -> Numérique *
;*****************************************************************
;* entrée : *
;* *
;* sortie : resultConv *
;* *
;*****************************************************************

CONV
movf resultConv,w ; Chargement du résultat de la conversion précédente
movwf resultConv2 ; Stockage de l'ancien résultat de la conversion

; 1 - lancement du convertisseur : ADON = 1


; --------------------------------------------------------

bsf ADCON0,ADON

; 2 - attendre que l'acquisition soit effectuée (Tacq = 19.7µs)


; -------------------------------------------------------

movlw 0x07 ; nb de boucles


movwf cmpt1 ; initialiser compteur de boucles
LOOPACQ ; (LOOPACQ = 22µs pour cmpt1=x07 et osc=4MHz)
decfsz cmpt1,f ; décrémenter le compteur de boucles
goto LOOPACQ ; if = 0 -> LOOPACQ

ESME Sudria p.55/72


2003
; 3 - démarrer la conversion en positionnant le bit GO du registre ADCON0
; ------------------------------------------------------------------------------------------------

bsf ADCON0,GO

; 4 - attendre que la conversion soit terminée (2Tad = 3.2µs)


; --------------------------------------------------------

movlw 0x01 ; nb de boucles


movwf cmpt1 ; initialiser compteur de boucles
LOOPAD ; (LOOPAD = 4µs pour cmpt1=x01 et osc=4MHz)
decfsz cmpt1,f ; décrémenter le compteur de boucles
goto LOOPAD ; if = 0 -> LOOPAD
; 5 - Lire le résultat de la conversion dans ADRESH
; ---------------------------------------------------------------
movf ADRESH,w ; Chargement du registre ADRESH
movwf resultConv ; Stockage des 8 bits du résultat de la conversion
return

Addition :
La routine « ADDI » réalise l’addition des chiffres stockés dans les variables
« var1 » et « var2 ». L’addition est effectuée par l’instruction « addwf », mais
l’utilisation de cette routine permet de détecter les dépassements en
interrogeant le registre « STATUS,C ». Le résultat est alors stocké dans deux
octets, « sommeL » contenant les 8 bits de poids faible et « sommeH »
contenant les éventuels dépassements.

;*****************************************************************
;* ADDITION 8 bits *
;* avec gestion du dépassement *
;*****************************************************************
;* entrées : var1 (8 bits) ] variables d'entrée non *
;* var2 (8 bits) ] modifiées par le programme *
;* *
;* sortie : sommeL (8 bits) *
;* sommeH (8 bits pour le dépassement de capacité) *
;* *
;*****************************************************************
;* var1 + var2 -> [sommeL ; sommeH] *
;*****************************************************************

ADDI
clrf sommeH ; effacer dépassement
movf var1,w ; charger la variable n°1 dans w
movwf sommeL ; sauver dans sommeL
movf var2,w ; charger la variable n°2 dans w
addwf sommeL,f ; ajouter w et sommeL puis stocker dans somme
btfsc STATUS,C ; tester si bit de dépassement = 1
incfsz sommeH,f ; oui, ajouter au résultat poids fort

return

ESME Sudria p.56/72


2003
Soustraction :
La routine « SOUSTRAC » soustrait la variable « var2 » à la variable « var1 ».
La soustraction est effectuée par l’instruction « subwf », mais l’utilisation de
cette routine permet de gérer les résultats négatifs qui se traduisent par des
dépassements de capacité que l’on détecte en interrogeant le registre
« STATUS,C ». Dans le cas d’un résultat négatif, il faut calculer le complément
vrai pour obtenir un résultat exploitable. Le résultat est stocké dans l’octet
« diffL », et le bit « signe,0 » reçoit le bit de signe du résultat.

;*****************************************************************
;* SOUSTRACTION 8 bits *
;*****************************************************************
;* entrées : var1 (8 bits) ] variables d'entrée non *
;* var2 (8 bits) ] modifiées par le programme *
;* *
;* sorties : diffL (8 bits) *
;* signe,0 bit de signe du résultat *
;* *
;*****************************************************************
;* var1 - var2 -> (signe) diffL *
;*****************************************************************

SOUSTRAC
bcf signe,0 ; effacer le bit de signe
movf var1,w ; charger la variable n°1 dans w
movwf diffL ; sauver dans diffL
movf var2,w ; charger la variable n°2 dans w
subwf diffL,f ; soustraire w à diffL puis stocker dans diffL
btfss STATUS,C ; tester si bit de dépassement = 0 , le résultat est donc négatif
goto COMP ; si résultat <0 , on cherche le complément à 2
return

COMP bsf signe,0 ; stockage du bit de signe négatif


comf diffL,f ; calcul du complément restreint
incf diffL,f ; calcul du complément vrai (complément à 2)

return

Multiplication :
La routine « MULTI » multiplie « var1 » et « var2 ». Le résultat nécessite donc
16 bits, donc 2 octets « produitH » et « produitL ».
Pour illustrer le principe de fonctionnement, voici la réalisation d’une
multiplication manuelle. Nous multiplions ici 12 par 13, c’est une opération de
4x4 bits avec un résultat sur 8 bits. Ceci afin de simplifier l’explication.
Le tableau suivant montre que pour programmer une multiplication, il suffit de
multiplier les bits un à un en effectuant un décalage à gauche lors du
chargement d’un nouveau bit multiplicateur.

ESME Sudria p.57/72


2003
1 1 0 0 12
X 1 1 0 1 13

1 1 0 0 12
0 0 0 0 0 0
1 1 0 0 0 0 48
1 1 0 0 0 0 0 96

1 0 0 1 1 1 0 0 156

Les résultats intermédiaires sont cumulés dans la variable « produitH »,


au fur et à mesure du traitement. Le calcul d’un produit 8x8 bits comporte
donc 8 étapes intermédiaires qui correspondent au traitement de chaque
bit du multiplicateur.

;*****************************************************************
;* MULTIPLICATION 8 x 8 bits *
;*****************************************************************
;* entrées : var1 (8 bits) ] variables d'entrée non *
;* var2 (8 bits) ] modifiées par le programme *
;* *
;* résultat sur 16 bits : produitH (8 bits de poids fort) *
;* produitL (8 bits de poids faible) *
;* *
;*****************************************************************
;* var1 * var2 -> [produitH ; produitL] *
;*****************************************************************

MULTI
clrf produitH ; effacer le résultat poids fort
clrf produitL ; effacer le résultat poids faible
movlw 0x08 ; pour 8 bits
movwf cmpt1 ; initialiser compteur de boucles
movf var1,w ; charger le multiplicateur n°1 dans w
movwf vartemp ; sauver dans vartemp
movf var2,w ; charger le multiplicateur n°2 dans w
LOOPMULTI
rrf vartemp,f ; décaler le multiplicateur vers la droite
btfsc STATUS,C ; tester si bit sorti = 1
addwf produitH,f ; oui, ajouter au résultat poids fort
rrf produitH,f ; décaler le résultat poids fort
rrf produitL,f ; décaler le résultat poids faible
decfsz cmpt1,f ; décrémenter le compteur de boucles
goto LOOPMULTI ; pas fini, bit suivant

return

ESME Sudria p.58/72


2003
Calcul du PID :
La routine « PID » résout l’équation suivante :
u(k) = Kp e(k) + Ki [ u(k-1) + e(k) ] + Kd [ e(k) - e(k-1) ]
avec : e(k) : résultat de la conversion A/D (variable « resultConv »)
e(k-1) : résultat de la conversion A/D précédente (« resultConv2 »)
u(k-1) : résultat précédent du calcul du PID (« resultPID2 »)

;*****************************************************************
;* Calcul du PID *
;*****************************************************************
;* entrées : resultConv, resultConv2, resultPID2 *
;* parametre1, parametre2, parametre3, parametre4 *
;* signe *
;* *
;* sorties : resultPID *
;* signe, resultPID2, resultConv2 *
;*****************************************************************
;* u(k) = Kp £(k) + Ki [u(k-1)+£(k)] + Kd [£(k)-£(k-1)] *
;*****************************************************************
PID ; resultPID = [ parametre1 + parametre2 + parametre3 ] * resultConv
; + parametre2 * resultPID2 - parametre3 * resultConv2
; -1 < parametre1, parametre2, parametre3 < 10
; signe,1 contient le signe de resultConv centré sur 0 = signe de result1
; signe,2 contient le signe de resultConv2 centré sur 0 = signe de result3
; signe,3 contient le signe de resultPID centré sur 0
; signe,4 contient le signe de resultPID2 centré sur 0 = signe de result2
; signe,5 contient le signe de result4

La valeur des échantillons est codée sur 8 bits (registre « ADRESH »). Cette
valeur correspond à une tension comprise entre –5V et +5V. Il est donc
nécessaire d’étalonner les données avant de commencer à résoudre l’équation.
L’étalonnage est effectué comme nous l’avons précédemment défini dans la
partie « étalonnage des données ». Cela consiste simplement à recentrer les
données sur ‘0’, c’est-à-dire soustraire ‘127’ à la variable d’entrée.

; 1) Recentrer la valeur du signal échantillonné sur 0


; ------------------------------------------------------------------
; -5V < E(k) < +5V => 0 < resultConv < 255
; => -127 < resultConv - 127 < +128
movf resultConv,w ; charger resultConv dans var1
movwf var1
movlw D'127' ; charger '127' dans var2
movwf var2
call SOUSTRAC ; appel de la routine de soustraction
movf diffL,w ; stockage de resultConv recentré sur 0
movwf resultConv
bcf signe,1 ; effacer signe,1
btfsc signe,0 ; stockage du signe du résultat de la soustraction dans signe,1
bsf signe,1
clrf resultDep ; effacer l'octet de traitement des dépassements

ESME Sudria p.59/72


2003
Une fois l’étalonnage effectué, le calcul débute. Celui-ci est scindé en plusieurs
résultats intermédiaires afin de simplifier le traitement des dépassements. En
effet, chaque résultat intermédiaire découle d’une multiplication dont le résultat
occupe jusqu’à 16 bits. Dès qu’il y a un dépassement, on l’ajoute ou on le
soustrait à la variable « resultDep » en fonction du signe du résultat sur lequel
apparaît ce dépassement. Si à la fin du calcul « resultDep » est différent de
zéro, il y a un dépassement et le signal devra être écrêté pour éviter des valeurs
aberrantes.
Le premier résultat intermédiaire correspond à « ( Kp + Ki + Kd ) . e(k) »
Son bit de signe est stocké dans le bit « signe,1 ».

; 2) Calculer : result1 = [ parametre1 + parametre2 + parametre3 ] * resultConv


; -----------------------------------------------------------------------------------------------------
movf parametre1,w ; charger parametre1 dans var1
movwf var1
movf parametre2,w ; charger parametre2 dans var2
movwf var2
call ADDI ; appel de la routine d'addition
movf sommeL,w ; stocker la somme de parametre1 et parametre2 dans var2
movwf var2
movf parametre3,w ; charger parametre3 dans var1
movwf var1
call ADDI ; appel de la routine d'addition
movf sommeL,w ; stocker la somme des parametre1, 2 et 3 dans var2
movwf var2
movf resultConv,w ; charger resultConv dans var1
movwf var1
call MULTI ; appel de la routine de multiplication
movf produitH,w ; stockage de produitH dans resultDep
movwf resultDep
movf produitL,w ; stockage de produitL dans result1
movwf result1 ; le signe de result1 est donné par signe,1

Le second résultat intermédiaire correspond à « Ki . u(k-1) »


Son bit de signe est stocké dans le bit « signe,4 ». S’il présente un
dépassement, « resultDep » est modifié en conséquence.

; 3) Calculer : result2 = parametre2 * resultPID2


; -------------------------------------------------------------
movf resultPID2,w ; charger resultPID2 dans var1
movwf var1
movf parametre2,w ; charger parametre2 dans var2
movwf var2
call MULTI ; appel de la routine de multiplication
btfss produitH,0 ; resultDep est incrémenté si produitH =! 0
goto SKIPDEP1 ; produitH = 0
btfss signe,4 ; prohuitH > 0
incf resultDep,f ; result2 > 0
btfsc signe,4
decf resultDep,f ; result2 =< 0
SKIPDEP1
movf produitL,w ; stockage de produitL dans result2
movwf result2 ; le signe de result2 est donné par signe,4

ESME Sudria p.60/72


2003
Le troisième résultat intermédiaire correspond à « Kd . e(k-1) »
Son bit de signe est stocké dans le bit « signe,2 ». S’il présente un
dépassement, « resultDep » est modifié en conséquence.

; 4) Calculer : result3 = parametre3 * resultConv2


; ----------------------------------------------------------------

movf parametre3,w ; charger parametre3 dans var1


movwf var1
movf resultConv2,w ; charger resultConv2 dans var2
movwf var2
call MULTI ; appel de la routine de multiplication
incf produitH,f
decfsz produitH,f ; tester la valeur de produitH
goto TRAITDEP2 ; prohuitH > 0
goto SKIPDEP2 ; produitH = 0
TRAITDEP2
btfss signe,2
incf resultDep,f ; result3 > 0
btfsc signe,2
decf resultDep,f ; result3 =< 0
SKIPDEP2
movf produitL,w ; stockage de produitL dans result3
movwf result3 ; le signe de result3 est donné par signe,2

Les calculs intermédiaires sont maintenant terminés. Il reste à tester si leur


dépassement cumulé est nul. Dans le cas contraire, il est inutile de poursuivre le
calcul, car le signal doit être écrêté à sa valeur maximale (soit ‘255’) si
« resultDep » est positif, ou à sa valeur minimale (soit ‘0’) s’il est négatif.

incf resultDep,f
decfsz resultDep,f ; tester la valeur de resultDep
goto TRAITDEP3 ; resultDep =! 0
goto SKIPDEP3 ; resultDep = 0
TRAITDEP3
movf resultDep,w ; charger resultDep dans w
btfsc STATUS,Z ; tester si w = 0
goto DEPASSNEG ; resultDep < 0 => on écrète le signal à sa valeur min : 0
; resultDep > 0 => on écrète le signal à sa valeur max : 255
movlw D'255' ; il y a dépassement positif => charger '255' dans w
goto SUITECR4
DEPASSNEG
movlw D'0' ; il y a dépassement négatif => charger '0' dans w
goto SUITECR4
SKIPDEP3

S'il n’y a pas de dépassement, ou si ces dépassements s’annulent, le calcul de


l’équation se poursuit.

ESME Sudria p.61/72


2003
Les deux premiers résultats intermédiaires sont additionnés en tenant compte
de leur signe respectif. Si leurs signes sont différents, alors c’est une
soustraction qu’il faut réaliser.
On obtient un quatrième résultat intermédiaire dont le bit de signe est stocké
dans le bit « signe,5 ».

; 5) Additionner : result4 = result1 + result2


; -------------------------------------------------------

movf result1,w ; charger result1 dans var1


movwf var1
movf result2,w ; charger result2 dans var2
movwf var2
bcf signe,5 ; initialisation du bit de signe de result4
btfss signe,1 ; test sur le signe de result1
goto RCPOSITIF3 ; result1 >= 0
btfss signe,4 ; result1 < 0
goto SIGNDIFF3 ; result2 >= 0 et result1 < 0
bsf signe,5 ; result4 est négatif
goto SIGNEQU3 ; result2 < 0 et result1 < 0
RCPOSITIF3
btfsc signe,4 ; result1 >= 0
goto SIGNDIFF3 ; result2 < 0 et result1 >= 0
SIGNEQU3 ; result2 >= 0 et result1 >= 0
call ADDI ; appel de la routine d'addition
movf sommeL,w
goto SUITECR3
SIGNDIFF3
btfss signe,1 ; test sur le signe de result1
goto SKIPINV3 ; result1 > 0 et result2 < 0
movf result2,w ; result1 < 0 et result2 > 0
movwf var1 ; permuter result1 et result2 avant de les soustraire
movf result1,w
movwf var2
SKIPINV3
call SOUSTRAC ; appel de la routine de soustraction
movf diffL,w
btfsc signe,0 ; test du signe du résultat de la soustraction
bsf signe,5 ; result4 est négatif
SUITECR3
movwf result4 ; le signe de result4 est donné par signe,5

Pour terminer le calcul, il reste à soustraire les deux derniers résultats


intermédiaires en tenant toujours compte de leur signe. Si leurs signes sont
différents c’est une addition qu’il faut réaliser.

ESME Sudria p.62/72


2003
On obtient le résultat final « resultPID » dont le bit de signe est stocké dans le
bit « signe,3 ».

; 6) Soustraire : resultPID = result4 - result3


; -------------------------------------------------------

movf result4,w ; charger result4 dans var1


movwf var1
movf result3,w ; charger result3 dans var2
movwf var2
bcf signe,3 ; initialisation du bit de signe de resultPID
btfss signe,5 ; test sur le signe de result4
goto RCPOSITIF4 ; result4 >= 0
btfss signe,2 ; result4 < 0
goto SIGNDIFF4 ; result3 >= 0 et result4 < 0
goto SIGNEQU4 ; result3 < 0 et result4 < 0
RCPOSITIF4
btfss signe,2 ; result4 >= 0
goto SIGNEQU4 ; result3 >= 0 et result4 >= 0
SIGNDIFF4 ; result3 < 0 et result4 >= 0
btfsc signe,5 ; test sur le signe de result4 => resultPID est du signe de result4
bsf signe,3 ; resultPID est négatif
call ADDI ; appel de la routine d'addition
movf sommeL,w
goto SUITECR4
SIGNEQU4
btfss signe,5 ; test du signe de result4
goto SKIPINV4 ; result4 > 0 et result3 > 0
movf result3,w ; result4 < 0 et result3 < 0
movwf var1 ; permuter result3 et result4 avant de les soustraire
movf result4,w
movwf var2
SKIPINV4
call SOUSTRAC ; appel de la routine de soustraction
movf diffL,w
btfsc signe,0 ; test du signe du résultat de la soustraction
bsf signe,3 ; resultPID est négatif
SUITECR4
movwf resultPID ; le signe de resultPID est donné par signe,3

Le calcul du PID est maintenant réalisé, cependant cette valeur doit être
décentrée conformément au formatage des données défini précédemment.

ESME Sudria p.63/72


2003
En effet, « resultPID » doit être compris entre ‘0’ et ‘255’ pour pouvoir être
injecté sur le PORTC. Il suffit donc d’ajouter ‘127’ à « resultPID ». Dans le cas
où la valeur de « resultPID » centrée sur ‘0’ est négative, il faut soustraire
« resultPID » à ‘127’.

; 7) Décentrer la valeur du signal corrigé pour qu'il soit compris entre 0 et 255
; ---------------------------------------------------------------------------------------------------
; -127 < resultPID < +128 => 0 < resultPID + 127 < 255
; => -5V < E(k) < +5V

movf resultConv,w ; mémoriser le résultat de la conversion centré sur 0


movwf resultConv2
bcf signe,2
btfsc signe,1 ; mémoriser le signe du résultat de la conversion centré sur 0 dans signe,2
bsf signe,2
movlw D'127' ; charger '127' dans var1
movwf var1
movf resultPID,w ; charger resultPID dans var2
movwf var2
movwf resultPID2 ; mémoriser le résultat du calcul du PID centré sur 0
btfsc signe,3 ; mémoriser le signe du résultat du calcul du PID centré sur 0 dans signe,4
goto SOUSPID
bcf signe,4 ; resultPID centré sur 0 est positif
call ADDI ; appel de la routine d'addition
movf sommeL,w
goto FINPID
SOUSPID
bsf signe,4 ; resultPID centré sur 0 est négatif
call SOUSTRAC ; appel de la routine de soustraction
movf diffL,w
FINPID
movwf resultPID ; stockage de resultPID compris entre 0 et 255

return

ESME Sudria p.64/72


2003
Conversion de chiffres en digits :
La routine « CONVDIGIT » réalise la conversion de la variable « vardigit » en un
code 8 bits. Ce code représente l’affichage sur sept segments du chiffre
contenu dans « vardigit ».
Cette routine permet donc d’obtenir la représentation sur sept segments (plus
une virgule) d’une valeur comprise entre ‘0’ et ‘9’. Dans le cas d’une valeur
erronée qui ne se trouverait pas dans cet encadrement, la routine retourne le
code d’un digit représentant un trait « – ».
Ainsi, si l’on visualise un trait sur l’un des digits de l’afficheur LCD, cela indique
une erreur.

;*****************************************************************
;* CONVERSION Chiffres -> Digits *
;*****************************************************************
;* entrée : vardigit *
;* *
;* sortie : w *
;*****************************************************************

CONVDIGIT
btfss STATUS,Z ; tester si W = 0
goto DIGITUN
movlw ZERO
goto FINCONV

DIGITUN
decfsz vardigit,f ; décrémenter le chiffre à traiter
goto DIGITDEUX
movlw UN ; var1 = 0 ?
goto FINCONV

DIGITDEUX
decfsz vardigit,f ; décrémenter le chiffre à traiter
goto DIGITTROIS
movlw DEUX ; var1 = 0 ?
goto FINCONV

DIGITTROIS
decfsz vardigit,f ; décrémenter le chiffre à traiter
goto DIGITQUATRE
movlw TROIS ; var1 = 0 ?
goto FINCONV

DIGITQUATRE
decfsz vardigit,f ; décrémenter le chiffre à traiter
goto DIGITCINQ
movlw QUATRE ; var1 = 0 ?
goto FINCONV

DIGITCINQ
decfsz vardigit,f ; décrémenter le chiffre à traiter
goto DIGITSIX
movlw CINQ ; var1 = 0 ?
goto FINCONV

ESME Sudria p.65/72


2003
DIGITSIX
decfsz vardigit,f ; décrémenter le chiffre à traiter
goto DIGITSEPT
movlw SIX ; var1 = 0 ?
goto FINCONV

DIGITSEPT
decfsz vardigit,f ; décrémenter le chiffre à traiter
goto DIGITHUIT
movlw SEPT ; var1 = 0 ?
goto FINCONV

DIGITHUIT
decfsz vardigit,f ; décrémenter le chiffre à traiter
goto DIGITNEUF
movlw HUIT ; var1 = 0 ?
goto FINCONV

DIGITNEUF
decfsz vardigit,f ; décrémenter le chiffre à traiter
goto DIGITERROR
movlw NEUF ; var1 = 0 ?
goto FINCONV

DIGITERROR
movlw TRAIT

FINCONV

return

ESME Sudria p.66/72


2003
Conversion des paramètres en digits :
La routine « CONVPARAM » réalise la conversion de l’ensemble des quatre
paramètres que l’on doit visualiser sur l’afficheur.
Cette routine fait appel à la précédente pour réactualiser la valeur de chaque
paramètre à sur l’écran LCD.

;*****************************************************************
;* CONVERSION des paramètres en digits *
;*****************************************************************
;* entrées : parametre1, parametre2, parametre3, parametre4 *
;* *
;* sorties : digit1, digit2, digit3, digit4 *
;* *
;*****************************************************************

CONVPARAM

movf parametre1,w ; conversion de parametre1 (chiffres) en digit1 (7 segments)


movwf vardigit
call CONVDIGIT
movwf digit1

movf parametre2,w ; conversion de parametre2 (chiffres) en digit2 (7 segments)


movwf vardigit
call CONVDIGIT
movwf digit2

movf parametre3,w ; conversion de parametre3 (chiffres) en digit3 (7 segments)


movwf vardigit
call CONVDIGIT
movwf digit3

movf parametre4,w ; conversion de parametre4 (chiffres) en digit4 (7 segments)


movwf vardigit
call CONVDIGIT
movwf digit4

return

ESME Sudria p.67/72


2003
Affichage des paramètres par une transmission “série” :
La routine « AFFICHAGE » génère deux signaux synchronisés qui permettent
d’établir un transfert de données série du PIC vers le contrôleur LCD.
Un signal « Data » est émis sur la pin « RB1 » du PORTB et le signal d’horloge
correspondant est disponible sur la pin « RB0 ».
Pour mettre à jour l’afficheur, le driver LCD doit recevoir un paquet de 36 bits
synchronisé par un signal d’horloge.

Les 36 bits envoyés sont organisés de la façon suivante :


- le début de l’envoi est signalé par un bit de « start » (les instructions « nop »
n’influencent pas le programme, elles ont pour seul but de créer un retard pour
permettre le temps d’établissement des signaux)

;*****************************************************************
;* AFFICHAGE (transmission série des données) *
;*****************************************************************
;* entrées : digit1, digit2, digit3, digit4 *
;* *
;* sortie : *
;* *
;*****************************************************************

AFFICHAGE

bcf PORTB,1 ; Mise à 0 du signal DATA


nop
bsf PORTB,0 ; Mise à 1 du signal CLOCK
nop
bcf PORTB,0 ; Mise à 0 du signal CLOCK
nop
bsf PORTB,1 ; Mise à 1 du signal DATA
nop
bsf PORTB,0 ; Mise à 1 du signal CLOCK

- les 4 octets correspondant au code des quatre digits (variables « digit1 » à


« digit4 ») sont envoyés les uns après les autres. La transmission se fait du bit
le moins significatif au bit le plus significatif.

movf digit4,w ; charger le 1er octet à envoyer


call AFFDIGIT ; Appel de la routine de transmission d'un mot de 8 bits
movf digit3,w ; charger le 2ème octet à envoyer
call AFFDIGIT ; Appel de la routine de transmission d'un mot de 8 bits
movf digit2,w ; charger le 3ème octet à envoyer
call AFFDIGIT ; Appel de la routine de transmission d'un mot de 8 bits
movf digit1,w ; charger le 4ème octet à envoyer
call AFFDIGIT ; Appel de la routine de transmission d'un mot de 8 bits

ESME Sudria p.68/72


2003
- il faut transférer un paquet de 36 bits pour que le driver puisse exploiter ce
signal. Jusqu’ici, nous avons envoyé un bit de « start » et quatre octets, soit 33
bits. Il faut donc ajouter deux bits vides et un bit de « fin » pour terminer la
transmission.

movlw B'00000100' ; charger les bits permettants de compléter la série de 36 bits transmis
movwf vartemp ; stocker l'octet à transmettre dans vartemp
movlw 0x03 ; 3 boucles pour transmettre les 3 bits manquants
movwf cmpt1 ; initialiser compteur de boucles
LOOPAFF2
rrf vartemp,f ; décaler vers la droite
bcf PORTB,0 ; Mise à 0 du signal CLOCK
btfsc STATUS,C ; tester le bit de dépassement C
bsf PORTB,1 ; C=1 -> Mise à 1 du signal DATA
btfss STATUS,C ; tester le bit de dépassement C
bcf PORTB,1 ; C=0 -> Mise à 0 du signal DATA
nop
bsf PORTB,0 ; Mise à 1 du signal CLOCK

decfsz cmpt1,f ; décrémenter le compteur de boucles


goto LOOPAFF2 ; si = 0 -> LOOPAFF2

bcf PORTB,1 ; Mise à 0 du signal DATA


bcf PORTB,0 ; Mise à 0 du signal CLOCK

return

Transmission “série” d’un octet :


La sous-routine « AFFDIGIT » est intégrée dans la routine « AFFICHAGE ».
Elle génère un signal « Data » et un signal d’horloge synchronisés permettant
de transmettre un octet.

AFFDIGIT
movwf vartemp ; stocker l'octet à transmettre dans vartemp

movlw 0x08 ; 8 boucles pour afficher un octet (1 mot de 8 bits)


movwf cmpt1 ; initialiser compteur de boucles
LOOPAFF1
rrf vartemp,f ; décaler vers la droite
bcf PORTB,0 ; Mise à 0 du signal CLOCK
btfsc STATUS,C ; tester le bit de dépassement C
bsf PORTB,1 ; C=1 -> Mise à 1 du signal DATA
btfss STATUS,C ; tester le bit de dépassement C
bcf PORTB,1 ; C=0 -> Mise à 0 du signal DATA
nop
bsf PORTB,0 ; Mise à 1 du signal CLOCK

decfsz cmpt1,f ; décrémenter le compteur de boucles


goto LOOPAFF1 ; si = 0 -> LOOPAFF1

return

ESME Sudria p.69/72


2003
Programme principal :
Le programme principal centralise les appels des différentes routines qu’il est
nécessaire d’exécuter pour réaliser l’asservissement.

Lors du démarrage, le programme commence par une phase d’initialisation de


l’afficheur et du convertisseur analogique-numérique :
- les paramètres sont convertis et codés sur sept segments,
- la valeur de chaque digit est transmise au contrôleur LCD via une liaison
série,
- une première acquisition et une conversion du signal d’entrée analogique
sont effectuées (il est indispensable de donner une valeur à « e(k-1) » avant
de commencer le calcul du PID).

Ensuite, une boucle infinie effectue en permanence la correction voulue et la


restitue sur le PORTC. Cette correction se fait en plusieurs étapes :
- acquisition et conversion analogique – numérique d’un échantillon,
- calcul du PID,
- stockage du résultat sur le PORTC.

;*********************************************************************************
;* PROGRAMME PRINCIPAL *
;*********************************************************************************

START
org 0x300

CALL CONVPARAM ; routine de conversion des paramètres (chiffres) en digits (7segments)

CALL AFFICHAGE ; routine d'affichage des paramètres sur l'afficheur LCD (initialisation)

CALL CONV ; routine d'acquisition et de conversion du signal d'entrée analogique


; (une première acquisition est nécessaire
; avant de pouvoir calculer le PID)
LOOP
CALL CONV ; routine d'acquisition et de conversion du signal d'entrée analogique

CALL PID ; routine de calcul du PID

movf resultPID,w ; Chargement du résultat du calcul du PID

movwf PORTC ; Ecriture sur le PORTC des 8 bits du résultat du calcul du PID

goto LOOP

end

ESME Sudria p.70/72


2003
D – SYNTHÈSE

Au cours de cette étude les différentes parties qui composent un module


d’asservissement P.I.D. d’une MCC ont été étudiées. À savoir :

- La programmation du P.I.D.
- Les conversions analogique-numérique et numérique-analogique.
- Les adaptateurs de tensions.
- La gestion des boutons-poussoirs.
- L’affichage, sur un écran LCD à 4 digits, des paramètres de correction du
P.I.D. par l’intermédiaire d’un driver LCD.

Nous pouvons qualifier ce projet de pluridisciplinaire. En effet, nous avons


travaillé dans différents domaines tels que : l’électronique analogique,
l’électronique numérique, l’automatique et l’informatique pour la programmation
du P.I.D.

En dehors de l’aspect technique, ce projet nous a permis de nous rendre


compte de l’importance de la gestion du temps et de la répartition des tâches au
sein du groupe.

Améliorations envisagées

Nous envisageons une amélioration de ce module en y ajoutant :


- Un filtre en sortie du CNA pour obtenir un signal de sortie plus stable.
- La gestion de la limite d’intégration.

ESME Sudria p.71/72


2003
E – SOURCES

- Datasheets des composants suivants :


16F876 (PIC)
TL084 (AOP)
AD557 (CNA)
MM5452 (driver LCD)
VI502 (afficheur LCD)

- Projet de première année : enregistreur numérique (par BRUYERE Philippe


GOMBERT Benjamin
VENCE Eric)

- Programmation 16f876 par Bigonoff

- www.abcelectronique.com
- kudelsko.free.fr
- fribotte.free.fr/bdtech/PidSurPic/PidSurPic1.html
- perso.wanadoo.fr/yves.heilig/ElecRob/page1.htm

REMERCIEMENTS

Nous tenons à remercier M. Touseau et M. Aït Abderrahim pour leur aide, leurs
conseils, leur disponibilité et l’encadrement qu’ils nous ont accordé tout au long
de ce projet.

Nous remercions également Mr Deleau pour son soutien logistique.

ESME Sudria p.72/72


2003

Vous aimerez peut-être aussi