Ensuite,
on active les interruptions en mettant à les
bits du registre de contrôle des interruptions INTCON :
  GIE :
activations des interruptions d´une manière générale,
  T0IE :
activation Timer0.
Toutes les autres interruptions
sont désactivées (les autres bits de INTCON sont à ).
ATTENTION :
tous ces registres sont dans BANK1.
 |
10.2.
Traitement des commandes |
Dans la boucle principale
nous allons traiter toutes les commandes, accélération et
freinage, l´arrêt d´urgence et le changement de sens.
Rappel des principes :
  D´une
manière automatique et indépendante, l´interruption Timer0 génère
le signal rectangulaire, de fréquence 240 Hz, de rapport cyclique
variable proportionnel à la variable VA_Vitesse ;
  Les
commandes, gérées dans notre boucle principale, ne font que
modifier la valeur de cette variable VA_Vitesse ;
  Une
inertie est prévue, dans le cas d´un appui continu sur un bouton
la modification de la vitesse est effectuée tous les 1/6 de seconde ;
  Le
changement de sens ne peut être fait que si la vitesse est zéro
(VA_Vitesse = ) ;
une led indique quand cette condition est réalisée.
 |
10.3.
Inertie |
Pour introduire de l´inertie (et également
pour faire fonction d´anti-rebond), nous avons une première boucle
qui fait que le traitement des commandes ne s´exécute que tous les
1/6 de seconde (0,15 seconde).
On verra plus loin que
nous avons 42 “crans” de vitesse,
passer de zéro à vitesse maximum (ou l´inverse), le balayage
complet s´effectuera donc en 7 secondes.
Tant que le compteur VA_Compteur_Inertie est
supérieur à ,
on tourne dans la boucle BouclePrincipale ;
au moment où le compteur passe par zéro, on saute à la
suite du programme. Ce compteur est décrémenté à passage
au créneau haut dans l´interruption Timer0,
soit à la fréquence de 240 Hz, ce qui veut dire que
si on le “charge” avec la valeur 40, il passe par zéro
tous les 240/40 secondes, soit 0,15 seconde.
Indicateur
d´état Z : pour tester la valeur du compteur, nous
utilisons “l´indicateur d´état Z”. Ce n´est pas Z comme
Zorro, mais évidemment Z comme zéro. Cet indicateur est le
bit Z dans le registre spécial STATUS.
Cet indicateur est à lorsque
le résultat d´une instruction est zéro, comme par exemple
la soustraction : si nous avons le chiffre 1 dans un registre
général, et que soustrayons le chiffre , le résultat
est zéro, mais surtout l´indicateur STATUS,Z est à pour
nous indiquer que le résultat (donc le contenu du registre) est
zéro.
Cet indicateur est utilisé dans
beaucoup d´instructions comme les additions ou soustractions, les décréments
ou incréments, les opérations logiques et dans certains move.
Dans notre cas, il s´agit
de l´instruction movf, qui copie le
contenu du registre donné en opérande soit dans W (avec ,W),
soit dans le même registre (avec ,F comme
ici). Si vous avez tout compris, vous vous rendez compte que l´instruction movf
VA_Compteur_Inertie,F ne fait rien, car elle copie le contenu du
registre dans le même registre, ce qui semble assez inutile !
Détrompez-vous, c´est la meilleure manière que nous avons
de tester si le registre est à ,
ce qui nous intéresse ici. Lorsque le registre
est à ,
c´est-à-dire que nous allons exécuter le traitement des commandes,
nous remettons d´abord 40 dans ce registre.
 |
10.4.
Freinage et accélération |
Nous sommes passés
dans le traitement des commandes (boutons) proprement dit.
Il y a ici trois actions
possibles :
  Accélérer :
augmenter la vitesse d´un cran,
  Freiner :
diminuer la vitesse d´un cran,
  Stop :
mettre la vitesse à zéro.
La vitesse est proportionnelle à la
valeur VA_Vitesse (revoir le chapitre
sur le Timer0), est peut varier de 0 à 255.
D´une manière pratique, pour augmenter ou diminuer la vitesse, il
faut se limiter à une quarantaine de “crans”, on va
donc additionner (ou soustraire) 6 à chaque action sur un bouton.
Notre vitesse va donc
varier de 0 à 255 mais par pas de 6, soit 255/6 = 42 crans,
ce qui est plus raisonnable. On va maintenant traiter en détail
les trois actions :
|
10.4.1. Accélération |
Pour nous faciliter
la vie, on commence par copier la vitesse dans W,
rappelez-vous que de toute façon on doit toujours passer par W ;
on verra à la fin des traitements que l´on aura la nouvelle vitesse
(modifiée ou non) toujours dans W,
et on la recopiera à ce moment dans le registre VA_Vitesse.
Pour l´accélération
on teste l´entrée IO_Acceleration :
si elle est à on
passe à l´instruction suivante qui est un saut, et on ne fait
rien. Rappelez-vous aussi que l´on utilise en général une
logique “inverse” due à l´électronique, qui fait
qu´au repos l´entrée est au + 3 volts par la résistance
de rappel, et active (bouton poussoir enfoncé) au niveau zéro
volt. On traite donc l´accélération si le bit IO_Accélération est à (c´est-à-dire
clear).
Ensuite on va aborder
une nouvelle instruction : addlw (add
litteral to W). Cette
instruction ne fait qu´additionner un littéral à W (qui contient
notre vitesse initiale) et qui contiendra notre nouvelle valeur après.
RAPPEL :
Où est
mon littéral ? On retrouve ici une des “facilités
de programmation” : j´ai en effet remplacé le littéral
par une constante définie au début du programme. Cette définition
se fait par une directive C_Cran EQU d´6´ placée en
début de programme, et qui indique au logiciel MPLAB que chaque
fois qu´il rencontre C_Cran, il doit le remplacer (EQU=équivalence)
par la valeur d´6´ qui est bien un littéral.
Donc addlw
C_Cran est égal
(équivalent) à addlw d´6´.
Dans l´instruction suivante,
on teste (btfsc) un autre “indicateur
d´état”, C : celui-ci
est l´indicateur de “retenue” (carry) ou de dépassement.
Je m´explique :
lorsque vous additionnez à la main 8 et 6, vous écrivez “4
et je retiens 1” (= 14) ; vous avez bien un “dépassement”
sur vos unités, et un 1 de retenue.
Ici c´est pareil, sauf
que l´on raisonne sur des octets, c´est-à-dire des valeurs entre
0 et 255. Que se passe-t-il lorsque le registre contient 252 et que l´on
ajoute 6 ?
Pour vous le résultat
est 258, mais cela notre microP ne sait pas faire. Pour lui le résultat
est 2 avec un débordement (une retenue) et c´est ce débordement
qui est signalé par l´indicateur d´état STATUS,C.
Si vous avez suivi,
revenons à notre programme : en additionnant 6 dans W,
le résultat
peut être supérieur à 255, il faut donc tester le débordement,
et si oui remettre 255 dans W. Si vous
continuez d´accélérer
(d´appuyer sur le bouton “accélérer”), à chaque
fois il y aura débordement (255 plus 6), mais la valeur sera toujours
ramenée à 255.
Avant de passer au freinage,
relisez encore une ou deux fois cette partie, il y a beaucoup de nouveautés,
et il faudrait avoir bien compris, car la suite utilise exactement les
mêmes notions, mais dans l´autre sens (en moins !).
 |
PTI+ Les
bits STATUS. — La
plupart des instructions effectuant des opérations
sur des registres peuvent activer des bits indiquant
le “statut” du résultat, dont les
deux plus importants sont :
 Zéro
(STATUS,Z),
qui indique que le résultat de l´opération
est 0, donc que le registre est à 0,
 Carry
(STATUS,C),
qui indique un dépassement de capacité (ou
une “retenue”), c´est-à-dire que le
résultat est supérieur à 255 ;
dans ce cas, la valeur dans le registre est XXX (=résultat
de l´opération) moins 256.
D´autres bits de statut
existent dans ce microP, mais ils sont peu utilisés. |
|
|
|
10.4.2. Freinage |
On retrouve ici la même
séquence que pour l´accélération : d´abord on
teste l´entrée IO_Freinage, si
elle est à (inactive), on saute.
Si elle est à ,
on rentre dans le traitement de freinage.
On utilisera ici l´instruction
de soustraction subwf (substract
W from F), qui soustrait la valeur de W du registre en opérande.
On charge donc d´abord notre valeur dans W (movlw
C_Cran), valeur qui est
toujours notre constante d´inertie, puis on soustrait W du registre VA_Vitesse qui contient la vitesse actuelle.
Le résultat de
la soustraction peut être rangé au choix dans le même
registre (par ,F) ou dans W (par
,W), ce que nous faisons ici car j´ai besoin de la nouvelle vitesse dans
W. Remarquez que dans ce cas, le registre initial VA_Vitesse n´est pas
modifié.
Comme pour l´addition,
on a ici un risque de débordement, par exemple si la vitesse est à 4
et on soustrait 6, le résultat n´est pas —2 (il n´existe pas de
nombre négatif), mais 254, et on va donc utiliser l´indicateur d´état
STATUS,C pour tester le débordement.
MALHEUREUSEMENT,
il fonctionne ici à l´envers, il est actif (C
= 1) s´il n´y
a pas de débordement. Je ne m´étends pas sur le sujet, aucun
intérêt
pour nous, retenez juste que les soustractions sont l´inverse d´une addition
(ça, vous le saviez déjà), mais aussi pour le fonctionnement
de STATUS,C.
Dans notre programme
on saute donc à la suite si STATUS,C est à (set),
sinon (ce qui veut dire qu´il y a débordement au sens soustraction),
on est passé en dessous de zéro, et on ramène donc
notre vitesse dans W à zéro.
Pour ce faire, on utilise l´instruction clrw (clear
W), qui met à le
registre W :
c´est la même chose que
clrf qui mettait à un
registre, mais appliqué à W.
Donc une fois la vitesse à zéro,
tout appui sur freinage ne change rien, la vitesse reste à zéro.
Si vous aviez compris
l´accélération, le freinage n´a pas posé de problème,
sauf cette inversion de l´indicateur, mais il n´y a rien à comprendre :
c´est comme ça.
|
10.4.3. Stop |
Ici c´est tout simple,
il s´agit d´un arrêt immédiat (d´urgence), donc on met W à par clrw si
le bouton STOP est appuyé, c´est-à-dire IO_Stop à .
Nous avons maintenant
traité les trois boutons qui ont une action sur la vitesse, et le
résultat est toujours dans W. Il nous reste à ramener cette
nouvelle vitesse dans VA_Vitesse par :
La dernière chose à faire
est de traiter le changement de sens, c´est-à-dire la dernière
entrée IO_SENS.
 |
10.5.
Changement de sens |
|
10.5.1. Logique et électronique |
On s´est imposé la
contrainte de ne pouvoir changer de sens que lorsque la vitesse est à zéro,
encore faut-il savoir quand la vitesse atteint ce niveau. En effet, dans
les crans très bas (1 ou 2 ou 3...), suivant la locomotive, elle
n´avancera pas, même si dans notre microP la vitesse n´est pas encore à zéro.
Il est donc visuellement impossible de savoir quand
la vitesse est effectivement à zéro .
J´ai donc introduit
une led qui s´allume lorsque la vitesse est réellement à zéro
(VA_Vitesse), et c´est seulement dans cet état-là que le
sens peut être inversé.
Comme nous n´avons
que 6 entrées-sorties sur ce microP, qui sont déjà toutes
occupées (2 en sortie, 4 pour les boutons en entrée), et
qu´il nous en faut une supplémentaire, on peut soit
changer de microP
pour un modèle plus puissant, soit réfléchir un
peu et utiliser une des E/S soit en entrée soit en sortie selon
le cas.
 |
 |
 |
C´est
bien entendu (!) cette dernière solution que nous allons mettre
en œuvre dans ce schéma électronique :
En
fonctionnement normal, l´E/S 4 (commande STOP) est configurée
en entrée, relié au 3 V par R6 (220 K), et
au 0 V par R7 (4,7 K) si on appuie sur le bouton poussoir.
La led montée
en parallèle n´est pas allumée, le courant est bien
trop faible.
Lorsque la vitesse est à zéro
(le poussoir STOP n´est donc plus utile), l´E/S est en sortie, état
haut (= 1) et alimente la led qui nous indique que la vitesse est
zéro et que l´on peut donc changer de sens de marche. |
|
 |
 |
PTI+ Pour
les électroniciens. — Le
montage proposé sur le poussoir S2 peut sembler
curieux, mais il marche.
Les caractéristiques électriques
du microP sont en effet assez différentes des circuits plus classiques
CMOS : pour une entrée à 0, elle doit être vraiment
proche de 0 V, typiquement inférieure à 0,8 V ou
1 V selon l´entrée.
Dans notre montage,
l´entrée est à 1,7 V, suffisant pour détecter
un 1 par le microP. |
|
|
|
10.5.2. Le programme |
Nous n´entrons dans
cette partie du programme lorsque, à la fin du traitement de la
vitesse, celle-ci est à 0. On s´impose en effet comme contrainte
que le changement n´est possible qu´à l´arrêt de la locomotive.
La première chose
est d´allumer la led, il faut donc passer l´E/S 4 en sortie, état
1. On attend ensuite une action :
  soit
un changement de sens (bouton S1 SENS),
  soit
un redémarrage de la loco (bouton S4 accélération).
Dans les deux cas, pour éviter les problèmes de rebond, une
seule action nous fait sortir immédiatement de ce traitement et
revenir dans la situation standard du chapitre précédent.
Test vitesse zéro :
Nous allons ici aussi
utiliser l´instruction movf, qui copie
un registre sur lui-même,
et qui nous permet par l´indicateur d´état Z de
tester le zéro de la vitesse.
Si ce n´est pas le cas,
on revient au début du programme principal.
Allumage LED :
Ici on allume la LED
en changeant l´E/S 4 en sortie (TRISIO,4 à )
et en positionnant la sortie à .
Rappel
1 : C´est
dans le registre TRISIO que l´on indique
les sens des E/S, bit à pour
sortie (zéro comme O, comme Output) ou à pour
entrée (1 comme I comme Input).
Rappel
2 : BANK0 et BANK1 :
Certains registres spéciaux, dont TRISIO, sont situés dans
la deuxième partie de la mémoire du microP, et il faut donc
d´abord se positionner dans cette partie (BANK1), et ne pas oublier de
revenir après (BANK0).
Changement de sens :
Nous avons ici une boucle
d´attente d´une des deux actions possibles :
  accélération :
on saute à la fin de cette section sans changer de sens ;
  changement
de sens (IO_SENS) : dans ce cas
on exécute l´inversion du bit zéro
de GPIO avec un “ou exclusif” (xorwf)
de GPIO et du chiffre b'00000001'.
 |
 |
 |
Rappel : xorwf (cette
instruction a déjà été vue dans l´introduction
et le montage Klaxon). Un “ou exclusif” (xor)
entre deux bits donne 1 si les deux bits sont différents (0 et 1),
et 0 si les bits sont identiques (00 ou 11).
Si
le bit n° zéro de GPIO était à zéro : zéro
xor 1 le met à 1 (cf. ligne 3
du tableau ).
Si le bit visé était à :
1 xor 1 le met à zéro (ligne 4
du tableau ). |
|
 |
On ramène
ici l´E/S 4 en entrée (TRISIO,4 à ),
et surtout on met la vitesse (qui est à 0) à 1 avant de revenir
au programme principal, ce qui évitera de revenir dans la boucle
de changement de sens.
 |
10.6.
Le traitement de l´interruption |
Cela doit être
la troisième ou quatrième fois que nous reprenons le fonctionnement
du Timer, et si vous êtes certains
d´avoir tout compris, sautez tout de suite au morceau de programme plus
loin. Mais je vous recommande cependant de lire les quelques lignes ci-dessous,
moi-même je trouve que ce
n´est pas évident du tout, et une nouvelle couche ne vous fera pas
de mal.
Notre Timer compte, il s´incrémente
de 1 toutes les 16 µS,
et déclenche une interruption chaque fois qu´il passe de 255 à zéro.
Nous allons donc inverser
(de à ou
de à )
notre sortie IO_Sortie_Train à chaque
interruption. Nous avons par ailleurs notre variable VA_Vitesse,
qui contient la valeur le la vitesse.
Si
la sortie est à ,
on la passe à ,
puis on charge le timer avec la valeur de VA_Vitesse,
ce qui fait qu´il va compter 255 – VA_Vitesse avant
la prochaine interruption.
Si
la sortie est à ,
on la passe à ,
et on va compter 255 – (255 – VA_Vitesse),
c´est-à-dire VA_Vitesse jusqu´à la prochaine interruption.
Une période à 1
plus une période à étant égale à 255 – VA_Vitesse
+ VA_Vitesse, c´est-à-dire
toujours 255, donc une fréquence fixe de 240 Hz, quelle que
soit la valeur de VA_Vitesse. C´est
ce qui est réalisé dans
le morceau de programme ci-dessous (il n´y a pas de nouvelle instruction,
vous devriez pouvoir le lire et le comprendre).
À chaque passage de
la sortie à ,
nous avons un décrément du compteur
d´inertie, qui permet de tenir compte de l´inertie dans l´accélération
ou le freinage, voir plus haut. decf est
une nouvelle instruction, qui ne fait que soustraire 1 au registre indiqué en
opérande.
Le résultat peut être soit rangé dans le même
registre (si on indique ,f comme ici),
soit rangé dans le registre
W (si on indique ,W).
Dans ce dernier cas,
si on récupère la valeur initiale moins 1 dans W, le registre
général initial reste inchangé.
 |
10.7.
Conclusion |
Ce montage fonctionne
sans problème, ni réglages, il a été testé chez
moi et chez Jidé avec différents types de locos.
Plusieurs variantes
sont possibles : par exemple on pourrait ajouter, sur le circuit de
puissance, un dispositif permettant de récupérer un courant
continu proportionnel au rapport cyclique.
Pire, certains songent
déjà à récupérer la F.C.E.M. (voir ce
terme dans les ouvrages spécialisés) pour améliorer
encore le rendement ! Et avec ça, on peut faire rouler au ralenti
une 020 Decauville Hoe Jouef de 1967, qui ne marchait même pas en 1967 ! [Montage
à venir dans Ptitrain.]
 |
 |
 |
En
ce qui concerne le programme, vous pouvez bien entendu modifier les
paramètres pour avoir plus ou moins de crans dans la vitesse,
ou changer l´inertie, ou la fréquence de 240 hertz... je fais
confiance à votre imagination.
On pourrait aussi sophistiquer
le programme en calculant une valeur de cran différente pour les
crans bas et les crans haut, sachant que la vitesse réelle de la
locomotive n´est pas une fonction linéaire de la variable VA_Vitesse.
Bref,
beaucoup de choses sont possibles*, ce montage est une base pour de futurs
développements ;
je sais par exemple que Jidé souhaite l´appliquer à des
automatismes plus compliqués comme par exemple une version du Numerax à microP
(bonne chance !).
|
|
  |
*
Il serait également possible de remplacer carrément le transistor
de puissance directement par un LM317**, ce qui permettrait de profiter
des sécurités en cas de surcharge et de court-circuit, de
ce composant. Idée de Jidé, fondée sur ce
schéma
de National Semiconductor ,
pas encore testée.
** J.P.M.
de l'A.M.F.N. nous écrit : “Malheureusement, nous sommes plusieurs à avoir
essayé, et ça
ne donne pas de bons résultats, parce que cette fonction
du LM317 est très
surfaite : en pratique, il se met en limiteur de courant, surchauffe un max et
finit par griller si on n'a pas prévu un radiateur surdimensionné... à moins
que ce soit une autre partie du circuit (palpeurs de prise de courant des locos...)
qui grille !” |
|