Réalisez un "Compteur Horaire"
Je ne peux en aucun cas être tenu pour responsable en cas d'accident ou autre.
A quoi sert le montage?:
Le fonctionnement:
Description:
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. Au démarrage, le PIC doit aller chercher la dernière valeur enregistrée. Considérons qu'il parvienne sans difficulté 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. |
;****************************************************************************************************** ;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 resultat 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:
Voici l'implantation des composants et le typon du circuit :
Il faut cabler les deux circuits imprimés perpendiculairement. 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 compteur en marche: |
Le montage vu de dessus: |
Vous devez telecharger le typon en cliquant ici tout en appuyant sur la touche MAJUSCULE.
Je rappelle qu'il faut telecharger le logiciel ARES Lite qui est gratuit. Il est
disponible sur le site suivant: http://www.multipower-fr.com
Vous pouvez egalement cliquer ici pour voir
comment faire pour imprimer votre typon
ATTENTION, ici il faut ouvrir le fichier de la manière suivante:
~ 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.
Remarques:
Je vous rappelle que je ne suis en aucun cas responsable des dommages corporels ou materiels que pourrait causer le montage.
Pour tout renseignement, question, commentaire, ... n'hesitez pas à m'écrire : rbourdon@enib.fr