Petit robot balladeur n'aimant pas les balles de ping pong
Ce robot a été conçu à
l'origine pour participer au concours organisé
annuellement par le magazine Electronique Pratique. Il utilise 2 moteurs pas à pas
réductés commandés par un PIC 16F84, via des
interrupteurs statiques de puissance BSP75 protégés
contre les surcharges, court-circuits, surtensions,
etc... Le robot connait la position de 5 balles centrales, il les envoie dans les buts adverses, puis rentre obstruer ses propres buts. La position de départ (cruciale) est donnée au moyen d'un gabarit amovible en dépron. |
Schéma théorique
Liste des composants
BILL OF MATERIALS Design: C:\TRAVAIL\ROBOT\SCHEMA.IDS Doc. no.: <NONE> Revision: <NONE> Author: dB Created: 25-Nov-01 Modified: 25-Nov-01 Modules ------- 1 bouton poussoir M/A Resistors --------- 11 R1,R3,R4,R5,R6,R7,R8,R9,R10,R11, 1k R12 1 R2 22 Capacitors ---------- 1 C1 470 mic 1 C2 100n Integrated Circuits ------------------- 1 U1 PIC16F84 Transistors ----------- 8 Q1,Q2,Q3,Q4,Q5,Q6,Q7,Q8 BSP75 Diodes ------ 1 D1 Zéner 4.7V Miscellaneous ------------- 1 X1 Reso 4MHz
Détail de la catapulte
Allure du typon (le circuit imprimé sert de chassis)
Schéma d'implantation
Les dessous de l'affaire
Fichier source du PIC
;----------------------------------------------------------------------------------------------- ; Code source pour robot piloté par PIC ; dB ; PIC16F84 ; Résonnateur 4 MHz ; ; 10/25/2001 ;----------------------------------------------------------------------------------------------- ; ; Garde au sol Arrête milieu terrain : hauteur 7 cm pour 80 cm horizontaux ; Le robot a une voie de 20 cm environ soit 10 cm entre roue et milieu du robot ; soit une garde au sol mini de h = 7 * (10 /80) = env 0.9 cm ; En pratique on prend 1.5 cm mini ; ; Roues Diamètre extérieur 38 mm, moyeu diamètre 15 mm ; Epaisseur jante 3 mm et moyeu 7 mm soit total 10 mm ; Pneu en gaine thermo rétractable ; Moto réducteurs 200 1/2 pas par tour, soit 100 pas ; roue 38 mm soit environ 1.2 mm / pas moteur ; ; Servo pulses: recul 0.75 ms soit Pulser = 8 ; prêt 2.00 ms soit Pulser = 216 ; tir 2.20 ms soit Pulser = 250 ; ; Micro 16F84 E/S 25 mA ; 1024 mots ROM 68 octets RAM 64 octets EEPROM ; ; RA2 [ ° ]RA1 ; RA3 [ ]RA0 ; RA4 [ ]Osc ; MCLR/[ ]Osc ; Gnd [ ]+Vcc ; RB0 [ ]RB7 ; RB1 [ ]RB6 ; RB2 [ ]RB5 ; RB3 [ ]RB4 ; ; Terrain 10 ; 13 9 3 ; 8 ; Vilain 12 7 2 Home ; 6 ; 11 5 1 ; 4 Départ ; ; Stratégie Envoyer dans l'ordre 5, 6, 7, 8, 9 puis pousser 3, 2, 1 ; Revenir au milieu buts perso, obstruer et tirs périodiques ; ; Déplacements Lecture octet mouvement, recopie registre trav1 et trav2 ; Routines mouvement et tir ; Mouvement: si flag collision = 0 (pas de collision): ; mouvement donné par trav1 ; à chaque pas robot (*) on décrémente trav1 jusqu'à 0 ; (*) un pas robot = 16 pas moteur ; ; si flag collision = 1 (il y a eu collision) ; mouvement complémentaire trav1 ; on incrémente trav1 à chaque pas robot jusqu'à trav2 ; puis on rabaisse le drapeau et on recommence l'étape interrompue ; ; avance 00 droite 01 gauche 10 arrière 11 ; ; nb pas robot = distance (mm) * 16 / 375 ; ; nb pas robot = angle (°) * 16 / 265 ; ; Brouillon Prévoir outil alignement départ ; Positions servo: 0.75 ms 2 ms 2.2 ms ; recul prêt tir ; Arrêt auto après 3 min ERRORLEVEL -302 ; Turn off bank bits warning ; PORTA ; RA0 <- capteur choc AVD ; RA1 <- bouton départ ; RA2 <- capteur choc AVG ; RA3 -> Pulses commande servo ; RA4 -> NC ; PORTB ; RB0 -> phase 1 moteur gauche ; RB1 -> phase 2 moteur gauche ; RB2 -> phase 3 moteur gauche ; RB3 -> phase 4 moteur gauche ; RB4 -> phase 1 moteur droit ; RB5 -> phase 2 moteur droit ; RB6 -> phase 3 moteur droit ; RB7 -> phase 4 moteur droit ; Variables CopieA equ H'0C' ; copie port A Pulser equ H'0D' ; pulse servo: temps = 0.7 ms + (Pulser * 6 µs) Minipa equ H'0E' ; décompteur pour n pas moteur pour 1 pas robot Etape equ H'0F' ; numéro du déplacement en cours Drapo equ H'10' ; 8 drapeaux ; b0 mémoire état bouton ; b1 1 = un des capteurs a été enfoncé ; b2 1 = marche robot 0 = arrêt robot ; b3 1 = étape en cours (0 = il faut changer d'étape) ; b4 NU ; b5 NU ; b6 NU ; b7 NU Trav1 equ H'11' ; 1er octet de travail (recopie mouvement) Trav2 equ H'12' ; 1er octet de travail (recopie mouvement) ; Structure: b7 0 = moteur gauche en avant, 1 = AR ; b6 0 = moteur droit en avant, 1 = AR ; b5 0 = avance fictive (tempo) 1 = réel ; b4 \ ; b3 \ nombre de pas robot sur 5 bits ; b2 / soit 32 pas maxi. Un pas robot ; b1 / = 16 pas moteur soit environ 24 mm ; b0 / Brouil equ H'13' ; brouillon ; Preprocessor Directives ; Using 16F84 processor, generating an Intel HEX file, using DECimal ; radix LIST P=16F84, F=INHX8M, R=DEC INCLUDE P16F84.INC ; Code protection OFF, High Speed oscillator, Watch Dog Timer OFF, ; and power-up timer ON __CONFIG _CP_OFF & _HS_OSC & _WDT_OFF & _PWRTE_ON ;----------------------------------------------------------------------------------------------- org 0x00 ; Vecteur Reset goto reset org 0x04 ; Vecteur Interruption retfie ;----------------------------------------------------------------------------------------------- reset bcf STATUS,RP0 ; travail sur bank 0 CLRF PORTA ; RAZ latches sorties port A bsf STATUS,RP0 ; travail sur bank 1 movlw B'00000111' ; A0..A2 entrée et A3 A4 sortie movwf TRISA bcf STATUS,RP0 ; travail sur bank 0 clrf PORTB ; RAZ latches sorties port A bsf STATUS,RP0 ; travail sur bank 1 clrf TRISB ; B0..B72 en sortie movlw B'00000000' bsf STATUS,RP0 ; travail sur bank 1 movwf OPTION_REG ; Timer sur horloge interne ;----------------------------------------------------------------------------------------------- principal call lecture ; recopie du portA dans CopieA call bouton ; gestion du bouton poussoir call capteur ; gestion des détecteurs chocs call etapes ; gestion étapes et mise à jour registres travail call mouvem ; mouvement dans une étape call servo ; gestion du servo goto principal ;---------------------------------------- lecture ---------------------------------------------- lecture bcf STATUS,RP0 ; bank 0 movfw PORTA movwf CopieA return ;--------------------------- bouton poussoir (fronts) ------------------------------------------ bouton btfss CopieA,1 ; si bouton enfoncé on saute goto bou01 ; sinon on va en bou01 btfsc Drapo,0 ; si mémoire bouton à 0 on saute goto bou02 ; sinon on sort bsf Drapo,0 ; on met mémoire bouton à 1 btfss Drapo,2 ; si le robot est en marche on saute goto bou00 ; sinon on va en bou00 bcf Drapo,2 ; on arrête le robot clrf Etape ; on remet l'étape 0 bcf Drapo,3 ; on quitte l'étape en cours goto bou02 ; on sort bou00 clrf CopieA clrf Pulser clrf Minipa clrf Etape clrf Drapo clrf Trav1 clrf Trav2 clrf Brouil call posdep ; tempo 1s avant démarrage bsf Drapo,2 ; on met le robot en marche goto bou02 ; puis on sort bou01 bcf Drapo,0 ; on remet mémoire bouton à 0 bou02 return ; on sort ;--------------------------------- détection chocs (flag état) --------------------------------- capteur btfsc CopieA,0 ; si capteur droit non enfoncé on saute bsf Drapo,1 ; on arme le flag capteur btfsc CopieA,2 ; si capteur gauche enfoncé on saute bsf Drapo,1 ; on arme le flag capteur Capd01 return ; on sort ;-------------------------------- succession des etapes ---------------------------------------- etapes btfss Drapo,2 ; si robot arrêté goto eta50 ; alors on sort btfsc Drapo,3 ; si pas d'étape en cours on saute pour changer d'étape goto eta50 ; si déja une étape en cours alors on sort bsf Drapo,3 ; on arme le drapeau (pour activer prochaine étape) eta00 movlw D'0' ; on charge une constante subwf Etape,W ; et on compare au numéro de l'étape en cours btfss STATUS,Z ; si égalité on saute goto eta01 ; sinon test suivant movlw B'10100100' ; on recopie code premier mouvement movwf Trav1 ; dans le registre Trav1 movlw D'8' ; Positionnement servo movwf Pulser goto eta49 ; et passage à la suite eta01 movlw D'1' ; etc etc etc ... subwf Etape,W btfss STATUS,Z goto eta02 movlw B'00110000' movwf Trav1 goto eta49 eta02 movlw D'2' subwf Etape,W btfss STATUS,Z goto eta03 movlw B'00110000' movwf Trav1 movlw D'216' movwf Pulser goto eta49 eta03 movlw D'3' subwf Etape,W btfss STATUS,Z goto eta04 movlw B'00100100' movwf Trav1 goto eta49 eta04 movlw D'4' subwf Etape,W btfss STATUS,Z goto eta05 movlw B'00100011' movwf Trav1 movlw D'250' movwf Pulser goto eta49 eta05 movlw D'5' subwf Etape,W btfss STATUS,Z goto eta06 movlw B'00000100' movwf Trav1 movlw D'8' movwf Pulser goto eta49 eta06 movlw D'6' subwf Etape,W btfss STATUS,Z goto eta07 movlw B'01101000' movwf Trav1 goto eta49 eta07 movlw D'7' subwf Etape,W btfss STATUS,Z goto eta08 movlw B'00101101' movwf Trav1 movlw D'216' movwf Pulser goto eta49 eta08 movlw D'8' subwf Etape,W btfss STATUS,Z goto eta09 movlw B'10101000' movwf Trav1 goto eta49 eta09 movlw D'9' subwf Etape,W btfss STATUS,Z goto eta10 movlw B'00101001' movwf Trav1 goto eta49 eta10 movlw D'10' subwf Etape,W btfss STATUS,Z goto eta11 movlw B'00100011' movwf Trav1 movlw D'250' movwf Pulser goto eta49 eta11 movlw D'11' subwf Etape,W btfss STATUS,Z goto eta12 movlw B'00000100' movwf Trav1 movlw D'8' movwf Pulser goto eta49 eta12 movlw D'12' subwf Etape,W btfss STATUS,Z goto eta13 movlw B'01100111' movwf Trav1 goto eta49 eta13 movlw D'13' subwf Etape,W btfss STATUS,Z goto eta14 movlw B'00101110' movwf Trav1 movlw D'216' movwf Pulser goto eta49 eta14 movlw D'14' subwf Etape,W btfss STATUS,Z goto eta15 movlw B'10101000' movwf Trav1 goto eta49 eta15 movlw D'15' subwf Etape,W btfss STATUS,Z goto eta16 movlw B'00100111' movwf Trav1 goto eta49 eta16 movlw D'16' subwf Etape,W btfss STATUS,Z goto eta17 movlw B'00100011' movwf Trav1 movlw D'250' movwf Pulser goto eta49 eta17 movlw D'17' subwf Etape,W btfss STATUS,Z goto eta18 movlw B'00000100' movwf Trav1 movlw D'8' movwf Pulser goto eta49 eta18 movlw D'18' subwf Etape,W btfss STATUS,Z goto eta19 movlw B'01101000' movwf Trav1 goto eta49 eta19 movlw D'19' subwf Etape,W btfss STATUS,Z goto eta20 movlw B'00101111' movwf Trav1 movlw D'216' movwf Pulser goto eta49 eta20 movlw D'20' subwf Etape,W btfss STATUS,Z goto eta21 movlw B'10101000' movwf Trav1 goto eta49 eta21 movlw D'21' subwf Etape,W btfss STATUS,Z goto eta22 movlw B'00100111' movwf Trav1 goto eta49 eta22 movlw D'22' subwf Etape,W btfss STATUS,Z goto eta23 movlw B'00100011' movwf Trav1 movlw D'250' movwf Pulser goto eta49 eta23 movlw D'23' subwf Etape,W btfss STATUS,Z goto eta24 movlw B'00000100' movwf Trav1 movlw D'8' movwf Pulser goto eta49 eta24 movlw D'24' subwf Etape,W btfss STATUS,Z goto eta25 movlw B'01101000' movwf Trav1 goto eta49 eta25 movlw D'25' subwf Etape,W btfss STATUS,Z goto eta26 movlw B'00110010' movwf Trav1 movlw D'216' movwf Pulser goto eta49 eta26 movlw D'26' subwf Etape,W btfss STATUS,Z goto eta27 movlw B'10101001' movwf Trav1 goto eta49 eta27 movlw D'27' subwf Etape,W btfss STATUS,Z goto eta28 movlw B'00101011' movwf Trav1 goto eta49 eta28 movlw D'28' subwf Etape,W btfss STATUS,Z goto eta29 movlw B'00100011' movwf Trav1 movlw D'250' movwf Pulser goto eta49 eta29 movlw D'29' subwf Etape,W btfss STATUS,Z goto eta30 movlw B'00000100' movwf Trav1 movlw D'8' movwf Pulser goto eta49 eta30 movlw D'30' subwf Etape,W btfss STATUS,Z goto eta31 movlw B'10101010' movwf Trav1 movlw D'8' movwf Pulser goto eta49 eta31 movlw D'31' subwf Etape,W btfss STATUS,Z goto eta32 movlw B'00000001' ; 1 coup pour rien movwf Trav1 goto eta49 eta32 movlw D'32' subwf Etape,W btfss STATUS,Z goto eta33 movlw B'00110000' movwf Trav1 goto eta49 eta33 movlw D'33' subwf Etape,W btfss STATUS,Z goto eta34 movlw B'00110000' movwf Trav1 goto eta49 eta34 movlw D'34' subwf Etape,W btfss STATUS,Z goto eta35 movlw B'00101000' movwf Trav1 goto eta49 eta35 movlw D'35' subwf Etape,W btfss STATUS,Z goto eta36 movlw B'01100101' movwf Trav1 goto eta49 eta36 movlw D'36' subwf Etape,W btfss STATUS,Z goto eta37 movlw B'00110000' movwf Trav1 goto eta49 eta37 movlw D'37' subwf Etape,W btfss STATUS,Z goto eta38 movlw B'00110000' movwf Trav1 goto eta49 eta38 movlw D'38' subwf Etape,W btfss STATUS,Z goto eta39 movlw B'00101000' movwf Trav1 goto eta49 eta39 movlw D'39' subwf Etape,W btfss STATUS,Z goto eta40 movlw B'10101010' movwf Trav1 goto eta49 eta40 movlw D'40' subwf Etape,W btfss STATUS,Z goto eta41 movlw B'00000001' ; 1 coup pour rien movwf Trav1 goto eta49 eta41 movlw D'41' subwf Etape,W btfss STATUS,Z goto eta42 movlw B'00110000' movwf Trav1 movlw D'216' movwf Pulser goto eta49 eta42 movlw D'42' subwf Etape,W btfss STATUS,Z goto eta43 movlw B'00100100' movwf Trav1 goto eta49 eta43 movlw D'43' subwf Etape,W btfss STATUS,Z goto eta44 movlw B'10100101' movwf Trav1 goto eta49 eta44 movlw D'44' subwf Etape,W btfss STATUS,Z goto eta48 movlw B'00000100' movwf Trav1 movlw D'250' movwf Pulser goto eta49 eta48 bcf Drapo,2 ; on arrête le robot clrf Etape ; on remet l'étape 0 bcf Drapo,3 ; on quitte l'étape en cours goto eta50 ; on sort eta49 movfw Trav1 movwf Trav2 incf Etape,F ; on prépare l'étape suivante eta50 return ;-------------------------------- mouvements dans une étape ------------------------------------ mouvem btfss Drapo,2 ; si robot en marche on saute goto mou09 ; sinon on sort btfss Trav1,7 ; si bit 7 code mouvement = 1 (mot gauche en AR) on saute goto mou00 ; sinon (mot gauche en AV) on va en mou00 btfss Trav1,6 ; si bit 6 code mouvement = 1 (mot droit en AR) on saute goto mou02 ; sinon (mot droit en AV) on va en mou02 call recul ; on appelle routine recul (chocs non gérés en AR) goto mou06 ; et ensuite on sort mou00 btfss Trav1,6 ; si bit 6 code mouvement = 1 (mot droit en AR) on saute goto mou04 ; sinon (mot droit en AV) on va en mou02 btfsc Drapo,1 ; si pas de collision on saute goto mou01 call droite ; on appelle routine tourne à droite goto mou06 ; et ensuite on sort mou01 call gauche ; suite collision, on revient à gauche ald droite goto mou06 mou02 btfsc Drapo,1 ; si pas de collision on saute goto mou03 call gauche ; on appelle routine tourne à gauche goto mou06 mou03 call droite ; suite collision, on revient à droite ald gauche goto mou06 mou04 btfsc Drapo,1 ; si pas de collision on saute goto mou05 call avance ; on appelle routine avance goto mou06 mou05 call recul ; suite collision, on recule ald d'avancer mou06 btfsc Drapo,1 ; si pas de collision on saute goto mou07 ; sinon on va en mou07 movlw B'00011111' ; dans l'octet code andwf Trav1,W ; on regarde valeur déplacement seul btfsc STATUS,Z ; si différent de zéro on saute goto mou08 ; sinon fin déplacement decf Trav1,F ; on décrémente Trav1 goto mou09 ; et on sort mou07 movfw Trav2 ; et on compare subwf Trav1,W ; Trav1 et Trav2 btfsc STATUS,Z ; si pas égaux on saute goto mou08 ; sinon fin déplacement incf Trav1,F goto mou09 mou08 bcf Drapo,3 ; étape finie: on baisse drapeau étape en cours btfsc Drapo,1 ; si pas de collision on saute decf Etape,F ; si collision on décrémente Etape bcf Drapo,1 ; on baisse drapeau inversion mou09 return ;----------------------------------------- servo ----------------------------------------------- servo btfss Drapo,2 ; si robot arrêté goto ser00 ; alors on sort bsf CopieA,3 ; à mettre en remarque pour essais sans bruit !!! movfw CopieA ; idem bcf STATUS,RP0 ; bank 0 movwf PORTA call delser bcf CopieA,3 movfw CopieA bcf STATUS,RP0 ; bank 0 movwf PORTA ser00 return ;---------------------------------------- avance ---------------------------------------------- avance movlw D'9' movwf Minipa btfss Trav1,5 ; si avance réelle on saute goto ava01 ; si avance fictive on va en ava01 ava00 movlw B'00011000' bcf STATUS,RP0 ; bank 0 movwf PORTB call delbob movlw B'00100100' bcf STATUS,RP0 ; bank 0 movwf PORTB call delbob movlw B'01000010' bcf STATUS,RP0 ; bank 0 movwf PORTB call delbob movlw B'10000001' bcf STATUS,RP0 ; bank 0 movwf PORTB call delbob decfsz Minipa,F goto ava00 movlw B'00000000' ; économiser les accus ! bcf STATUS,RP0 ; bank 0 movwf PORTB ; (on éteind la lumière en sortant) goto ava02 ava01 call surpl ava02 return ;---------------------------------------- recul ---------------------------------------------- recul movlw D'9' movwf Minipa btfss Trav1,5 goto rec01 rec00 movlw B'10000001' bcf STATUS,RP0 ; bank 0 movwf PORTB call delbob movlw B'01000010' bcf STATUS,RP0 ; bank 0 movwf PORTB call delbob movlw B'00100100' bcf STATUS,RP0 ; bank 0 movwf PORTB call delbob movlw B'00011000' bcf STATUS,RP0 ; bank 0 movwf PORTB call delbob decfsz Minipa,F goto rec00 movlw B'00000000' ; économiser les accus ! bcf STATUS,RP0 ; bank 0 movwf PORTB ; (on éteind la lumière en sortant) goto rec02 rec01 call surpl rec02 return ;----------------------------------- tourne à gauche ------------------------------------------- gauche movlw D'9' movwf Minipa btfss Trav1,5 goto gau01 gau00 movlw B'00010001' bcf STATUS,RP0 ; bank 0 movwf PORTB call delbob movlw B'00100010' bcf STATUS,RP0 ; bank 0 movwf PORTB call delbob movlw B'01000100' bcf STATUS,RP0 ; bank 0 movwf PORTB call delbob movlw B'10001000' bcf STATUS,RP0 ; bank 0 movwf PORTB call delbob decfsz Minipa,F goto gau00 movlw B'00000000' ; économiser les accus ! bcf STATUS,RP0 ; bank 0 movwf PORTB ; (on éteind la lumière en sortant) goto gau02 gau01 call surpl gau02 return ;-------------------------------- tourne à droite ---------------------------------------------- droite movlw D'9' movwf Minipa btfss Trav1,5 goto dro01 dro00 movlw B'10001000' bcf STATUS,RP0 ; bank 0 movwf PORTB call delbob movlw B'01000100' bcf STATUS,RP0 ; bank 0 movwf PORTB call delbob movlw B'00100010' bcf STATUS,RP0 ; bank 0 movwf PORTB call delbob movlw B'00010001' bcf STATUS,RP0 ; bank 0 movwf PORTB call delbob decfsz Minipa,F goto dro00 movlw B'00000000' ; économiser les accus ! bcf STATUS,RP0 ; bank 0 movwf PORTB ; (on éteind la lumière en sortant) goto dro02 dro01 call surpl dro02 return ;-------------------------------------- délais servo ------------------------------------------- ; 6 cycles par boucle, horloge 4 MHz, division ; par 4, soit 1 µs par cycle, soit 6 µs par boucle delser movfw Pulser movwf Brouil del00 nop ; 1 cycle perdu ! nop ; 1 cycle perdu ! nop ; 1 cycle perdu ! decfsz Brouil,F ; décrément Brouil goto del00 ; si Brouil <> 0 on boucle sinon suite movlw D'117' ; et on recharge à 117 pour movwf Brouil ; rajouter une constante de 117 * 6 µs = 0.702 ms del01 nop ; 1 cycle perdu ! nop ; 1 cycle perdu ! nop ; 1 cycle perdu ! decfsz Brouil,F goto del01 return ;-------------------------------------- délais bobines ----------------------------------------- ; 6 cycles par boucle, horloge 4 MHz, division ; par 4, soit 1 µs par cycle, soit 6 µs par boucle delbob movlw D'255' ; on charge à 255 pour movwf Brouil ; obtenir une constante de 255 * 6 µs = 1.53 ms delb00 nop ; 1 cycle perdu ! nop ; 1 cycle perdu ! nop ; 1 cycle perdu ! decfsz Brouil,F ; décrément Brouil goto delb00 ; si Brouil <> 0 on boucle sinon suite movlw D'255' ; et on recommence movwf Brouil ; soit encore 1.53 ms delb01 nop ; 1 cycle perdu ! nop ; 1 cycle perdu ! nop ; 1 cycle perdu ! decfsz Brouil,F goto delb01 movlw D'255' ; et encore un coup avec 255 movwf Brouil ; pour obtenir 255 * 6 = 1.53 ms delb02 nop ; 1 cycle perdu ! nop ; 1 cycle perdu ! nop ; 1 cycle perdu ! decfsz Brouil,F goto delb02 ; soit un total de 3 * 1.53 = 4.59 ms return ;---------------------------------------- surplace --------------------------------------------- surpl call delbob call delbob call delbob call delbob decfsz Minipa,F goto surpl return ;------------------------------------- pause départ -------------------------------------------- posdep movlw D'150' movwf Minipa pos00 call delbob decfsz Minipa,F goto pos00 return ;--------------------------------------------- fin --------------------------------------------- end ;-----------------------------------------------------------------------------------------------