Schema pour réaliser un Compteur Horaire


A quoi sert le montage?:
 Il sert à totaliser le nombre d'heures de fonctionnement d'une machine dans le but de gérer les opérations de maintenance (par exemple:vidange, nettoyage, ...).
Le fonctionnement:
 Le comptage va de "0000.0" à "9999.9" heures.Dès la mise sous tension, le comptage se déclenche. Pour garder en mémoire la durée écoée, on procède à un enregistrement toutes les 2 minutes. Par conséquent, lorsque le montage n'est pas alimenté, le comptage est arreté sur la dernière valeur enregistrée. Pour rectifiée l'erreur due à la mise en marche (et à l'arret), on donne une minute d'avance à chaque démarrage du comptage. (Cette minute sera compensée à l'arret.)
Description:
 L'alimentation typique est de 12V (régée ensuite à 5V), la consommation est de l'ordre de 100 mA.Le coeur du montage est un microcontrôleur PIC16F84. IL gère:< type="circle">L'affichage du nombre d'heures.L'enregistrement du nombre d'heures.Le cadencement du décompte (quartz 4MHz).Vous pouvez télécharger le schéma du montage en cliquant ici tout en appuyant sur la touche MAJUSCE.Voici le schéma du montage:
schema_compteur_horaire.gif (47936 octets) Les afficheurs sont de type anode commune.Le port A gère le mtiplexage et le port B pilote les segments des cinq afficheurs.La circuiterie de reset est particièrement conçue pour empêcher le PIC de fonctionner en dessous d'une tension trop faible.
Le programme:Le programme est réalisé pour un PIC16F84, il utilise les interruptions internes du PIC. Remarque importante sur le programme:
Le comptage réalisé par le PIC est en fait basé sur un décomptage: il décompte de 10 à 1. Quand un registre atteint la valeur 0, il est aussitôt réinitialisé à 10.
Pour faire apparaitre un comptage au lieu d'un décomptage, on utilise le sous programme "affiche" qui renvoi un 0 pour un 10, un 1 pour un 9, un 2 pour un 8, un 3 pour un 7, un 4 pour un 6, un 5 pour un 5, un 6 pour un 4, un 7 pour un 3, un 8 pour un   et un 9 pour un 1.
On obtient bien un comptage de 0 à 9 pour chaque registre.Voici le fonctionnement de la partie enregistrement sous forme de GRAFCET:

grafcet_compteur_horaire.gif (75499 octets) 

A première vue, le PIC doit juste compter en enregistrant le temps actuel dans sa memoire EEPROM. Il n'y aurait aucun problème si le protocole d'enregistrement n'éxigeait pas que l'on arrête les interruptions. Il est donc indispensable de stopper les interruptions internes à chaque enregistrement. Comme se sont les interruptions qui gèrent le comptage, on se trouve obligé de faire un compromis entre fréquence d'enregistrement et précision de l'horloge.
La précision totale du système dépend donc de nos choix: plus on enregistre souvent, plus la précision est bonne pour les transitions "marche-arrêt" et plus elle est mauvaise pour l'horloge du comptage elle même. Après réflexion, j'ai choisi d'enregistrer toutes les deux minutes.
Concrêtement, le PIC compte normalement pendant deux minutes au bout desquelles il s'arrête, enregistre et recommence à compter. On constate alors qu'il suffit de connaître le temps d'enregistrement et le tour est joué... On se reporte aussitôt à la fiche technique qui nous indique le temps typique d'enregistrement mais malheureusement ce temps peut fluctuer.
Revenons au programme en nous référant au GRAFCET ci-contre.
Tout d'abord, définissons les notations utilisées. Pour les étapes, les noms sont assez explicites; P1 et P2 correspondent aux parties de mémoire EEPROM utilisées par le PIC. Pour les transitions, "=1" signifie que la transition est validée, "test" est l'indicateur d'enregistrement, OK signifie que l'on attend que le transfert soit effectué et T est la temporisation de deux minutes.
Au démarrage, le PIC doit aller chercher la dernière valeur enregistrée. Considérons qu'il parvienne sans difficté dans la boucle. Lorsque T est valide (=1), on enregistre 0 dans test pour indiquer que l'on est en cours d'enregistrement dans le cas d'une coupure d'alimentation au moment de l'enregistrement. On enregistre alors P1, on remet test=1 et on enregistre P2.
Examinons le cas du démarrage. On commence par lire le bit test, si il est à 1, c'est que P1 est valable, on lit alors P1 et on transfert P1 dans P2 (au cas ou P2 serait nonvalable). on est alors sûr que P1 et P2 sont tous les deux valables. Si le bit test est à 0, P1 est non valable, on lit P2.
De cette manière, on remarque que même dans le cas le plus défavorable il reste toujours un emplacement valable (P1 ou P2). On note aussi que la première mise en marche du PIC exige que l'on ait déjà programmé les emplacements mémoire correspondant à P1 et P2 sur la valeur "0000,0". Il faut se reporter aux dernières lignes du programme pour voir comment on programme la mémoire EEPROM du PIC. Vous pouvez télécharger le programme compt_heure.ASM en cliquant ici tout en appuyant sur la touche MAJUSCE.Vous pouvez télécharger le fichier éxécutable compt_heure.HEX en cliquant ici tout en appuyant sur la touche MAJUSCE.Voici le programme:
;******************************************************************************************************
;montage compteur d'heure.
;24/09/2000
;programme de compteur d'heure
;
;Auteur: Raphael Bourdon
;******************************************************************************************************

    list p=16f84,f=inhx8m             ; Type de PIC et format de fichier
    __config    B'11111111110001'    ; pas de protection du code, timer au demarrage,
                        ; pas de chien de garde, oscillateur a quartz.
    #include "p16f84.inc"             ; Librairie pour le compilateur

;definition des variables
time1    equ    H'0C'
time2    equ    H'0D'
temp    equ    H'0E'
afficheur    equ    H'0F'
savstatus    equ    H'10'
dizieme    equ    H'11'
unite    equ    H'12'
dizaine    equ    H'13'
centaine    equ    H'14'
millier    equ    H'15'
temp1    equ    H'16'
time3    equ    H'17'
temp2    equ    H'18'

;definition des adresses memoires EEPROM
s_test    equ    D'0'             ;s_test indique l'etat de la sauvegarde
s_time3    equ    D'1'
s_dizieme    equ    D'2'
s_unite    equ    D'3'
s_dizaine    equ    D'4'
s_centaine    equ    D'5'
s_millier    equ    D'6'
ss_time3    equ    D'7'
ss_dizieme    equ    D'8'
ss_unite    equ    D'9'
ss_dizaine    equ    D'10'
ss_centaine    equ    D'11'
ss_millier    equ    D'12'
    org    0
    goto    debut

;------------------------------------------------------------------------------------------------------
    org    H'04'             ;INTERRUPTION

    movwf    temp             ;sauvegarde de W dans temp
    swapf    STATUS,0         ;sauvegarde de STATUS
    movwf    savstatus         ;dans savstatus
    bcf    STATUS,RP0         ;on passe dans la page memoire 0
    movlw D'06'             ;on initialise TMR0 a 6
    movwf TMR0
    bcf INTCON,T0IF        ;remise a 0 du bit T0IF (il est mis a 1 a chaque interruption)


    decfsz time1,1             ;time1 sert de diviseur par 250. On decompte qu'une
    goto    fininterrupt         ;interruption sur 250.
    movlw    D'250'             ;reinitialisation de time a 250.
    movwf    time1   

    decfsz time2,1             ;time2 sert de diviseur par 30.
    goto    fininterrupt         ;reinitialisation de time a 30.
    movlw    D'30'   
    movwf    time2

    bsf    temp2,0             ;temp2,0 permet l'enregistrement.
    decfsz time3,1             ;time3 sert de diviseur par 3. On decompte qu'une
    goto    fininterrupt         ;interruption sur 3.
    movlw    D'3'             ;reinitialisation de time a 3.
    movwf    time3

    decfsz    dizieme,1         ;decremente dizieme
    goto    fininterrupt

    movlw    H'0A'
    movwf    dizieme
    decfsz    unite,1             ;decremente unite
    goto    fininterrupt

    movlw    H'0A'
    movwf    unite
    decfsz    dizaine,1         ;decremente dizaine
    goto    fininterrupt        

    movlw    H'0A'
    movwf    dizaine
    decfsz    centaine,1         ;decremente centaine
    goto    fininterrupt

    movlw    H'0A'
    movwf    centaine
    decfsz    millier,1         ;decremente millier
    goto    fininterrupt

    movlw    H'0A'
    movwf    millier

fininterrupt
    swapf    savstatus,0         ; restauration de STATUS
    movwf    STATUS
    swapf    temp,1             ; restauration de W
    swapf    temp,0            
    retfie

;------------------------------------------------------------------------------------------------------
debut    ; Initialisation

    movlw    H'01'
    movwf    PCLATH

    movlw    D'250'             ; initialisation de time1 a 250
    movwf    time1

    movlw    D'15'             ; initialisation de time2 a 15
    movwf    time2             ;on donne une minute d'avance au demarrage

    movlw    D'3'             ; initialisation de time3 a 3
    movwf    time3


    clrf    afficheur
    bsf    afficheur,4         ;initialisation de afficheur

    clrf    temp2   

;on initialise les registres sauvegardes dans l'EEPROM

    movlw    s_test             ;lecture de s_test
    call    lecture
    btfss    EEDATA,0         ;test sur s_test,0
    goto    sauvegarde         ;si s_test,0 = 1, s_* registres -> * registres

    movlw    s_time3
    call    lecture
    movwf    time3

    movlw    s_dizieme
    call    lecture
    movwf    dizieme

    movlw    s_unite
    call    lecture
    movwf    unite

    movlw    s_dizaine
    call    lecture
    movwf    dizaine

    movlw    s_centaine
    call    lecture
    movwf    centaine

    movlw    s_millier
    call    lecture
    movwf    millier

;enregistrement de secour        * registres -> s_* registres
    movlw    ss_time3
    movwf    EEADR
    movf    time3,0
    movwf    EEDATA
    call    ecriture

    movlw    ss_dizieme
    movwf    EEADR
    movf    dizieme,0
    movwf    EEDATA
    call    ecriture

    movlw    ss_unite
    movwf    EEADR
    movf    unite,0
    movwf    EEDATA
    call    ecriture

    movlw    ss_dizaine
    movwf    EEADR
    movf    dizaine,0
    movwf    EEDATA
    call    ecriture

    movlw    ss_centaine
    movwf    EEADR
    movf    centaine,0
    movwf    EEDATA
    call    ecriture

    movlw    ss_millier
    movwf    EEADR
    movf    millier,0
    movwf    EEDATA
    call    ecriture

    goto    fin_init

sauvegarde                 ;si s_test = 0, ss_* registres -> * registres
    movlw    ss_time3
    call    lecture
    movwf    time3

    movlw    ss_dizieme
    call    lecture
    movwf    dizieme

    movlw    ss_unite
    call    lecture
    movwf    unite

    movlw    ss_dizaine
    call    lecture
    movwf    dizaine

    movlw    ss_centaine
    call    lecture
    movwf    centaine

    movlw    ss_millier
    call    lecture
    movwf    millier

fin_init


; Configuration de l'interruption et des ports A et B
    bsf    STATUS,RP0         ; selection de la page memoire n1

    movlw    B'10000101'         ; On configure le prediviseur
    movwf    OPTION_REG         ; interruption toutes les 64 instructions

    movlw    B'10000000'         ;les pattes 0/6 du port
    movwf    TRISB             ;B en sorties

    clrf    TRISA             ; Tout le port A en sortie

    bcf    STATUS,RP0         ; on repasse dans la page memoire 0

    clrf    PORTA             ; on met le port A a zero
    comf    PORTA,1

    clrf    PORTB             ; on met le port B a zero

    movlw    B'10100000'         ; on va configurer les interruptions
    movwf    INTCON

;------------------------------------------------------------------------------------------------------
boucle                    
    bcf    STATUS,C         ;remise a zero de la retenue
    rrf    afficheur,1         ;puis on fait tourner le bit de afficheur
    movf    afficheur,1         ;afficheur-> afficheur
    btfsc    STATUS,Z         ;si afficheur vaut zero
    bsf    afficheur,4
       
    btfsc    afficheur,0         ;si le bit 0 de afficheur vaut 1
    movf    millier,0         ;on met millier dans W
    btfsc    afficheur,1         ;si le bit 1 de afficheur vaut 1
    movf    centaine,0         ;on met centaine dans W
    btfsc    afficheur,2         ;si le bit 2 de afficheur vaut 1
    movf    dizaine,0         ;on met dizaine dans W
    btfsc    afficheur,3         ;si le bit 3 de afficheur vaut 1
    movf    unite,0             ;on met unite dans W
    btfsc    afficheur,4         ;si le bit 4 de afficheur vaut 1
    movf    dizieme,0         ;on met dizieme dans W

    call    affiche
    movwf    PORTB

    comf    afficheur,0         ;on complemente afficheur, on met le restat dans W
    movwf    PORTA             ;W -> portA
       
    call    tempo             ;la tempo sert a ralentir la vitesse sur les ports A et B
   
    btfss    temp2,0             ;on teste l'indicateur d'enregistrement temp2,0
    goto    boucle             ;si temp2,0 = 0 on retourne a boucle
    bcf    temp2,0             ;temp2,0 = 0

;inserer l'enregistrement a cet endroit
    movlw    H'FF'             ;on coupe l'affichage
    movwf    PORTA

    movlw    s_test             ;on enregistre 0 dans s_test
    movwf    EEADR
    clrf    EEDATA
    bcf    INTCON,GIE
    call    ecriture

    movlw    s_time3             ;* registres -> s_* registres
    movwf    EEADR
    movf    time3,0
    movwf    EEDATA
    call    ecriture

    movlw    s_dizieme
    movwf    EEADR
    movf    dizieme,0
    movwf    EEDATA
    call    ecriture

    movlw    s_unite
    movwf    EEADR
    movf    unite,0
    movwf    EEDATA
    call    ecriture

    movlw    s_dizaine
    movwf    EEADR
    movf    dizaine,0
    movwf    EEDATA
    call    ecriture

    movlw    s_centaine
    movwf    EEADR
    movf    centaine,0
    movwf    EEDATA
    call    ecriture

    movlw    s_millier
    movwf    EEADR
    movf    millier,0
    movwf    EEDATA
    call    ecriture

valide
    movlw    s_test             ;on enregistre 1 dans s-test
    movwf    EEADR
    clrf    EEDATA
    comf    EEDATA,1
    bcf    INTCON,GIE
    call    ecriture

    bsf    STATUS,RP0         ;on verifie que s_test = 1
    bsf    EECON1,RD         ;sinon on va a valide
    bcf    STATUS,RP0
    btfss    EEDATA,0
    goto    valide

;enregistrement de secour
    movlw    ss_time3         ;* registres -> ss_* registres
    movwf    EEADR
    movf    time3,0
    movwf    EEDATA
    call    ecriture

    movlw    ss_dizieme
    movwf    EEADR
    movf    dizieme,0
    movwf    EEDATA
    call    ecriture

    movlw    ss_unite
    movwf    EEADR
    movf    unite,0
    movwf    EEDATA
    call    ecriture

    movlw    ss_dizaine
    movwf    EEADR
    movf    dizaine,0
    movwf    EEDATA
    call    ecriture

    movlw    ss_centaine
    movwf    EEADR
    movf    centaine,0
    movwf    EEDATA
    call    ecriture

    movlw    ss_millier
    movwf    EEADR
    movf    millier,0
    movwf    EEDATA
    call    ecriture

    movlw    D'241'             ;compense le retard du a l'enregistrement
    movwf    time1

    comf    afficheur,0         ;on remet en marche l'affichage
    movwf    PORTA
    bsf    INTCON,GIE         ;reactive les interruptions
    goto    boucle

;------------------------------------------------------------------------------------------------------
;sous-programmes

lecture
    movwf    EEADR
    bsf    STATUS,RP0
    bsf    EECON1,RD
    bcf    STATUS,RP0
    movf    EEDATA,W
    return

ecriture
    bsf    STATUS,RP0
    clrf    EECON1
    bsf    EECON1,WREN
    movlw    H'55'
    movwf    EECON2
    movlw    H'AA'
    movwf    EECON2
    bsf    EECON1,WR
fin_ecriture
    btfsc    EECON1,WR
    goto    fin_ecriture
    bcf    STATUS,RP0
    bcf    temp2,0
    return

tempo
    decfsz    temp1,1
    goto    tempo
    return

affiche
    addwf    PCL,1             ;on charge le registre PCL par la
    nop                 ;valeur qu'il contient plus la valeur       
   
    retlw    b'01101111'
    retlw    b'01111111'         ;de W
    retlw    b'00000111'         ;On se deplace ainsi a l'adresse:    
    retlw    b'01111101'         ;adresse de 'addwf PCL,1' + W
    retlw    b'01101101'         ;il faut intercaler une instruction nop
    retlw    b'01100110'         ;car W varie de 0 à 9 Enfin, on
    retlw    b'01001111'         ;retourne dans W la valeur a afficher
    retlw    b'01011011'
    retlw    b'00000110'
    retlw    b'00111111'

;definition des contenus des registres de sauvegarde pour initialiser l'EEPROM a la premiere
;utilisation du montage
;le comptage demarre ainsi a "0000,0" apres la programmation du PIC
    org    H'2100'
    de     H'FF',H'03',H'0A',H'0A',H'0A',H'0A',H'0A',H'03',H'0A',H'0A',H'0A',H'0A',H'0A'

    end
Realisation:


typon_compteur_horaire.gif (34191 octets)

Voici l'implantation des composants et le typon du circuit :
Il faut cabler les deux circuits imprimés perpendicairement. C'est à cause du manque de place que les résistances ne sont pas sur le circuit mais soudées entre les deux parties. Pour établir les autres contacts entre les deux circuits vous devez souder des queues de résistances. Le montage est prévu pour un boitier TEKO metallique de 40x40x70 (constitué de deux parties vissées).
Les afficheurs sont des HDSP-F101 (Hewlett Packard), on peut les remplacer par des afficheurs ayant des caractéristiques équivalentes: même boitier, courant nominal de 5mA et anode commune.
Voici des photos de la réalisation:

Le montage vu de dessus:
photo_compteur_heure2.jpg (20568 octets)
Le compteur en marche:

photo_compteur_heure1.jpg (19295 octets)





  • Vous devez telecharger le typon en cliquant ici tout en appuyant sur la touche MAJUSCE.
    Je rappelle qu'il faut telecharger le logiciel ARES Lite qui est gratuit. Il est disponible sur le site suivant: http://www.mtipower-fr.com
    ~ Ouvrez le logiciel ARES Lite
    ~ Cliquez sur File, puis sur Import Region.








  • Essais:

    Lorsque vous branchez le montage:  IL doit aussitôt afficher "0000,0".
    En marche continue, j'ai mesuré une erreur de 1 seconde sur 24 heures (sans arrêt du montage).
    Le clignotement bref toutes les deux minutes et normal, il correspond à l'enregistrement.

    Aucun commentaire:

    Enregistrer un commentaire