5e application : Pictrain4

Le programme

13.1Conversion Analogique / Digital
13.2Le programme
13.3Mise en oeuvre
Pictrain4 : le programme
13.1. Conversion analogique-numérique *
* Les censeurs de la langue française nous le disent : C.A.N. en français (conversion analogique-numérique) traduit le A.D.C. (analog digital conversion) américain.
La seule nouveauté de ce montage est l´utilisation du convertisseur A/N, dont il faut avoir en tête les principes pour la compréhension du programme.
Je ne vais pas donner la théorie de ces convertisseurs, ni même rentrer dans le détail de la fonction dans les PIC. Je me contenterai du strict nécessaire ; pour plus de détails, vous pouvez consulter comme d´habitude notre maître Bigonoff.

Est-il besoin de le rappeler à nos lecteurs, la page de BIGONOFF, le pape aux PIC, c'est là.
13.1.1. Principe général
Le but de la conversion est de transformer la valeur d´un potentiel (tension, en volt) présent sur une patte d´un PIC en une valeur numérique exploitable dans le programme.
Si on considère que le potentiel sur la patte du PIC peut varier entre 0 et 5 volts, un potentiel de 2 V donnera dans un registre une valeur numérique de 102 (soit 2/5 de 256), un potentiel de 4 V la valeur de 205 (soit 4/5).
Le principe de la conversion est de charger un condensateur et de mesurer ensuite la valeur de cette charge. La conversion s´effectue donc en deux étapes :
a) Charge : un condensateur est relié à l´entrée, et se charge proportionnellement au potentiel de cette entrée ;
b) Mesure : au moment de la mesure, le condensateur est coupé de l´entrée et est connecté à un système de mesure qui mesure par approximations successives la charge du condensateur.
On transforme donc une valeur de potentiel, valeur analogique qu´un microprocesseur ne sait pas traiter, en une durée (nombre digital ou numérique), qu´un microprocesseur sait maintenant traiter. [N.D.L.R. En France, l'abréviation de milliseconde est ms ; l'abréviation de microseconde est µs ou, sur Internet, us].
Bien que de faible capacité (120 pF pour le 12F675), la charge et la décharge du condensateur prennent un certain temps, temps d´un ordre de grandeur différent des temps d´exécution du programme. Pour notre PIC, la durée totale est de l´ordre de 42 us (charge 20 us, mesure 22 us). Heureusement, cette valeur n´est critique que si l´on veut obtenir un grand débit des mesures, par exemple dans l´échantillonnage d´un signal.
Le résultat est donné sur 10 bits, mais nous n´utiliserons que les 8 bits de gauche (les plus significatifs).
Dans notre application, il suffira de prendre en compte ces délais, et finalement notre seule contrainte sera de ne pas vouloir faire une mesure si le condensateur n´est pas encore chargé.
FAQ   La conversion AD dans les PIC— Tout cela est bien entendu bien plus complexe que ce que je présente ici. On peut jouer sur beaucoup de paramètres, la précision de la mesure, la vitesse de conversion… Les registres de commande la fonction sont ADCON0, ANSEL, ADRESH et ADRESL.
On peut aussi définir la plage de tension de la mesure (ici j´utilise les tensions d´alimentation du PIC). Bref, l´application que j´en donne ici est standard, “bateau” on pourrait presque dire, mais elle s´applique dans la plupart des cas courants.
Pour ceux que cela intéresserait particulièrement, Bigonoff donne dans son cours (partie 2, sur les 16F67x) une description complète et très précise de ce dispositif, et bien entendu il faut aussi lire le datasheet du PIC  675.
13.1.2. La conversion A/N du 12F675
Rappel : il est impératif d´utiliser ici un 12F675 et non un 12F629, qui ne comporte pas cette fonction. C´est d´ailleurs la seule différence entre ces deux PIC.
Quatre entrées peuvent être utilisées comme entrée du convertisseur (GPIO 0, 1, 2 et 4), mais il n´y a qu´un seul convertisseur. En fonction des besoins, on sélectionne l´entrée à mesurer.
On peut donc avoir plusieurs sources de courant à mesurer, mais bien entendu pas en même temps, à cause du problème des délais. Si on effectue une mesure sur une des pattes, il faut attendre les délais donnés ci-dessus avant de changer de patte et de refaire une mesure.
Divers bits des registres spécialisés permettent la commande de la conversion. La connexion d´une patte au convertisseur déclenche la charge du condensateur (durée minimum 20 us) ; un bit commande le lancement de la mesure (durée minimum 22 us). À la fin de la mesure, le système se reconnecte à l´entrée, mais il faut bien entendu de nouveau 20 us pour recharger le condensateur.
Comme d´habitude dans les PIC, un bit permet de savoir lorsque l´opération est terminée, mais comme d´habitude je ne m´en sers pas, je trouve plus simple d´attendre un certain temps pour être certain que l´opération soit terminée.
FAQ   Les bits à connaître — Dans le cas standard que nous utilisons ici, il y a peu de bits de commande de la fonction à connaître :
ADCON0 — A/D CONTROL REGISTER (adresse : 1Fh) :
bits 2 et 3 : sélection de l´entrée (lancement de la charge),
bit 1 : lancement de la mesure.
ANSEL — ANALOG SELECT REGISTER (adresse : 9Fh) :
bits 4 à 6  : vitesse de conversion, valeur 001 dans notre cas,
bits 0 à 3 : déclaration des entrées en analogique.
Le résultat de la mesure (les 8 bits les plus significatifs) est dans ADRESH, les poids faibles sont dans ADRESL, mais ne sont pas utilisés ici.
13.1.3. Application dans notre programme
Notre programme n´utilise que des traitements dans l´interruption Timer0, paramétrée sur 10 ms, selon le processus suivant :
1) début du programme : après initialisation des registres, la patte 0 (servo 1) est mise en charge ;
Les étapes suivantes sont liées à l´interruption Timer0 :
2) interruption A :
a. Etape A1 : lancement de la lecture, pendant le temps d´émission du signal minimum sur le servo 1 (± 600 us) ; à la fin, le résultat est disponible ;
b. Etape A2 : suite du signal proportionnellement à la valeur lue sur le potentiomètre ; à la fin, basculement sur l´autre entrée AD (servo 2) pour lancer la charge.
3) interruption B :
a. Etape B1 : lancement de la lecture, pendant le temps d´émission du signal minimum sur le servo 2 ;
b. Etape B2 : suite du signal proportionnellement à la valeur lue sur le potentiomètre ; à la fin, basculement sur l´autre entrée AD (servo 1) pour lancer la charge.
Les deux interruptions A et B se succèdent à intervalle de 10 ms, soit à un intervalle de 20 ms par servo.
Détail des interruptions :
ximage5.png
Dans ce schéma, à chaque interruption on lit la valeur d´un servo, valeur qui sera utilisée pour émettre le signal de débattement (proportionnel) ; à la fin, on branche le convertisseur sur la deuxième entrée, entrée qui sera lue à la prochaine interruption.
On s´affranchit ainsi des contraintes de temps de la conversion, les durées étant toujours beaucoup plus grandes que les délais de charge ou de lecture du convertisseur.
14.2. Le programme
Le programme n´est pas très complexe. Il comprend juste une interruption par le Timer0, programmée sur 10 ms environ. À chaque interruption, le programme transforme la valeur donnée par le potentiomètre en une largeur d´impulsion de commande.
Pourquoi 10 ms ? Comme j´ai deux servomoteurs, je traite alternativement le servo 1 et le servo 2, ce qui me donne une durée entre impulsions de 20 ms par servo — C.Q.F.D..
Je ne vais pas revenir sur les instructions ou les structures de programmes, il n´y a rien de neuf, prière de vous reporter aux présentations Pictrain précédentes. Je ne m´attarderai que sur le principe de la conversion numérique-analogique.
13.2.1. Initialisations
Je rappelle que j´ai l´habitude de mettre dans un fichier séparé tout ce qui est “standard” dans nos programmes, c'est-à-dire les initialisations standard du PIC ainsi que le traitement des interruptions. Ce paquet d´instructions ne ferait qu´“encombrer” notre programme, et ne présente aucun intérêt.
Ce fichier est appelé par la pseudo-instruction #include  ; Paramétrage standard qui ne fait qu´insérer le contenu à cet endroit. Bien entendu, le fichier Param_Std_12F.inc doit être disponible, c'est-à-dire être dans le même répertoire que le projet, ou mieux, dans les fichiers standards de MPLAB.
Dans les paramètres spécifiques à ce programme, on retrouve : b
a) les paramètres du Timer0
xlisting1201.png
Le prédiviseur permet d´obtenir une fréquence de 100 Hz (période de 10 ms).
b) les entrées-sorties :
xlisting1202.png
Les E/S 0 et 1 sont en entrée (pour la conversion A/N), 4 et 5 en sortie pour la commande des servomoteurs. Les E/S 2 et 3 sont en entrée “en l´air”, mais avec résistance de rappel. b*
c) initialisation A/N :
xlisting1203.png
Je déclare les E/S 0 et 1 comme étant des entrées analogiques, et j´active le convertisseur. Le bit ANSEL,4 détermine la vitesse de mesure (voir la documentation précitée si vous voulez des détails — elle est fonction de la vitesse de processeur et de la précision de la mesure).
13.2.2. Boucle principale
N´est pas utilisée ici, elle tourne donc à vide :
xlisting1204.png
De même, l´interruption Timer1 n´est pas utilisée, mais de par la construction de mes programmes, elle doit être présente :
xlisting1205.png
13.2.3. S/P Interruption Timer0
a) Choix du servo à traiter
xlisting1206.png
L´indicateur IN_SERVO_EC sert à déterminer quel est le servomoteur à traiter (alternativement sero1 et servo2), et donc quelle branche du sous-programme on va exécuter.
b) Traitement servo 1
xlisting1207.png
REGLAGE_minimum1 est un paramètre qui conditionne le temps minimum du signal de commande, REGLAGE_cran1 est le paramètre qui conditionne la durée supplémentaire du signal. Si cela vous semble nébuleux, relisez la partie théorique sur les servomoteurs.
xlisting1208.png
Ici est émis le signal de commande sur GPIO,4, la durée est calculée dans le sous-programme SP_signal (voir plus loin).
xlisting1209.png
À la fin du traitement, on lance le chargement du condensateur sur l´autre entrée, et on positionne l´indicateur pour traiter l´autre servomoteur au prochain passage.
c) Traitement servo
xlisting1210.png
Le traitement est identique, seuls les paramètres changent (REGLAGE_minimum2 et REGLAGE_cran2) ainsi que la sortie de commande de servo (ici GPIO,5) et à la fin on repasse sur la première entrée analogique.
d) Sous-programme émission commande servomoteur
Dans ce sous-programme, on exécute les traitements suivants :
lancement de la lecture du convertisseur A/N,
temporisation “minimum” de la commande du servo, fonction du paramètre VA_cpt_Sec,
à la fin de cette première temporisation, la valeur du convertisseur est disponible, et on exécute la deuxième temporisation correspondant au débattement.
Lancement lecture :
xlisting1211.png
Boucle de temporisation “minimum” :
xlisting1212.png
Pas d´observation particulière, votre connaissance des PIC doit vous permettre de comprendre.
Chargement et ajustement de la valeur lue par le convertisseur AD :
xlisting1213.png
La valeur lue dans le registre ADRESH est “shiftée” deux fois vers la droite, c'est-à-dire qu´elle est divisée par 4. Elle prend donc une valeur entre 0 et 64 (256/4), ce qui facilitera le calcul de la deuxième temporisation ci-dessous.
Deuxième temporisation :
xlisting1214.png
La deuxième temporisation est donnée par deux boucles :
boucle externe, basée sur la valeur lue dans le convertisseur A/N, qui exécute à chaque passage une
boucle interne, basée sur un paramètre spécifique au servomoteur.
Ces deux boucles imbriquées permettent donc une durée de signal proportionnelle à la valeur lue par le convertisseur A/N, tout en conservant une possibilité de réglage selon les caractéristiques du servomoteur utilisé, en jouant sur le paramètre CRAN.
13.3. Mise en œuvre
Suite à la variabilité des servomoteurs, j´ai donc introduit dans ce montage des variables de réglage, définies en début de programme :
xlisting1215.png
REGLAGE_frequence : permet de faire varier la fréquence du Timer0, et donc de modifier si besoin est le délai entre deux impulsions de commande au servomoteur. La valeur indiquée donne un délai de 19,6 ms.
Pour chaque servomoteur, deux paramètres sont nécessaires :
REGLAGE_minimum1 : ce paramètre conditionne la durée minimum du signal de commande, c'est-à-dire le positionnement d´un côté du servomoteur,
REGLAGE_cran1 : cette valeur conditionne la durée maximum du signal de commande du servomoteur, c'est-à-dire la position extrême de l´autre côté.
Ces réglages permettent un fonctionnement correct du servomoteur : en effet, si vous émettez une commande trop courte ou trop longue, le servomoteur va “buter” en fin de course, c'est-à-dire qu´il va essayer de continuer après la butée.
Cela entraînera un fonctionnement permanent du servo, donc consommation de courant (> 200 mA), et je suppose qu´il ne va pas aimer.
Si vous voulez utiliser toute l´amplitude du déplacement du servo (+/- 200° dans mon cas), ces deux variables doivent donc être réglées finement pour arriver jusqu´au bout de chaque côté, mais pas trop pour ne pas “brouter” (en général, cela s´entend à l´oreille, sinon un ampèremètre vous l´indiquera).
Ces réglages vous permettent aussi de limiter l´amplitude du mouvement du servomoteur. Vous pouvez ainsi régler les déplacements à gauche et à droite, en fonction de votre utilisation, et par exemple n´utiliser qu´un débattement de 90°.
ATTENTION : comme la position maximum est la somme du minimum plus l´amplitude, il faut toujours régler le minimum en premier (REGLAGE_minimum) et seulement ensuite le maximum (REGLAGE_cran).
Enfin, comme les servomoteurs sont souvent un peu différents, ces réglages sont prévus indépendamment pour chaque sortie.
FAQ  “Rustine” — En termes plus officiels, une rustine s´appelle, en informatique, une solution de contournement. Il s´agit, s´il survient un problème (un bug) pour lequel on n´a pas de solution “correcte”, de trouver rapidement une astuce qui permette de contourner le problème.
Généralement, on n´a pas le temps (il faut que cela tourne), ou pas l´envie de creuser trop profondément (c´est mon cas ici).
Bref, en créant le montage, je suis tombé sur un bug : lorsque je mets le potentiomètre tout à fait du côté du “moins”, et donc la valeur en entrée du convertisseur est 0V (masse), le convertisseur me donnait une valeur numérique aberrante (proche du maximum).
Pour contourner le problème, j´ai ajouté entre le potentiomètre et la masse une petite résistance (100 à 200 ohms), ce qui fait que l´entrée n´est jamais reliée directement à la masse. Je ne sais si cela provient de mon montage, du potentiomètre, du PIC lui-même, et j´ai pas cherché à le savoir. Le montage fonctionne, c´est tout ce qu´on lui demande.

Psi
Octobre
2008


N.B. — Textes, schémas, programmes © Psi pour Ptitrain. Photos Jidé ou D.R. quand signalé. — Toutes vos remarques et commentaires sont bienvenus, et les pages de Ptitrain ne sont pas statiques : les erreurs sont corrigées sitôt connues, les améliorations, éclaircissements, etc. feront l´objet de mises à jour fréquentes.
Ptitrain, l´e-magazine du train éclectique. — Directeur de la publication : Christophe Franchini.
Rédacteur en chef : Jean-Denis Rondinet — Rev. 14.10.2008