[ Accueil ] [ CONTACT ] [ PLAN du Site ] [ RCNV ] [ Publications ] [ Chantiers Bateaux ] [ Technique Modélisme ] [ Electronique ] [ Radios Vintage ] [ Multi-Switch ] [ Vrac ] [ Astuces ] [ Liens ] [ Base ] [ Compteur ]
 

        ... rgl

 

Les encodeurs numériques

Codeur absolu - Codeur incrémental

Application Micro Contrôleur

(c) R.LEGAT jr
 

 

 Sur cette page:

-  Les types d'encodeurs ou de codeurs numériques
-  Bref
comparatif entre codeur absolu et codeur incrémental
-  L'
encodeur incrémental: générateur de code Gray (binaire réfléchi)
-  Déterminer le
sens de rotation
-  Comptage du nombre de crans encodés
Algorithme de traitement des signaux d'un encodeur incrémental
-  Application: Conception d'un Menu pour gérer un programme


 

 

 

 

Les types de codeurs:

 

Il existe deux types de codeurs: le codeur absolu et le codeur incrémental.

Ils peuvent être de type électromécanique ou optique et peuvent se présenter en modèle rotatif ou linéaire (latte).

 

Dans le cas d'un encodeur absolu, chaque position est caractérisée par un code non volatile.

Cette position est connue dès la mise sous tension du système.

 

Le codeur incrémental, de conception plus simple, et donc moins onéreux, génère un code Gray sur deux bits.

Les modèles un peu plus sophistiqués, optiques par exemple, peuvent présenter une info supplémentaire : le « top zéro ».

Il s’agit d’une impulsion qui est générée une seule fois par tour et qui détermine une position de référence permettant une réinitialisation à chaque tour.

 

                    

 

                                                  Codeur absolu                                                                           Codeur incrémental

 

                                                                     

Bref comparatif des deux systèmes :

 

Codeur absolu

Avantages

 

II est insensible aux coupures du réseau : la position du mobile est détenue dans un code qui est envoyé en parallèle (parfois en série) au système de traitement.

 

L'information de position est donc disponible dès la mise sous tension.

 

Si le système de traitement «saute» une information de position délivrée par le codeur, la position réelle du mobile ne sera pas perdue car elle restera valide à la lecture suivante.

 

Le positionnement peut se faire sans référence par un passage par zéro (Top zéro)

Inconvénients

 

Il est de conception électrique et mécanique plus complexe aussi son coût sera plus élevé qu'un codeur incrémental.

 

Les informations de position sont délivrées « en parallèle » ; son utilisation mobilisera donc un nombre important d'entrées du système de traitement. A noter que les modèles plus sophistiqués transmettent leur code en mode série.

 

 

Codeur incrémental

Avantages

Le codeur incrémental est de conception simple car son disque ne comporte que deux pistes, voire une troisième pour le « top zéro ».

 

Il est donc plus fiable et moins onéreux qu'un codeur absolu.

Inconvénients

 

Le système de gestion est sensible aux coupures du réseau : chaque coupure du courant peut faire perdre la position réelle du mobile à l'unité de traitement. Il faudra alors procéder à la réinitialisation du système automatisé.

 

Il est sensible aux parasites en ligne, un parasite peut être comptabilisé par le système de traitement comme une impulsion délivrée par le codeur.

 

Les fréquences des signaux A et B étant généralement élevées, il faudra vérifier que le système de traitement est assez rapide pour prendre en compte tous les incréments (impulsions) délivrés par le codeur.

 

Le non-comptage d’une impulsion induit une erreur de position qui ne peut être corrigée que par la lecture du « top zéro».

 

 

    Nous allons nous intéresser au codeur incrémental simple.

 

 

CODEUR INCREMENTAL

 

Générateur de Code Gray (Binaire réfléchi) sur 2 bits

 

 
Pour nos applications, nous allons utiliser le codeur incrémental simple.

 

Outre une entrée «tension de référence» (C), il comporte juste deux sorties (A, B) et donc pas d’info « Top zéro ».

 

Certains modèles peuvent être munis d’un switch poussoir, fermé par enfoncement de l’axe, pour validation d’une commande, par exemple.


Ce type de codeur rotatif est donc un « générateur d’impulsions » qui délivre un code Gray sur ses deux sorties.

Le code Gray se caractérise par la modification d’un seul bit à la fois, à chaque changement d’état.

 

Dans notre cas, les impulsions doivent être traitées pour en interpréter:   - le sens de rotation de l’axe

                                                                                                                             - le nombre de crans qui ont été tournés

 

 

 

Constitution interne 

Le codeur comporte un disque avec des zones de contact régulièrement espacées qui sont connectées à la broche commune (généralement reliée à Gnd), et à deux autres broches de contact séparées: A et B.

Le disque pouvant tourner sur 360°, dans un sens ou dans l'autre, les broches A et B entreront en contact avec la broche commune et les deux signaux carrées de sortie seront générés en conséquence.

L'interprétation de la séquence des deux signaux carrés va nous permettre de déterminer le sens et la vitesse de rotation, ainsi que le nombre de pas effectués durant la rotation.

Ces informations seront traitées par un MCU et seront très utiles pour de multiples tâches habituelles: menu déroulant, réglage d'un timer, volume sonore, ...

 

      

       

 

 

 

 

Déterminer le sens de rotation

 

Analysons préalablement le code Gray généré par l’encodeur incrémental :

 

            

 

                                      

                                                                               Code Gray généré sur 2 bits.

 

 

  

1) Traitement des impulsions par électronique

 

Sens de rotation

 

Utilisation d’une bascule D

 

Le déphasage de 90° électrique des signaux A et B permet de déterminer le sens de rotation :

-       Dans un sens pendant le front montant du signal A, le signal B est à zéro.

-       Dans l’autre sens pendant le front montant du signal A, le signal B est à un.

 

Si on utilise une bascule D (74HC74) en branchant le signal A sur l’entrée CK et le signal B sur la patte D, l’état de la sortie Q nous indiquera le sens de rotation de l’axe.

 

 

 

D

H

Q n+1

0

^

0

1

^

1

x

0

Qn

x

1

Qn

   

Q recopie D à chaque front montant sur H.                   

 

 

Les pins /CLR et /PR de la bascule seront forcés à l'état haut.

                                                                                                               

 

 

2) Lecture et traitement des états stabilisés par Microcontrôleur

 

A) Sens de rotation

 

Suivant les tables et les graphiques édités plus haut, nous constatons qu’il est possible de déterminer le sens de rotation simplement en effectuant une opération Logique XOR sur le nouvel état de A et l’état de B précédent.

 

Pour différencier les nouveaux états établis des précédents, nous allons identifier les états précédents de A et B avec un préfixe «p» et les nouveaux états avec l’indice «n».

 

Nous allons écrire les 4 états possibles dans l’ordre où ils se présentent chronologiquement :

 

nA = nouvelle valeur de A

Ap = valeur précédente de A

nB = nouvelle valeur de B

Bp = B précédent 

                            

                                                              Mais ces formules ne sont valables que pour une rotation que d’un seul cran !  

 

En effet, si un pas est « sauté », les comparaisons des anciens états et des nouveaux ne seront plus «synchronisés» et les formules ne seront donc plus valables !

 

Il faut donc espérer que le µC soit suffisament rapide pour effectuer sa boucle infinie et pouvoir traiter distinctement chaque cran, un par un, en lui laissant le temps de bien remémoriser chaque valeur de B (Bp).

 

L’idéal serait d’utiliser une «Interruption» dès que l’encodeur est activé… mais certains µC, dont le Stamp, ne gèrent pas les interruptions.

 

 

B) Comptage des crans

 

 

ATTENTION: 
Avec certains petits codeurs, un cran que l'on ressent en tournant la molette, provoque en fait la génération de 4 cycles !
On peut s'en rendre compte en placant un multimètre entre une sortie et la broche de référence: lorsqu'on tourne d'un cran, le résultat de mesure ne change pas !

En fait, il y a bien eu passage par 4 cycles différents mais très rapidement !

Il faut en tenir compte dans la conception du programme, en divisant les mesures effectives par 4 !

 

Ce qui va être expliqué ci-dessous considère qu'un cran = 1 seul changement d'état (et non 4).

 

Nous allons donc devoir utiliser une variable « compteur de crans » et la mettre à jour pour chaque cran tourné dans un sens ou l’autre.

 

Au vu de ce que nous avons vu plus haut nous disposons des données suivantes:

 

Sens de rotation

nA XOR Bp=

Action Compteur

Direct

0

+1

Inverse

1

-1

 

Pour une rotation dans le sens direct, nous devrons incrémenter le compteur de crans et pour le sens inverse, ce compteur devra être décrémenté.

 

Si nous appelons «I» l’incrément du compteur et «x» le résultat de (nA xor Bp), nous avons les relations suivantes:

 

Pour x=0   -->   I = +1           Ecart de 1 unité entre x et I

Pour x=1   -->   I = -1            Ecart de 2 unités entre x et I

 

 

Nous allons raisonner sur le principe des régressions mathématiques.

 

Une régression est l'estimation de l'équation de la relation existant entre plusieurs variables, ici x et I.

 

Considérant ici x la mesure des causes, et I celle des effets, la liaison entre I et x s’écrit suivant la relation fonctionnelle suivante :  I = fc (x).

Traduisez: à une valeur donnée de x correspond une valeur bien déterminée de I.

 

Cette relation peut être linéaire ou non.

Dans le cas d’un modèle linéaire, l'équation de la régression est: Modèle linéaire: I=a+bx.

 

Et oui, l'équation d’une droite dont les paramètres sont : a (ordonnée à l'origine) et b (pente).

 

 

Dans notre cas, nous voyons que pour une variation d’une unité de x, I peut varier de 2 unités dans le sens inverse.

 

Un facteur b de -2 est donc à introduire dans notre fonction avant d’évaluer le facteur «a».  Ainsi :

 

Pour x=0   ==>   I = x * (-2) = 0            (Le résultat final doit être +1)

Pour x=1   ==>   I = x * (-2) = -2           (Le résultat final doit être -1)

 

Nous voyons immédiatement que le facteur de transposition «a» est alors égal à +1.  En effet :

 

Pour x=0   ==>   I = (x * (-2)) +1 = +1   ( Le résultat final de +1 est obtenu )

Pour x=1   ==>   I = (x * (-2)) +1 = -1    ( Le résultat final de -1 est obtenu )

 

 

Nous pouvons donc finaliser ce raisonnement en écrivant :

 

                    Compteur = Compteur + (((nA.xor.Bp)*(-2))+1)   

 

Cette formule n’est à appliquer, cran après cran, que lorsque l’encodeur a effectivement été actionné !

 

Pour les MicroContrôleurs qui ne gèrent pas les Interruptions, un mouvement sera détecté en scrutant les modifications d’état des sorties A et B de l’encodeur.

 

 

Algorithme

 

Structuré :

 

IF (nA<>Ap.or.nB<>Bp)                                ‘ Action détectée sur encodeur

  LET ComptOld = Compteur                            ' Mémorisation du Compteur

  LET Compteur = Compteur + (((nA.xor.Bp)*(-2))+1)   ' Incrémente/Décrémente Compteur

  LET NbreCrans = Compteur – ComptOld                ‘ Nombre de crans

  LET Ap = nA                                        ‘ Remplacement mémo de Ap par An

  LET Bp = nB                                        ‘ remplacement mémo de Bp par Bn

Endif

 

 

Programme complet de test d'un encodeur et affichage des résultats sur LCD 2 Lignes/16#


Ce programme va tester les actions sur un encodeur numérique. Il va ainsi:
     - Compter les impulsions générées suivant deux calculs différents (dont les 2 résultats seront affichés simultanément)

     - Déterminer le sens de rotation

     - Reconnaitre une rotation lente ou rapide (utile pour accélérer une incrémentation dans un système opérationnel par exemple)

     - Afficher les résultats sur un LCD, en mode 4bits, avec gestion temporisée du backLight + test de l'afficheur au démarrage

     - Générer un bip lorsque le codeur est actionné

 

                              Le programme est testé sur une plateforme Basic Stamp IIsx

          
                               A gauche le codeur, à droite le potentiomètre de contraste.
                               LCD bleu, caractères blancs, 2Lx16C, rétroéclairé.

 

Programme de test

 

' {$STAMP BS2sx}
' {$PBASIC 2.5}
'  ________________________________________________________________________________________
' |                                                                                        |
' | Fichier : Test_EncodV5_LCD.bsx                                                         |
' |                                                                                        |
' | Concept : R.LEGAT / Micro_Info                                                         |
' | Date    : 03 Octobre 2013                                                              |
' |                                                                                        |
' | Notes : Lecture d'un encodeur numérique.                                               |
' |*******  Affichage LCD sur 5 caracteres de la valeur lue (0 à 65535).                   |
' |         La valeur fait l'objet de 2 formules d'ajustement et de stabilisation.         |
' |         Un Piezo émet un bip sonore lors d'un changement de valeur.                    |
' |         Un compteur donne un indice de vitesse de rotation de l'encodeur.              |
' |         Le rétroéclairage s'allume lors d'une action sur l'encodeur.                   |
' |         Une tempo calibre la durée d'allumage du rétroéclairage.                       |

' |         Un test initial des digits du LCD est effectué au démarrage.                   |
' |________________________________________________________________________________________|
'
'-------------------------------------------------------------------------------------------
'    Liste des connexions  (Stamp, Encodeur, Piezo, LCD 2x16, rétroéclairage)
'-------------------------------------------------------------------------------------------
'    -------------------------
'   | ENCODEURS | STAMP2 i/o
'    ---------- +-------------
'     Encod. Xa |  P0    In
'     Encod. Xb |  P1    In
'    -----------
'   |   PIEZO   |  P3    Out
'    -----------
'   |    LCD    |
'    -----------|
'      BkLight  |  P4    Out
'     (15/16)   |             par Transitor de commutation
'
'      RS (4)   |  P10   Out
'      E  (6)   |  P11   Out
'
'      D4 (11)  |  P12   Out \
'      D5 (12)  |  P13   Out |
'      D6 (13)  |  P14   Out | OUTD (LCDbus de 4 bits)
'      D7 (14)  |  P15   Out /
'
'      RW (5)   |  Gnd    = Write
'      D0 (7)   |  Gnd \
'      D1 (8)   |  Gnd |
'      D2 (9)   |  Gnd |  = Mode 4 bits
'      D3 (10)  |  Gnd /
'
'          Connexions LCD
'      -------------------------
'        (LCD)  |  (Fonction)
'      ---------+---------------
'        pin 1  |  -Vss
'        pin 2  |  +Vdd
'        pin 3  |  Contrast
'        pin 4  |  RS  (1= Data, 0= Command)
'        pin 5  |  R/W (1= Read, 0= Write)
'        pin 6  |  E   (1= enabled)
'        pin 7  |  DBO
'        pin 8  |  DB1
'        pin 9  |  DB2
'        pin 10 |  DB3
'        pin 11 |  DB4
'        pin 12 |  DB5
'        pin 13 |  DB6
'        pin 14 |  DB7
'        pin 15 |  + Anode BackLight
'        pin 16 |  - Kathode (3,1V / 18mA = R de 33 à 100ohms vers +5V)
'
'-------------------------------------------------------------------------------------------
' Position des caractères à afficher (2x16#)
'
'     |-------------------------------|   X= nombre de changement d'états (4 par cran !)
' L1: |X = 0 0 0 0 0 . . A = 0 0 0 0 0|   A= (X+3)/4 Formule A_justée
' L2: |B = 0 0 0 0 0 . . > R A P I D E|   B= X/4     Formule B_asique
'     |-------------------------------|   LENT ou RAPIDE = Vitesse de rotation de l'encodeur
'
'-------------------------------------------------------------------------------------------
' COMMANDES d'adressage des 2 x 16 caractères (en hexa) => Adresse de la DDRAM + 128.d !
'
'     |-------------------------------------------------|
' L1: | 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F |
' L2: | C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF |
'     |-------------------------------------------------|
'
'*******************************************************************************************
' Définitions des VARiables et CONstantes
'*******************************************************************************************
 ComptX          VAR     Word             ' Compteur pour l'encodeur de l'axe X
 ComptA          VAR     Word             ' Compteur X manipulé  (Formule de stabilisation)
 ComptB          VAR     Word             ' Compteur X simplement(Formule /4)

 XAp             VAR     Bit              ' Lecture précédente de pin A (X)
 XBp             VAR     Bit              ' Lecture précédente de pin B (X)

 Timing          VAR     Word             ' Mesure temps entre clicks (0 à 65535)
 TLight          VAR     Word             ' Temps d'éclairage du BackLight

 Char            VAR     Byte             ' Caractère Data ou Commande envoyé sur le LCDbus
 Pdis            VAR     Byte             ' 80 emplacements de caractères sur l'écran

 Lecture         VAR     Word             ' Valeur du compteur (0 à 65535)

 Unite           VAR     Byte             ' Digit Unite      (0 à 9)
 Dizaine         VAR     Byte             ' Digit Dizaine    (0 à 9)
 Centaine        VAR     Byte             ' Digit Centaine   (0 à 9)
 Millier         VAR     Byte             ' Digit Millier    (0 à 9)
 DixMillier      VAR     Byte             ' Digit DixMillier (0 à 9)

 

 Seuil           CON     100              ' IF Timing > Seuil then LENT
 Tempo           CON     100              ' Temporisation utilisée pour l'affichage


'*******************************************************************************************
' Définition des I/O du Stamp
'*******************************************************************************************
 Xa              VAR     IN1              ' Pin a Encodeur X
 Xb              VAR     IN0              ' Pin b Encodeur X

 LCDbus          VAR     OUTD             ' 4-bit LCD Data Bus

 

 Bip             CON      3               ' Piezo pour comptage sonore des crans
 BkLight         CON      4               ' Rétro-éclairage par Transistor de commutation

 RS              CON     10               ' Register Select (1= Data, 0= Command)
 E               CON     11               ' LCD Enable (1 = enabled)


'*******************************************************************************************
' Initialisation des Entrées / Sorties du Stamp
'*******************************************************************************************
' Définitions des pins du Stamp : 0=Entrée / 1=Sortie

  DIRS = %0   'All input for security

   OUTPUT  4  'BkLight (par Transistor de commutation)
   OUTPUT  5  'Piezo pour comptage sonore des crans
   OUTPUT 10  'RS   to  4.Lcd
   OUTPUT 11  'Enb  to  6.Lcd
   OUTPUT 12  'DB4  to 11.Lcd \
   OUTPUT 13  'DB5  to 12.Lcd |
   OUTPUT 14  'DB6  to 13.Lcd | OUTD
   OUTPUT 15  'DB7  to 14.Lcd /

'ou
' DIRL = %00110000
' DIRH = %11111100
'ou
' DIRS = (DIRH DIRL) = %11111100 00110000


'*******************************************************************************************
'  Codes généraux de contrôle pour l'afficheur LCD
'*******************************************************************************************
''' Mettre en remarque les Constantes non utilisees par le programme !

  ClrLCD   CON  $01     '00000001  ' Effacement de l'afficheur                     1
' CrsrHm   CON  $02     '00000010  ' Positionnement du curseur en HOME             2
' CrsrGa   CON  $10     '00010000  ' Déplacement du curseur vers la gauche        16
' CrsrDr   CON  $14     '00010100  ' Déplacement du curseur vers la droite        20
' DiSpGa   CON  $18     '00011000  ' Déplacement de l'affichage à gauche          24
' DispDr   CON  $1C     '00011100  ' Déplacement de l'affichage à droite          28
' CGRAM    CON  $40     '01000000  ' RAM pour caractères perso                    64
' DDRAM    CON  $80     '10000000  ' RAM d'affichage à sa 1ere adresse           128
' Line1    CON  $80     '10000000  ' Adressage DDRAM debut 1ere ligne afficheur  128
' Line2    CON  $C0     '11000000  ' Adressage DDRAM debut 2eme ligne afficheur  192
  AllOn    CON  $0E     '00001110  ' Curseur On et continu + Afficheur On         14
  AllOff   CON  $08     '00001000  ' Curseur et Afficheur Off                      8
  CrsrOff  CON  $0C     '00001100  ' Curseur Off + Afficheur On                   12
' CrsrCgt  CON  $0F     '00001111  ' Curseur clignotant                           15
' Scrolli  CON  $06     '00000110  ' No shift - Increment                          6
' Scrolld  CON  $04     '00000100  ' No Shift - Decrement                          4
' Mode1L   CON  $20     '00100000  ' Mode 1 Ligne  5*7                            32
  Mode2L   CON  $28     '00101000  ' Mode 2 Lignes  5*7                           40


'*******************************************************************************************
' EEPROM Data  --->   2K (x8) pour le programme et les Datas
'*******************************************************************************************
 Msg0      DATA    "Test_EncodV5_LCD"  ' Nom/version du programme 16 caractères
 Msg1      DATA    "LENT  "            ' Mise en EEPROM message de 6 caractères
 Msg2      DATA    "RAPIDE"            ' Mise en EEPROM message de 6 caractères


'*******************************************************************************************
' Initialisation LCD - Mode 4 bits - 2 Lignes de 16 caractères
'*******************************************************************************************
LCD_Init:           'Ce label est facultatif car le programme n'y fera plus appel

 LOW RS             ' Passage en mode COMMANDE
  PAUSE 500         ' Stabilisation de l'alim
  LCDbus = %0011    ' Commande de fonction en mode 8 bits (!) 3
  PULSOUT E,1       ' Envoi de la commande (Top de 1x 80nsec)
  PAUSE 5           ' Attend 5 mS (+ de 4.1 ms)
  PULSOUT E,1       ' Envoi de la Commande
  PAUSE 1           ' Attend 1 mS (+ de 100 µs)
  PULSOUT E,1       ' Envoi de la Commande
  PAUSE 5           ' Attend 5 mS (+ de 4.1 ms)
  LCDbus = %0010    ' Commande de fonction en mode 4 bits     2
  PULSOUT E,1       ' Envoi de la Commande
  PAUSE 1           ' Attend 1 mS (+ de 40 µs)
  Char = Mode2L     ' Mode 4 bits, 2 lignes, Matrice 5x8     44
  GOSUB LCD_Command ' Envoi de la Commande
  PAUSE 1           ' Attend 1 mS (+ de 40 µs)
  Char = AllOff     ' Ecran off, Curseur off, clignote off
  GOSUB LCD_Command ' Envoi de la Commande
  PAUSE 1           ' Attend 1 mS (+ de 40 µs)
  Char = AllOn      ' Ecran On, Curseur On, clignote off
  GOSUB LCD_Command ' Envoi de la Commande
  PAUSE 1           ' Attend 1 mS (+ de 40 µs)
  Char = %00000110  ' Curseur vers la droite, Affichage fixe  6
  GOSUB LCD_Command ' Envoi de la Commande
  PAUSE 1           ' Attend 1 mS (+ de 40 µs)
  Char = ClrLCD     ' Effacement de l'écran
  GOSUB LCD_Command ' Envoi de la Commande
  PAUSE 2           ' Attend 1 mS (+ de 40 µs)
 HIGH RS            ' Relachement de la ligne de commande. Passage en mode DATA Caractères


' |========================================================================================|
' |      *************************** Début du programme **************************         |
' |========================================================================================|

Test_LCD:                          'Ce label est facultatif car le programme n'y fera plus appel

Char = CrsrOff : GOSUB LCD_command ' 2 commandes sur la même ligne grace au caractere separateur ":"

 

'TEST initial des 2x16 digits du LCD, de son BackLight et du Piezo

FREQOUT bip, 2500, 1550                    ' Long Beep de Reset ==> Test du piezo
HIGH BkLight                               ' Allumage rétroéclairage

 

  FOR Pdis=0 TO 15
   Char = $80+Pdis : GOSUB LCD_Command       ' Adressage au #01 de la L1 et suivants
   Char = $FF      : GOSUB LCD_Data          ' Envoi d'un caractère complètement rempli
   PAUSE 2*Tempo                             ' Delai entre l'affichage de chaque caractère
  NEXT                                       ' Affiche 16 caractères pleins sur la Ligne1

 

 FOR Pdis=0 TO 15
  Char = $C0+Pdis : GOSUB LCD_Command       ' Adressage au #01 de la L2 et suivants
  Char = $FF      : GOSUB LCD_Data          ' Envoi d'un caractère complètement rempli
  PAUSE 2*Tempo                             ' Delai entre l'affichage de chaque caractère
 NEXT                                       ' Affiche 16 caractères pleins sur la Ligne2

PAUSE 20*Tempo                              ' Délai avant effacement des deux lignes de test des digits du LCD

 

Char = ClrLCD : GOSUB LCD_command          ' Effacement de l'écran

 

' Affichage du nom du programme (16 caractères)
'=> Ligne 1:

FOR Pdis=0 TO 15                           ' Affichage de Msg0 de l'EEPROM (16 caracteres)
 READ (Msg0 + Pdis),Char
 GOSUB LCD_Data                            ' Affiche le nom est la version du programme (Msg0)
 'PAUSE 2*tempo                            'Delai entre l'affichage de chaque caractère
NEXT

 

'=> Ligne 2:
' Autre moyen, mais plus gourmand en commandes et en temps, pour transmettre des caract. non mémorisés
Char = $C4 : GOSUB LCD_Command        ' Adressage au #05 de la L2
Char = 82  : GOSUB LCD_Data           ' envoi de "R"
Char = 46  : GOSUB LCD_Data           ' Envoi de "."
Char = 76  : GOSUB LCD_Data           ' envoi de "L"
Char = 101 : GOSUB LCD_Data           ' Envoi de "e"
Char = 103 : GOSUB LCD_Data           ' envoi de "g"
Char = 97  : GOSUB LCD_Data           ' Envoi de "a"
Char = 116 : GOSUB LCD_Data           ' envoi de "t"

PAUSE 30*Tempo                        ' Délai pour la lecture du nom du programme et du CopyRight

 

' Effacement LCD
Char = ClrLCD : GOSUB LCD_command : PAUSE 2   '3 commandes sur la meme ligne grace au séparateur ":"

 

'Envoi des labels fixes: ( X=  A=   B=   > )
'Ces labels pourraient etre mis en Data EEPROM et affichés comme le nom du programme (READ)

Char = $80 : GOSUB LCD_Command        ' Adressage au #01 de la L1
Char = 88  : GOSUB LCD_Data           ' envoi de "X"
Char = 61  : GOSUB LCD_Data           ' Envoi de "="

Char = $89 : GOSUB LCD_Command        ' Adressage au #10 de la L1
Char = 65  : GOSUB LCD_Data           ' envoi de "A"
Char = 61  : GOSUB LCD_Data           ' Envoi de "="

Char = $C0 : GOSUB LCD_Command        ' Adressage au #01 de la L2
Char = 66  : GOSUB LCD_Data           ' envoi de "B"
Char = 61  : GOSUB LCD_Data           ' Envoi de "="

Char = $C9 : GOSUB LCD_Command        ' Adressage au #10 de la L2
Char = 62  : GOSUB LCD_Data           ' envoi de ">"

ComptX = 0 : Xap = Xa : Xbp = Xb      ' RAZ valeurs Encodeur X
TLight = 0 : Timing = 0               ' Initialisation des compteurs
LOW BkLight                           ' Extinction BackLight


' |========================================================================================|
' |    ***********************  Début de la boucle infinie  **************************     |
' |========================================================================================|

'--->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  DO                          ' Debut de la boucle logique principale et infinie.
                               ' Pas besoin de label car on évitera toujours d'utiliser l'instruction Goto !

'DEBUG CLS                     ' Effacement écran PC de la lecture précédemment effectuée (en cas d'utilisation du Debug vers le PC)

                               ' Le Debug est surtout utilisé en phase de conception et de test du programme.

                               ' Par la suite, lorsque le programme est fonctionnel, il est autonome et retourne ses infos vers le LCD


    Timing = Timing + 1        ' Boucle de comptage vitesse de rotation de l'encodeur
    TLight = TLight + 1        ' Boucle de comptage pour durée du BackLight

      IF TLight >3000 THEN
       LOW BkLight             ' Extinction du BackLight après durée déterminée (3000 boucles)
      ENDIF
'DEBUG ? Timing
'DEBUG ? TLight

  IF ((Xa<>Xap)|(Xb<>Xbp)) THEN             ' Test si changement de valeur sur lecture X
   ComptX = ComptX + (((Xa ^ Xbp)*(-2))+1)  ' Calcul nouvelle valeur du compteur X
   Xap = Xa : Xbp = Xb                      ' Mise à jour des valeurs précédentes pour X

'DEBUG ? xa
'DEBUG ? xb
     IF ((Xa=1)&(Xb=1)) THEN             ' Test de position stabilisée du Cran
       HIGH BkLight                      ' Allumage du BackLight car action sur l'encodeur
       FREQOUT bip, 40, 1500             ' Beep changement de valeur
       TLight = 0                        ' Début de la tempo pour le rétroéclairage
        ComptA = ((ComptX+3)/4)          ' Formule1: Ajustement de la valeur du compteur
        ComptB = ComptX/4                ' Formule2: Basique sans stabilisation (encodeur/4)

'DEBUG ? ComptX
Lecture = Comptx
GOSUB Calcul      ' Décompose la valeur X en Unités, Diz., Cent.,Mil., DixMil.
GOSUB AffCptX
     ' Affichage de la valeur du compteurX

'DEBUG ? ComptA
Lecture = ComptA
GOSUB Calcul      ' Décompose la valeur A en Unités, Diz., Cent.,Mil., DixMil.
GOSUB AffCptA
     ' Affichage de la valeur du compteurA

'DEBUG ? ComptB
Lecture = ComptB
GOSUB Calcul      ' Décompose la valeur B en Unités, Diz., Cent.,Mil., DixMil.
GOSUB AffCptB
     ' Affichage de la valeur du compteur B

'DEBUG ?timing,CR

   IF Timing > Seuil THEN
'DEBUG "LENT",CR,CR


'Affichage LCD, caractere par caractere
    Char = $CA : GOSUB LCD_Command              ' Adressage au #11 de la Ligne2
      FOR Pdis = 0 TO 5
       READ (Msg1 + Pdis),Char : GOSUB LCD_Data ' Msg1 = "LENT  "
       'PAUSE 2*tempo

      NEXT
   ELSE
'DEBUG  "RAPIDE",CR,CR


'Affichage LCD, caractere par caractere
    Char = $CA : GOSUB LCD_Command              ' Adressage au #11 de la Ligne2
      FOR Pdis = 0 TO 5
       READ (Msg2 + Pdis),Char : GOSUB LCD_Data ' Msg2 = "RAPIDE"
       'PAUSE 2*tempo
      NEXT
   ENDIF                           ' Fin du test Lent/Rapide
   Timing=0                        ' Raz du compeur Lent/Rapide
 ENDIF                             ' Fin du test cran stabilisé
ENDIF                              ' Fin de traitement compteur X
LOOP                             ' Fin de la boucle infinie (et pas de GoTo !!!)  ;))
END                                ' Fin syntaxique du programme principal

'<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<---


' |========================================================================================|
' |      ****************************** SUBROUTINES  *******************************       |
' |========================================================================================|

' Envoi d'une COMMANDE à l'afficheur

'ComLCD:
' LOW RS            ' Activation de la ligne de commande  (RS=0 : RW=Gnd)
' GOSUB ChrLCD      ' Envoi de la commande
' HIGH RS           ' Relachement de la ligne de commande (RS=1 : RW=Gnd)
' PAUSE 1           '  et passage en mode DATA Caractères
'RETURN

'-------------------------------------------------------------------------------------------
' Ecriture d'un CARACTERE dans l'afficheur en mode 4 bits (RS=1)

'ChrLCD:
' OUTA = Char >> 4  ' Sortie du Nibble UPPER de poids fort (Char=8bits)
' PULSOUT E,1       ' Ecriture du caractère (Top de 1x 80nsec sur Enable)
' OUTA = Char       ' Sortie du nibble LOWER de poids faible
' PULSOUT E,1       ' Ecriture du caractère (Top de 1x 80nsec sur Enable)
'RETURN

'-------------------------------------------------------------------------------------------
' idem que ci-dessus mais par Routine à 2 entrées possibles pour envoi d'une COMMANDE OU d'un DATA caractère

LCD_Command:
  LOW RS                 ' Activation de la ligne de commande  (RS=0 : RW=Gnd)
LCD_Data:
  LCDbus = Char.HIGHNIB  ' Sortie du Nibble de poids fort
  PULSOUT E, 1           ' Latch Enable (+ Increment automatique de la DDRAM)
  LCDbus = Char.LOWNIB   ' Sortie du Nibble de poids faible
  PULSOUT E, 1           ' Latch Enable (+ Increment automatique de la DDRAM)
  HIGH RS                ' Relachement de la ligne de commande (RS=1 : RW=Gnd)
  PAUSE 1                '  et passage en mode DATA Caractères
RETURN

'-------------------------------------------------------------------------------------------
'Calcul des "digits" à afficher individuellement

Calcul:                          ' Exemple avec lecture = 12345  //xx => // = MODULO (Reste de divison par xx)
  
Unite=     (Lecture)  //10      '  Reste de la division 12345 //10 = 5
  Dizaine=   (Lecture/10)//10     '  Reste de la division 1234 //10 = 4
  Centaine=  (Lecture/100)//10    '  Reste de la division 123 //10 = 3
  Millier=   (Lecture/1000)//10   '  Reste de la division 12 //10 = 2
  DixMillier=(Lecture/10000)//10  '  Reste de la division 1 //10 = 1
RETURN

'-------------------------------------------------------------------------------------------
'Affiche Compteur X, caractere par caractere

AffCptX:
  Char = $86           : GOSUB LCD_Command      ' Adressage au #07 de la L1
  Char = Unite+48      : GOSUB LCD_Data         ' Envoi de Unite de CompX

  Char = $85           : GOSUB LCD_Command      ' Adressage au #06 de la L1
  Char = Dizaine+48    : GOSUB LCD_Data         ' Envoi de Dizaine de ComptX

  Char = $84           : GOSUB LCD_Command      ' Adressage au #05 de la L1
  Char = Centaine+48   : GOSUB LCD_Data         ' Envoi de Centaine de ComptX

  Char = $83           : GOSUB LCD_Command      ' Adressage au #04 de la L1
  Char = Millier+48    : GOSUB LCD_Data         ' Envoi de Millier de ComptX

  Char = $82           : GOSUB LCD_Command      ' Adressage au #03 de la L1
  Char = DixMillier+48 : GOSUB LCD_Data         ' Envoi de DixMillier de ComptX
RETURN

'-------------------------------------------------------------------------------------------
'Affiche Compteur A, caractere par caractere

AffCptA:
  Char = $8F           : GOSUB LCD_Command      ' Adressage au #16 de la L1
  Char = Unite+48      : GOSUB LCD_Data         ' Envoi de Unite de CompA

  Char = $8E           : GOSUB LCD_Command      ' Adressage au #15 de la L1
  Char = Dizaine+48    : GOSUB LCD_Data         ' Envoi de Dizaine de ComptA

  Char = $8D           : GOSUB LCD_Command      ' Adressage au #14 de la L1
  Char = Centaine+48   : GOSUB LCD_Data         ' Envoi de Centaine de ComptA

  Char = $8C           : GOSUB LCD_Command      ' Adressage au #13 de la L1
  Char = Millier+48    : GOSUB LCD_Data         ' Envoi de Millier de ComptA

  Char = $8B           : GOSUB LCD_Command      ' Adressage au #12 de la L1
  Char = DixMillier+48 : GOSUB LCD_Data         ' Envoi de DixMillier de ComptA
RETURN

'-------------------------------------------------------------------------------------------
'Affiche Compteur B, caractere par caractere

AffCptB:
  Char = $C6           : GOSUB LCD_Command      ' Adressage au #7 de la L2
  Char = Unite+48      : GOSUB LCD_Data         ' Envoi de Unite de CompB

  Char = $C5           : GOSUB LCD_Command      ' Adressage au #06 de la L2
  Char = Dizaine+48    : GOSUB LCD_Data         ' Envoi de Dizaine de ComptB

  Char = $C4           : GOSUB LCD_Command      ' Adressage au #05 de la L2
  Char = Centaine+48   : GOSUB LCD_Data         ' Envoi de Centaine de ComptB

  Char = $C3           : GOSUB LCD_Command      ' Adressage au #04 de la L2
  Char = Millier+48    : GOSUB LCD_Data         ' Envoi de Millier de ComptB

  Char = $C2           : GOSUB LCD_Command      ' Adressage au #03 de la L2
  Char = DixMillier+48 : GOSUB LCD_Data         ' Envoi de DixMillier de ComptB
RETURN

'-------------------------------------------------------------------------------------------
'***************** FIN DE PROGRAMME ********************************************************
' __________________________________________________________________________________________

 

 

Ce programme a été concu en programmation structurée.

Vous remarquerez que le corps principal est très "propre" facile à lire et qu'il se résume à peu de chose car il fait appel à des Subroutines.

Ces sousroutines (aussi parfois appelées Fonctions) sont des petits programmes, ayant une porte d'entrée (un Label:) et une de sortie (Return).

Ces petits modules peuvent être copiés/collés dans divers programmes de votre composition.

Il est ainsi aisé de se constituer une petite bibliothèques de sousroutines universelles (protocole in/out i2C, gestion LCD, ...)

Une fois une subroutine effectuée, le programme continue sa progression là où il avait fait appel à cette subroutine.

Il continue proprement son déroulement, de haut en bas, jusqu'à la fin de la boucle infinie (LOOP) et recommence inlassablement au début (DO).

Cette manière de faire assure une bonne programmation sans créer des liens "spaghettis" qui conduisent souvent au plantage d'un programme.
Ces "liens spaghettis" sont toujours dus à l'usage d'instructions GoTo qui vous balancent d'un endroit à l'autre du programme principal sans
suivre une progression linéaire, du haut vers le bas, du déroulement de votre programme.

Il faut alors, difficilement, tenir compte de la capacité de votre µC à gérer ce nombre de "liens internes".

Une fois cette capacité de calcul dépassée ... le programme plante sans préavis et vous-vous demanderez généralement pourquoi !?

Et bien ... tout simplement parceque votre programme n'est pas "structuré" et que vous avez saturé votre µC !

L'instruction GoTo est donc à proscrire de vos programmes !

Prenez vite la très bonne habitude de vous en passer et d'utiliser des appels à des subroutines.

Vous remarquerez d'ailleurs que dans le programme écrit ci-dessus il n'y aucun GoTo !

 

 

 

 

 

   Trafic Visiteurs:  

 
[ Electronique ]
Copyright © Roger LEGAT - 2008 - Tous Droits réservés - (Thds V2)