;****************** ;* Gazaile * ;*commande volets * ;* mars 2014 * ;* Lino de Martin * ;****************** ;notice : ;ce projet a pour but de commander les mouvements des volets de l'aile de l'avion à l'aide de la carte "commande_volet.PCB". ;le microcontrôleur pilote le moteur électrique continu 12V grace à un circuit de puissance MOS (pont en H). ;il est informé de la vitesse de l'avion grâce à un capteur de pression différentiel relié à une antenne de Prandtl. ;il est informé de ce qu'il doit faire grâce à 9 touches : 6 touches "mémoire", une touche UP(monte), une DOWN(descend) et une SET(règle). ;il est informé de la position des volets à l'aide d'un potentiomètre linéaire de recopie. ;il sort sur le connecteur IC15 une information PWM fonction de la position du volet (y mettre un voltmètre de 0 à 5V) ;il gère sur IC7 une interface série pour des options avancées (déport de panneau de commande). ;effacement des mémoires ;appuyer sur SET plus de 8s ;Réglage de la butée haute ;A l'aide de la touche UP remontez les volets jusqu'au maximum mécanique. ;appuyez sur la touche SET au moins 1s (mais pas plus de 4 secondes) puis relacher là. ;appuyez sur la touche UP : la butée haute est mémorisée. ;Si vous mettez plus de 16s pour appuyer sur UP la fonction est annulée. ;Réglage de la butée basse ;A l'aide de la touche down abaissez les volets jusqu'au maximum mécanique. ;appuyez sur la touche SET au moins 1s (mais pas plus de 4 secondes) puis relacher là. ;appuyez sur la touche DOWN : la butée basse est mémorisée. ;Si vous mettez plus de 16s pour appuyer sur DOWN la fonction est annulée. ;Mémorisation d'une position sur une touche Sx (de S1 à S6) ;A l'aide des touches UP et DOWN positionnez les volets ;appuyez sur la touche SET au moins 1s (mais pas plus de 4 secondes) puis relacher là. ;appuyez sur la touche Sx : la position est mémorisée. ;Si vous mettez plus de 16s pour appuyer sur Sx la fonction est annulée. ;Mémorisation des vitesses maximum pour une position ;Réglez la chaine anémométrique pour afficher la vitesse voulue ;appuyez sur la touche SET entre 4s (mais pas plus de 8 secondes) puis relacher là. ;appuyez sur la touche Sx : la vitesse est mémorisée pour la position Sx. ;la sortie des volets est interdites si la vitesse est supérieure à celle mémorisée. ;si aucune vitesse n'est renseignée le système tient compte de la vitesse VMAX ;N.B.: pour la position S1, le mouvement est autorisé si la vitesse est supérieure à la vitesse mémorisée. ;programmation de la vitesse VMAX à ne pas dépasser qui déclenche automatiquement la rentrée des volets en position 0 (S2) ; au bout d'une minute de dépassement de cette vitesse ;appuyez sur la touche SET entre 4s (mais pas plus de 8 secondes) puis relacher là. ;appuyer sur la touche UP. ;N.B.: si S2 n'est pas programmé ou si VMAX n'est pas programmé : la fonction est dévalidée. ;checksum : #include "E:\mes Documents\ulm\gazaile\commande_volet\P16F1827.inc" PROCESSOR 16F1827 __config _CONFIG1, _FOSC_INTOSC&_WDTE_OFF&_PWRTE_ON&_MCLRE_ON&_CP_OFF&_CPD_OFF&_BOREN_ON&_CLKOUTEN_OFF&_IESO_OFF&_FCMEN_OFF __config _CONFIG2, _WRT_OFF&_PLLEN_OFF&_STVREN_ON&_BORV_25&_LVP_OFF ;******************************************* ;* définition des ports du microcontrôleur * ;******************************************* ;étiquettes qui définissent l'utilisation des ports ;communication série #define RXD PORTB,RB1 ;RB1 RX réception #define TXD PORTB,RB2 ;RB2 TX émission ;mesure de pression/vitesse (valeur pour ADCON0) #define PRES b'00100101' ;RB3/AN9 : — CHS<4:0> GO/DONE ADON ;mesure position des volets (valeur pour ADCON0) #define POS b'00100001' ;RB4/AN8 : — CHS<4:0> GO/DONE ADON ;affichage de la position des volets ;PWM RA4 CCP4 PWM4 ;clavier #define LA PORTB,RB7 ;RB7 ligne A : S1, S2, S3, S4 #define LB PORTB,RB6 ;RB6 ligne B : S5, S6, S7 #define LC PORTB,RB5 ;RB5 ligne C : S8, S9 #define S1 CLAVAI,0 ;touche -4° #define S2 CLAVAI,1 ;touche 0° #define S3 CLAVAI,2 ;touche +10° #define S4 CLAVAI,3 ;touche +15° #define S5 CLAVAI,4 ;touche +30° #define S6 CLAVAI,5 ;touche Full #define S7 CLAVAI,6 ;touche Up #define S8 CLAVAI,7 ;touche Set #define S9 CLAVBI,0 ;touche Down ;driver moteur #define INA PORTA,RA6 ;RA6 INA commande de la branche A #define ENA PORTA,RA2 ;RA2 ENA/DIAGA autorisation / diagnostique de la branche A #define INB PORTA,RA7 ;RA7 INB commande de la branche B #define ENB PORTA,RA0 ;RA0 ENB/DIAGB autorisation / diagnostique de la branche B ;RA3 CCP3 PWM3 PWM modulation de la puissance ;CS mesure du courant consommé (valeur pour ADCON0) #define COUR b'00000101' ;RA1/AN1 : — CHS<4:0> GO/DONE ADON ;tag de débug #define TD PORTB,RB0 ;************** ;* constantes * ;************** ;paramètres des fonctions ;*** le TIMER0 à un prescaler de 8 ce qui fait une interruption @16Mhz toutes les Fosc/4x8x256 = 250nsx8x256 = 512µS VOPTION equ b'00000010' ;WPUEN INTEDG TMR0CS TMR0SE PSA PS<2:0> VICLA equ .24 ;nombre d'intégration du clavier VCAMES equ .8 ;nombre d'accumulation des mesures de tension (en puissance 2 : 2,4,8,16,32,64) VDMAXH equ 0xFC ;vitesse max par défaut, poids fort VDMAXL equ 0x01 ;poids faible. N.B: vitesse codée sur 10 bits soit 0x3FF max : -0x03FF = 0xFC01 VTIMER1H equ 0xC2 / 2 ;durée de la montée en puissance. Par exemple pour que le PWM passe de 0 à 0xFF en 1 seconde VTIMER1L equ 0xBA ;une incrémentation doit durée 1s/0xFF = 4ms. 4ms/250ns@16Mhz = 0x3D46. 0x10000-0x3D46= 0xC2BA VPMIN equ .60 ;puissance minimum au démarrage du moteur électrique VPFREIN equ .245 ;puissance de freinage du moteur électrique VPDEC equ .100 ;puissance en approche du point de consigne VPCONS equ 0x18 ;distance pour laquelle on change la puissance en approche du point de consigne. ;*************** ;* mémoire RAM * ;*************** ;définition des étiquettes des variables et implantation en RAM ;*** registres paginés Bank0 0x20 à 0x6F TXBUF equ 0x20 ;pointeur de l'octet à sortir via l'interface série ;fin sortie via interface série : les octets encadrés doivent avoir des adresses ram qui se suivent PMOT equ 0x21 ;puissance moteur CSUTATS equ 0x22 ;SUTATS POSL equ 0x23 ;valeur de la position du volet POSH equ 0x24 PRESL equ 0x25 ;valeur de la pression PRESH equ 0x26 COURL equ 0x27 ;valeur du courant mesuré COURH equ 0x28 CLAVAI equ 0x29 ;valeur de la touche intégrée CLAVBI equ 0x2A ;début sortie via interface série ;copie du contenu de l'EEPROM en RAM CLAVA equ 0x2B ;registre d'état de la lecture du clavier touches S1 à S8 CLAVB equ 0x2C ;idem pour S9 CLAVAP equ 0x2D ;valeur qui postule au changement CLAVBP equ 0x2E CCLAV equ 0x2F ;compteur d'intégration du clavier ;début de la zone sauvegardée en EEPROM POSMAXH equ 0x30 ;poids fort de la limite haute de la course du potentiomètre / position des volets au plus bas POSMAXL equ 0x31 ;poids faible POSMINH equ 0x32 ;limite basse de la course du potentiomètre / position des volets au plus haut POSMINL equ 0x33 ; POS4H equ 0x34 ;mémoire de la position -4° (S1) POS4L equ 0x35 ; POS0H equ 0x36 ;mémoire de la position 0° (S2) POS0L equ 0x37 ; POS10H equ 0x38 ;mémoire de la position +10° (S3) POS10L equ 0x39 ; POS15H equ 0x3A ;mémoire de la position +15° (S4) POS15L equ 0x3B ; POS30H equ 0x3C ;mémoire de la position +30° (S5) POS30L equ 0x3D ; POSFH equ 0x3E ;mémoire de la position Full (S6) POSFL equ 0x3F ; V4H equ 0x40 ;vitesse max à la position -4° V4L equ 0x41 ; V0H equ 0x42 ;vitesse max à la position 0° V0L equ 0x43 ; V10H equ 0x44 ;vitesse max à la position +10° V10L equ 0x45 ; V15H equ 0x46 ;vitesse max à la position +15° V15L equ 0x47 ; V30H equ 0x48 ;vitesse max à la position +30° V30L equ 0x49 ; VFH equ 0x4A ;vitesse max à la position Full VFL equ 0x4B ; VMAXH equ 0x4C ;vitesse max à ne pas dépasser qui commande la rentrée automatique des volets VMAXL equ 0x4D ; ;fin de la zone sauvegardée en EEPROM TEMPHIT equ 0x4E ;brouillon pour les IT TEMPMIT equ 0x4f TEMPLIT equ 0x50 ;*** registres paginés Bank1 0xA0 à 0xEF AMESH equ 0xA0 ;accumulation des mesures du CAN AMESL equ 0xA1 CAMES equ 0xA2 ;compteur de moyennage des mesures du CAN ;*** registres communs 0x70 à 0x7F SECONDE equ 0x70 ;sous horloge de base 62.5ms du TIMER6 MINUTE equ 0x71 ;sous horloge de base 62.5ms du TIMER6 TEMP equ 0x72 ;brouillon pour calcul local TEMPH equ 0x73 TEMP2 equ 0x74 TEMP2H equ 0x75 SUTATS equ 0x76 ;registre de STATUS du système TA equ .0 ;touche appuyée MVP equ .1 ;mouvement programmé en cours MVT equ .2 ;mouvement des touche UP/DOWN en cours MUP equ .3 ;sens du mouvement 1=Up, 0=Down TS equ .4 ;touche SET (S8) enfoncée TS4 equ .5 ;touche SET enfoncée plus de 4s TS8 equ .6 ;touche SET enfoncée plus de 8s VSTAT equ 0x77 VMD equ .0 ;vitesse max dépassée VMDL equ .1 ;vitesse max dépassée depuis plus de 32s TPOSH equ 0x78 ;position à atteindre, poids fort TPOSL equ 0x79 ;poids faible ;********************* ;* mémoire programme * ;********************* ;la mémoire commence par la définition des 2 vecteurs : Reset et Interruption debut org .0 ;première instruction après la mise sous tension ou un RESET goto init ;vecteur RESET ;***************** ;* interruptions * ;***************** ;les routines de traitement des interruptions sont placées sur le vecteur isr org .4 ;vecteur d'interruption movlb .0 ;bank 0 btfsc INTCON,TMR0IF goto ITmes ;IT de mesure des tensions btfsc PIR3,TMR4IF goto CLAV ;IT de scrutation du clavier btfsc PIR3,TMR6IF goto TBASE ;base de temps et envoie de trame série ;*** interuptions autorisées sur demande movlb .1 ;bank1 btfss PIE1,TXIE goto no_TXIE movlb .0 ;bank0 btfsc PIR1,TXIF goto isr_TXIF no_TXIE movlb .0 ;bank0 retfie ;********************* ;* interruption * ;* mesure de tension * ;********************* ;on arrive içi quand TIMER0 déborde toutes les 512µS ;une convertion de tension est finie en 48µs on est sûr qu'elle sera finie. ;on accumule la valeur mesurée VCAMES fois grace au compteur CAMES dans les registres AMESH/AMESL ;Aprés avoir aiguillé vers la mesure choisie on teste l'accumulation : ;si elle n'est pas terminée on relance une nouvelle mesure. ;si elle est terminée on change l'aiguillage de la tenion à mesurer (pression>position, position>courant, courant>pression) ;on calcule la valeur moyenne en cours et on la sauvegarde dans les bons registres ;ensuite on initialise le nombre d'acumulation et on relance une convertion. ; ;au niveau timing c'est la mesure de la position qui est la plus critique ;il faut 16s au motoréducteur pour parcourir 160mm, ;on fait une mesure toutes les 512µs, si VCAMES=8 on a une nouvelle valeur toutes les 512µs*8(VCAMES)*3(position/courant/pression)= 12ms ;cela donne une précision à pleine vitesse de 12ms x 160mm/16S = 0.12 mm : suffisant ! ITmes bcf INTCON,TMR0IF ;acquitement de l'interruption movlb .1 ;bank 1 movf ADRESL,w ;accumulation de la mesure addwf AMESL,f btfsc STATUS,C incf AMESH,f ;gestion de la retenue movf ADRESH,w addwf AMESH,f movlw PRES xorwf ADCON0,w ;Est-ce une mesure de pression ? btfss STATUS,Z goto ITmesa ;non ;oui gestion de la mesure de pression decfsz CAMES,f goto finITmes ;l'acumulation n'est pas finie movlw POS ;fin d'accumulation : on change l'aiguillage du convertisseur pour mesurer la position call decalames ;calcul de la moyenne de la valeur bsf ADCON0,GO ;lancement de la conversion movf AMESH,w movlb .0 ;bank0 movwf PRESH movwf TEMPHIT movlb .1 ;bank 1 movf AMESL,w movlb .0 ;bank0 movwf PRESL movwf TEMPMIT clrf TEMPLIT ;pour l'instant je ne fais pas de correction pour avoir POSMAX-POSMIN en pleine échelle sur le PWM4 rrf TEMPHIT,f ;rotation pour la mise à jour du PWM4 rrf TEMPMIT,f rrf TEMPLIT,f rrf TEMPHIT,f rrf TEMPMIT,f rrf TEMPLIT,f lsrf TEMPLIT,f movlb .6 ;bank6 movlw b'11001111' andwf CCP4CON,f movlb .0 ;bank0 lsrf TEMPLIT,w movlb .6 ;bank6 iorwf CCP4CON,f ;mise à jour des 2 bits de poids faibles du PWM4 movlb .0 ;bank0 movf TEMPMIT,w movlb .6 ;bank6 movwf CCPR4L ;mise à jour des 8 bits de poids forts du PWM4 movlb .0 ;bank0 call initAMES retfie ITmesa movlw POS xorwf ADCON0,w ;Est-ce une mesure de position ? btfss STATUS,Z goto ITmesb ;non ;oui gestion de la mesure de position decfsz CAMES,f goto finITmes ;l'acumulation n'est pas finie movlw COUR ;fin d'accumulation : on change l'aiguillage du convertisseur pour mesurer le courant call decalames ;calcul de la moyenne de la valeur bsf ADCON0,GO ;lancement de la conversion movf AMESH,w movlb .0 ;bank0 movwf POSH movlb .1 ;bank 1 movf AMESL,w movlb .0 ;bank0 movwf POSL call initAMES retfie ;gestion de la mesure du courant ITmesb decfsz CAMES,f goto finITmes ;l'acumulation n'est pas finie movlw PRES ;fin d'accumulation : on change l'aiguillage du convertisseur pour mesurer la pression call decalames ;calcul de la moyenne de la valeur bsf ADCON0,GO ;lancement de la conversion movf AMESH,w movlb .0 ;bank0 movwf COURH movlb .1 ;bank 1 movf AMESL,w movlb .0 ;bank0 movwf COURL call initAMES retfie finITmes bsf ADCON0,GO ;lancement d'une nouvelle conversion retfie decalames movwf ADCON0 ;pendant le temps du décalage le condensateur du S&H du CAN se charge movlw VCAMES ;on charge le nombre d'accumulations faites movwf CAMES lsrf AMESH,f ;on divise par 2 autant de fois que d'accumulation à la puissance 2 rrf AMESL,f lsrf CAMES,f btfss CAMES,0 ;arrivé au bit 0 le nombre de division par 2 est atteint goto $-4 ;pour retrouver la valeur moyennée movlw VCAMES ;initialisation du compteur d'accumulation movwf CAMES return ;pour cette sous routine on a une durée =9+log2(VCAMES)x6 ;par exemple VCAMES=8 donne : 9+log2(8)x6 = 9+3x6 = 27 cycles = 6.75µs @16Mhz ;par exemple VCAMES=64 donne : 9+log2(64)x6 = 9+6x6 = 45 cycles = 11.25µs @16Mhz initAMES movlb .1 ;bank1 clrf AMESH clrf AMESL return ;*********************** ;* interruption * ;* decodage du clavier * ;*********************** ;on arrive içi toutes les 8.2ms grâce à TIMER4 ;pour utiliser 3 ports pour la gestion de 9 touches on commute un port en sortie puis les autres en entrée ;en fonction de leur état on sait qu'elles touches sont enfoncées. ;cette méthode ne gère pas les appuis simultanés sur plusieurs touches ;S1, S2, S3, S4? ;On met la ligne A en sortie à 0, si les lignes B et C en entrée sont à 1 c'est qu'aucune des touches S1 à S4 n'est pressées ;Si la ligne B=0 il faut la passer en sortie à 0, A en entrée : si A=0 c'est S1 qui est pressée sinon c'est S2 ;Si la ligne C=0 il faut la passer en sortie à 0, A en entrée : si A=0 c'est S3 qui est pressée sinon c'est S4 CLAV bcf PIR3,TMR4IF ;on acquite l'interruption clrf CLAVA ;on initialise l'état des touches clrf CLAVB call CLA ;on passe la ligne A en sortie à 0 et B,C en entrées btfsc LB goto S3S4 S1S2 call CLB ;LB=0 c'est S1 ou S2 qui est active. On passe la ligne B en sortie à 0 et A,C en entrées btfss LA bsf CLAVA,0 ;LA=0 c'est S1 qui est pressée btfsc LA bsf CLAVA,1 ;LA=1 c'est S2 qui est pressée goto FINS ;une touche est appuyée pas la peine de continuer les autres décodages S3S4 btfsc LC goto BS5 ;LC=1 aucune des touches S1 à S4 n'est pressée call CLC ;LC=0 c'est S3 ou S4 qui est active. On passe la ligne C en sortie à 0 et A,B en entrées btfss LA bsf CLAVA,2 ;LA=0 c'est S3 qui est pressée btfsc LA bsf CLAVA,3 ;LA=1 c'est S4 qui est pressée goto FINS ;une touche est appuyée pas la peine de continuer les autres décodages BS5 call CLB ;On passe la ligne B en sortie à 0 et A,C en entrées btfsc LA goto S6S7 ;LA=1 S5 n'est pas pressée bsf CLAVA,4 ;LA=0 c'est S5 qui est pressée goto FINS ;une touche est appuyée pas la peine de continuer les autres décodages S6S7 btfsc LC goto BS8 ;LC=1 S6 et S7 ne sont pas pressées call CLC ;LC=0 c'est S6 ou S7 qui est activ. On passe la ligne C en sortie à 0 et A,B en entréese btfss LB bsf CLAVA,5 ;LB=0 c'est S6 qui est pressée btfsc LB bsf CLAVA,6 ;LB=1 c'est S7 qui est pressée goto FINS ;une touche est appuyée pas la peine de continuer les autres décodages BS8 call CLC ;On passe la ligne C en sortie à 0 et A,B en entrées btfsc LA goto BS9 ;LA=1 S8 n'est pas pressée bsf CLAVA,7 ;LA=0 c'est S8 qui est pressée goto FINS ;une touche est appuyée pas la peine de continuer les autres décodages BS9 btfsc LB goto FINS ;pas de touche appuyée bsf CLAVB,0 ;LB=0 c'est S9 qui est pressée FINS ;intégration de la valeur actuelle du clavier ;On ne peut pas surement établir l'état d'une touche sur une seule information. En effet cela peut être un rebond de contact ou un parasite. ;pour être certain que l'information est valide il faut qu'elle soit présente un certain nombre de fois. ;c'est le rôle de l'intégration. On vérifie que l'information lue est présente au moins VICLA fois grace au compteur CCLAV ;si CLAVA/CLAVB est identique à CLAVAI/CLAVBI il n'y a pas de changement : on initialise CCLAV=VICLA ;si CLAVA/CLAVB est différent de CLAVAI/CLAVBI on définit dans un premier temps le postulant au changement CLAVAP/CLAVBP=CLAVA/CLAVB ;si le postulant au changement d'état des touches est égal à CLAVA/CLAVB VICLA fois de suite alors CLAVAI/CLAVBI=CLAVA/CLAVB ;sinon on reconsidère le postulant CLAVAP/CLAVBP=CLAVA/CLAVB et on initialise de nouveau CCLAV=VICLA ;CLAVAI/CLAVBI contient donc l'état des touches après intégration. ;Au niveau timing il faut que VICLA lectures durent moins de 0.2 secondes (~un apuui rapide sur une touche). ;en se servant du TIMER4 que l'on règle comme base de temps à 250ns*64*256*2= 8.2ms ;VICLA = 0.2s / 8.2ms = 24 movf CLAVAI,w xorwf CLAVA,w btfss STATUS,Z goto SCH ;il y a changement de valeur movf CLAVBI,w xorwf CLAVB,w btfss STATUS,Z goto SCH ;il y a changement de valeur ICCLAV movlw VICLA ;il n'y a pas eu changement de valeur movwf CCLAV ;initialisation de l'intégration retfie SCH movf CLAVAP,w xorwf CLAVA,w btfsc STATUS,Z goto DCCLAV ;la partie A du postulant est identique movf CLAVA,w ;le postulant est différent movwf CLAVAP ICLAVBP movf CLAVB,w movwf CLAVBP goto ICCLAV ;initialisation de l'intégration DCCLAV movf CLAVBP,w xorwf CLAVB,w btfss STATUS,Z goto ICLAVBP ;la partie B du postulant est différente DCCLAVB decfsz CCLAV,f ;le postulant est identique. On décrémente le compteur d'ntégration retfie movf CLAVA,w ;l'intégration est terminée movwf CLAVAI ;on change la valeur movf CLAVB,w movwf CLAVBI goto ICCLAV ;initialisation de l'intégration ;************************ ;* interruption * ;* base de temps 62.5ms * ;************************ ;on arrive içi toutes les 62.5 ms TBASE bcf PIR3,TMR6IF ;on acquite l'interruption movlb .1 ;bank1 bsf PIE1,TXIE ;on autorise l'envoie de caracère par l'interface série donc on autorise l'émission de la trame. incf SECONDE,f ;on incrémente SECONDE toutes les 62.5ms on a donc : ;le bit 0 est à 1 ou 0 toutes les 62.5ms ou 16 fois/s ;le bit 1 est à 1 ou 0 toutes les 125ms ou 8 fois/s ;le bit 2 est à 1 ou 0 toutes les 250ms ou 4 fois/s ;le bit 3 est à 1 ou 0 toutes les 500ms ou 2 fois/s ;le bit 4 est à 1 ou 0 toutes les 1s ou 1 fois/s ;le bit 5 est à 1 ou 0 toutes les 2s ou 0.50 fois/s ;le bit 6 est à 1 ou 0 toutes les 4s ou 0.25 fois/s ;le bit 7 est à 1 ou 0 toutes les 8s ou 0.125 fois/s btfsc STATUS,Z incf MINUTE,f ;le bit 0 est à 1 ou 0 toutes les 16s retfie ;le bit 1 est à 1 ou 0 toutes les 32s ;le bit 2 est à 1 ou 0 toutes les 1 minute 4s ;le bit 3 est à 1 ou 0 toutes les 2 minutes 8s ;le bit 4 est à 1 ou 0 toutes les 4 minutes 16s ;le bit 5 est à 1 ou 0 toutes les 8 minutes 32s ;le bit 6 est à 1 ou 0 toutes les 17 minutes 4s ;le bit 7 est à 1 ou 0 toutes les 34 minutes 8s ;********************* ;* interruption * ;* envoi de trame * ;* de valeurs via * ;* l'interface série * ;********************* ;on envoie dans l'ordre CLAVBI, CLAVAI, COURH, COURL, PRESH, PRESL, POSH, POSL, SUTATS, PMOT CR soit 11 octets ;comme le format est 8N1 il y a 10 bits à transmettre pour un octet, à 9600 bauds un octet dure 1.04 ms ;on arrive donc içi toutes les 1.04 ms isr_TXIF movlb .0 ;bank 0 decfsz TXBUF,f goto TXIFA movlw .11 ;9 octets à transmettre movwf TXBUF movf SUTATS,w movwf CSUTATS movlb .6 ;bank6 movf CCPR3L,w movlb .0 ;bank 0 movwf PMOT movlw .13 ;envoie du code ASCII Carriage return movlb .3 ;bank3 movwf TXREG ;vers l'interface série movlb .1 ;bank1 bcf PIE1,TXIE ;la trame est finie, on bloque l'émission de caractère. retfie ;c'est le TIMER6 qui réautorisera les émissions. TXIFA movlw low TXBUF ;adresse de début du buffer de transmission série addwf TXBUF,w ;on ajoute le pointeur de l'octet à envoyer movwf FSR0L ;on positionne l'adresse à lire clrf FSR0H ;pour un adressage indirect movf INDF0,w ;on lit l'octet à envoyer movlb .3 ;bank3 movwf TXREG ;envoie vers l'interface série retfie ;***************** ;* sous routines * ;***************** ;gestion du clavier CLA bsf LB bsf LC bcf LA movlb .1 ;bank 1 bcf LA ;LA en sortie bsf LB ;LB en entrée bsf LC ;LC en entrée movlb .0 ;bank 0 RET return RET8 call RET return CLB bsf LA bsf LC bcf LB movlb .1 ;bank 1 bsf LA bcf LB bsf LC movlb .0 ;bank 0 return CLC bsf LA bsf LB bcf LC movlb .1 ;bank 1 bsf LA bsf LB bcf LC movlb .0 ;bank 0 return ;***calcul checksum de la plage memoire pour l'EEPROM CKSMEM clrf TEMP ;sert à recalculer le cheksum clrf FSR0H ;initialise le pointeur de la lecture indirecte de la mémoire movlw low VMAXL movwf FSR0L movf INDF0,w addwf TEMP,f decf FSR0L,f movlw low POSMAXH-1 xorwf FSR0L,w btfss STATUS,Z goto $-6 movf TEMP,w return ;***EEPROM écriture de W EEWRITE bcf INTCON,GIE btfsc INTCON,GIE goto $-2 movlw 0x55 movwf EECON2 movlw 0xAA movwf EECON2 bsf EECON1,WR bsf INTCON,GIE ;attention dans les ISR il ne doit pas il y avoir d'accès aux registres de l'EEPROM btfsc EECON1,WR ;on doit tester le fin d'écriture avant de modifier goto $-1 ;les registres de l'EEPROM return ;*** pause de 0.5s pause05 movlb .0 ;bank0 clrf SECONDE btfss SECONDE,3 goto $-1 ;attente de 0.5s return ;*** pause de 1s pause1 clrf SECONDE btfss SECONDE,4 goto $-1 ;attente de 2s return ;*** pause de 2s pause2 clrf SECONDE btfss SECONDE,5 goto $-1 ;attente de 2s return ;*** arret moteur STOPMOT movlb .0 ;bank0 bcf INA nop bcf INB ;on arrête le moteur movlb .6 ;bank6 movlw VPFREIN ;pour stopper le moteur on le court-circuite movwf CCPR3L ;puissance à 0 call pause1 clrf CCPR3L ;puissance à 0 movlb .0 ;bank0 return ;*** incrémentation de la puissance moteur PINCMOT movlb .6 ;bank6 movf CCPR3L,w xorlw 0xFF btfss STATUS,Z ;si puissance incf CCPR3L,f ;n'est pas au max on l'incrémente movlw VPMIN subwf CCPR3L,w ;correction de la puissance minimum de départ movlw VPMIN btfss STATUS,C movwf CCPR3L ;CCPR3L — SCS<1:0> movlw VOPTION movwf OPTION_REG ;initialisation de la direction des ports en sortie bcf INA bcf INB bcf ENA bcf ENB bcf TD ;initialisation des mesures de tension clrf AMESH clrf AMESL movlw VCAMES movwf CAMES movlb .0 ;bank 0 clrf PRESH clrf PRESL clrf POSH clrf POSL clrf COURH clrf COURL ;initialisation de la lecture du clavier clrf CLAVAP clrf CLAVBP clrf CLAVAI clrf CLAVBI ;initialisation du système clrf SUTATS clrf VSTAT ;initialisation USART : 9600 bauds 8N1 movlw .11 ;9 octets à envoyer movwf TXBUF movlb .3 ;bank 3 clrf SPBRGH ;définition de la vitesse à 9600 bauds movlw .25 movwf SPBRGL movlw b'00000000' ;SCKP:0 = Transmit inverted data to the TX/CK pin ,0 = Transmit non-inverted data to the TX/CK pin movwf BAUDCON ;ABDOVF RCIDL — SCKP BRG16 — WUE ABDEN movlw b'00000000' movwf TXSTA ;CSRC TX9 TXEN(1) SYNC SENDB BRGH TRMT TX9D movlw b'10000000' movwf RCSTA ;SPEN RX9 SREN CREN ADDEN FERR OERR RX9D bsf TXSTA,TXEN ;configuration du convertisseur analogique numérique ;il y a 3 mesures à faire : le courant consommé par le moteur (RA1/AN1), la pression (RB3/AN9) et la position des volets (RB4/AN8) clrf ANSELA clrf ANSELB bsf ANSELA,ANSA1 ;RA1/AN1 bsf ANSELB,ANSB3 ;RB3/AN9 bsf ANSELB,ANSB4 ;RB4/AN8 movlb .1 ;bank 1 bsf ADCON0,ADON movlw PRES movwf ADCON0 ;l'horloge du convertisseur est à Fosc/64 soit Tad=4µS. Une conversion dure 12Tad soit 48µS movlw b'11100000' ;ADFM ADCS<2:0> — ADNREF ADPREF<1:0> (justifiacation à droite Fosc/64) movwf ADCON1 bsf ADCON0,GO ;configuration de l'interruption TIMER0 ;TIMER 0 génére une IT toutes les 512µS pour les mesures de tensions movlb .0 ;bank 0 clrf TMR0 bcf INTCON,TMR0IF bsf INTCON,TMR0IE BSF INTCON,GIE ;TIMER 1 créer un cycle de VTIMER1H/L pour incrémenter la puissance du moteur movlw b'00000001' movwf T1CON ;TMR1CS<1:0> T1CKPS<1:0> T1OSCEN T1SYNC — TMR1ON ;TIMER 2 comme horloge des PWM movlb .5 ;bank 5 clrf CCPTMRS ;C4TSEL<1:0> C3TSEL<1:0> C2TSEL<1:0> C1TSEL<1:0> ;configuration de TIMER2 movlb .0 ;bank 0 movlw 0xff movwf PR2 movlw b'00000101' ;— TxOUTPS<3:0> TMRxON TxCKPS<1:0> movwf T2CON ;prescaler=4, postscaler=1 ;frequence PWM = 16Mhz/((0xFF+1)x4x4)= 3.9Khz movlb .6 ;bank 6 movlw b'00111100' ;PxM<1:0>(1) DCxB<1:0> CCPxM<3:0> movwf CCP3CON movwf CCP4CON ;PWM RA4 CCP4 PWM4 et RA3 CCP3 PWM3 movlb .1 ;bank 0 bcf TRISA,RA4 bcf TRISA,RA3 ;TIMER 4 comme cycle de scrutation du clavier ;TIMER 4 doit générer une interruption toutes les 8.2ms movlb .8 ;bank 8 movlw 0xff movwf PR4 movlw b'00001111' ;— TxOUTPS<3:0> TMRxON TxCKPS<1:0> movwf T4CON ;prescaler=64, postscaler=2, PR4=255 > 250nsx64x(255+1)x2= 8.2 ms clrf TMR4 ;autorisation des interruptions bsf INTCON,PEIE movlb .0 ;bank 1 bcf PIR3,TMR4IF movlb .1 ;bank 1 bsf PIE3,TMR4IE ;TIMER 6 comme base de temps 62.5ms qui incrémente SECONDE et MINUTE movlb .8 ;bank 8 movlw .243 movwf PR6 movlw b'01111111' ;— TxOUTPS<3:0> TMRxON TxCKPS<1:0> movwf T6CON ;prescaler=64, postscaler=16, PR6=195 > 250nsx64x(243+1)x16= 50 ms clrf TMR6 ;autorisation des interruptions movlb .0 ;bank 1 bcf PIR3,TMR6IF movlb .1 ;bank 1 bsf PIE3,TMR6IE ;********** ;* EEPROM * ;********** ;dans cette mémoire non volatile nous sauvegardons différents paramètres ;0x0 checksum adresse 0+1+...+dernier paramètre ;0x1 poids fort de la limite haute de la course du potentiomètre / position des volets ;0x2 poids faible ;0x3 poids fort de la limite basse de la course du potentiomètre / position des volets ;0x4 poids faible ;0x5 poids fort de la mémoire de la position -4° ;0x6 poids faible ;0x7 poids fort de la mémoire de la position 0° ;0x8 poids faible ;0x9 poids fort de la mémoire de la position +10° ;0xa poids faible ;0xb poids fort de la mémoire de la position +15° ;0xc poids faible ;0xd poids fort de la mémoire de la position +30° ;0xe poids faible ;0xf poids fort de la mémoire de la position Full ;0x10 poids faible ;0x11 poids fort de la mémoire de la vitesse max à la position -4° ;0x12 poids faible ;0x13 poids fort de la mémoire de la vitesse max à la position 0° ;0x14 poids faible ;0x15 poids fort de la mémoire de la vitesse max à la position +10° ;0x16 poids faible ;0x17 poids fort de la mémoire de la vitesse max à la position +15° ;0x18 poids faible ;0x19 poids fort de la mémoire de la vitesse max à la position +30° ;0x1a poids faible ;0x1b poids fort de la mémoire de la vitesse max à la position Full ;0x1c poids faible ;0x1d poids fort de la vitesse max à ne pas dépasser qui commande la rentrée automatique des volets ;0x1e poids faible ;configuration de l'EEPROM movlb .3 ;bank 3 movlw b'00000100' movwf EECON1 ;EEPGD CFGS LWLO FREE WRERR WREN WR RD ;lecture de l'EEPROM clrf TEMP ;sert à recalculer le cheksum clrf FSR0H ;initialise le pointeur de la lecture indirecte de la mémoire movlw low VMAXL movwf FSR0L movlw low VMAXL - low POSMAXH +1 ;pointeur de l'adresse de l'EEPROM movwf EEADRL bsf EECON1,RD movf EEDATL,w movlb .0 ;bank0 movwf INDF0 addwf TEMP,f movlb .3 ;bank 3 decf FSR0L,f decfsz EEADRL,f goto $-8 bsf EECON1,RD ;lecture du checksum movf EEDATL,w movlb .0 ;bank0 xorwf TEMP,w btfsc STATUS,Z goto OKEEPROM ;le checksum est bon ;le checksum est mauvais on place 0 dans les constantes de vitesse pour ne pas gérer cette fonction ;on bloque l'action des touches mémoires tant qu'un SET d'une touche n'est pas fait ;lors du premier SET, toutes les touches prennent la même valeur de position avant de relacher le bit SUTATS,EEER MEMRESET clrf SUTATS ;effacement de SUTATS depuis l'aiguillage des touches clrf FSR0H ;effacement de la zone mémoire des vitesses et positions movlw low POSMAXH movwf FSR0L clrf INDF0 incf FSR0L,f movlw low VMAXL +1 xorwf FSR0L,w btfss STATUS,Z goto $-5 ;effacement de l'EEPROM movlb .3 ;bank 3 clrf EEDATL movlw low VMAXL - low POSMAXH +1 ;pointeur de l'adresse de l'EEPROM movwf EEADRL call EEWRITE decfsz EEADRL,f goto $-2 call EEWRITE ;ecriture du checksum OKEEPROM ;*********************************************** ;* aiguillage en fonction des touches appuyées * ;*********************************************** ;on scrute CLAVBI/CLAVAI les touches sont définies comme cela : ;CLAVAI bit 0 touche S1 = -4° ;CLAVAI bit 1 touche S2 = 0° ;CLAVAI bit 2 touche S3 = +10° ;CLAVAI bit 3 touche S4 = +15° ;CLAVAI bit 4 touche S5 = +30° ;CLAVAI bit 5 touche S6 = Full ;CLAVAI bit 6 touche S7 = Up ;CLAVAI bit 7 touche S8 = Set ;CLAVBI bit 0 touche S9 = Down movlb .0 ;bank 0 bsf ENA nop bsf ENB clrf SUTATS call STOPMOT ;on stope le moteur ;on monte les volets avec INA=1 et INB=0 ;on descend avec INA=0 et INB=1 ATTTMR1 movlb .0 ;bank 0 btfss PIR1,TMR1IF goto $-1 ;on attends la période de 4ms de TIMER 1 movlw VTIMER1L ;on reprogramme le TIMER 1 pour 4ms movwf TMR1L movlw VTIMER1H movwf TMR1H bcf PIR1,TMR1IF ;Fonction de rentrée automatique. ;Teste si VMAX est dépassée depuis plus de 32s S0A movf VMAXH,w btfss STATUS,Z goto S0B ;il y a une vitesse max de programmée movf VMAXL,w btfsc STATUS,Z goto S1A ;pas de limite de vitesse S0B bcf INTCON,GIE ;il y a une vitesse max de programmée movf PRESH,w movwf TEMPH movf VMAXL,w ;VMAX contient le complément à 2 de la vitesse : -VMAX addwf PRESL,w bsf INTCON,GIE btfsc STATUS,C ;on fait Vitesse_actuelle - VMAX incf TEMPH,f movf VMAXH,w addwf TEMPH,w btfss STATUS,C goto S0D ;résultat négatif : vitesse assez faible > on initialise la fonction ;résultat positif : vitesse trop élevée btfsc VSTAT,VMD ;est-ce la première fois qu'elle est dépassée goto S0C ;non clrf SECONDE ;oui, on initialise le chronomètre clrf MINUTE bsf VSTAT,VMD S0C btfsc VSTAT,VMDL ;vitesse dépassée depuis bien plus de 32s ? goto S0K ;oui btfss MINUTE,1 ;est-ce dépassé depuis plus de 32s ? goto S1A ;non : on continue de tester les autres touches ;depuis plus de 32s bsf VSTAT,VMDL S0K movf POS0H,w btfss STATUS,Z goto S0F movf POS0L,w btfsc STATUS,Z goto S1A ;pas de position 0° de programmée : on ne fait rien ;position 0° programmée : on teste si la position actuelle est en dessous de la position 0° S0F bcf INTCON,GIE ;on stope les IT pour ne pas avoir d'altération de la valeur 10bits car entre les movf POSH,w ; 2 instructions "movf" il peut il y avoir une IT qui change les valeurs POSH ou POSL. movwf TEMP ;détermination du sens du mouvement movf POS0L,w ;soustraction POS-Position_0° addwf POSL,w bsf INTCON,GIE btfsc STATUS,C incf TEMP,f movf POS0H,w addwf TEMP,w btfss STATUS,C goto S1A ;C=0 POS-TPOS < 0 la position actuelle est plus haute que celle visée : on ne fait rien bsf SUTATS,MUP ;C=1 POS-TPOS >= 0 la position actuelle des volets est plus basse que celle visée : on monte les volets bsf SUTATS,MVP ;on demande un mouvement programmé movf POS0H,w ;vers la position 0° movwf TPOSH movf POS0L,w movwf TPOSL bcf INB nop bsf INA goto TS7 ;on lance le mouvement programmé mais les touches UP/DOWN sont traitées en priorité ;pour annuler la remontée pendant au plus 32s S0D bcf VSTAT,VMD bcf VSTAT,VMDL ;touche S1 S1A btfss S1 goto S2A btfsc SUTATS,TS4 goto SETV4 btfsc SUTATS,TS goto SETPOS4 movf V4H,w btfss STATUS,Z goto S1B movf V4L,w btfsc STATUS,Z goto S1E ;le contrôle de vitesse est différent pour cette touche S1 ;en effet il s'agit d'une position "grande vitesse" ;on autorise donc cette position pour des vitesses supérieures à celle mémorisée S1B bcf INTCON,GIE movf PRESH,w movwf TEMPH movf V4L,w addwf PRESL,w bsf INTCON,GIE btfsc STATUS,C incf TEMPH,f movf V4H,w addwf TEMPH,w btfsc STATUS,C ;c'est içi que se fait l'inversion (btfsC au lieu de btfsS) goto S1E S1G clrf SUTATS btfsc S1 goto $-1 goto ATTTMR1 S1E movf POS4H,w btfss STATUS,Z goto S1F movf POS4L,w btfsc STATUS,Z goto S1G S1F movf POS4H,w movwf TPOSH movf POS4L,w movwf TPOSL goto INITCPOS ;mémorisation de la position actuelle pour la touche -4° SETPOS4 bcf INTCON,GIE comf POSH,w movwf POS4H comf POSL,w bsf INTCON,GIE movwf POS4L incf POS4L,f btfsc STATUS,Z incf POS4H,f call SAUVEEP goto S1G ;mémorisation de la vitesse actuelle pour la touche -4° SETV4 bcf INTCON,GIE comf PRESH,w movwf V4H comf PRESL,w bsf INTCON,GIE movwf V4L incf V4L,f btfsc STATUS,Z incf V4H,f call SAUVEEP goto S1G ;pour les commentaires des touches S2 à S6 voir ceux de la touche S6 ;touche S2 S2A btfss S2 goto S3A btfsc SUTATS,TS4 goto SETV0 btfsc SUTATS,TS goto SETPOS0 movf V0H,w btfss STATUS,Z goto S2B movf V0L,w btfsc STATUS,Z goto S2E S2B bcf INTCON,GIE movf PRESH,w movwf TEMPH movf V0L,w addwf PRESL,w bsf INTCON,GIE btfsc STATUS,C incf TEMPH,f movf V0H,w addwf TEMPH,w btfss STATUS,C goto S2E S2G clrf SUTATS btfsc S2 goto $-1 goto ATTTMR1 S2E movf POS0H,w btfss STATUS,Z goto S2F movf POS0L,w btfsc STATUS,Z goto S2G S2F movf POS0H,w movwf TPOSH movf POS0L,w movwf TPOSL goto INITCPOS ;mémorisation de la position actuelle pour la touche 0° SETPOS0 bcf INTCON,GIE comf POSH,w movwf POS0H comf POSL,w bsf INTCON,GIE movwf POS0L incf POS0L,f btfsc STATUS,Z incf POS0H,f call SAUVEEP goto S2G ;mémorisation de la vitesse actuelle pour la touche 0° SETV0 bcf INTCON,GIE comf PRESH,w movwf V0H comf PRESL,w bsf INTCON,GIE movwf V0L incf V0L,f btfsc STATUS,Z incf V0H,f call SAUVEEP goto S2G ;touche S3 S3A btfss S3 goto S4A btfsc SUTATS,TS4 goto SETV10 btfsc SUTATS,TS goto SETPOS10 movf V10H,w btfss STATUS,Z goto S3B movf V10L,w btfsc STATUS,Z goto S3E S3B bcf INTCON,GIE movf PRESH,w movwf TEMPH movf V10L,w addwf PRESL,w bsf INTCON,GIE btfsc STATUS,C incf TEMPH,f movf V10H,w addwf TEMPH,w btfss STATUS,C goto S3E S3G clrf SUTATS btfsc S3 goto $-1 goto ATTTMR1 S3E movf POS10H,w btfss STATUS,Z goto S3F movf POS10L,w btfsc STATUS,Z goto S3G S3F movf POS10H,w movwf TPOSH movf POS10L,w movwf TPOSL goto INITCPOS ;mémorisation de la position actuelle pour la touche 10° SETPOS10 bcf INTCON,GIE comf POSH,w movwf POS10H comf POSL,w bsf INTCON,GIE movwf POS10L incf POS10L,f btfsc STATUS,Z incf POS10H,f call SAUVEEP goto S3G ;mémorisation de la vitesse actuelle pour la touche 10° SETV10 bcf INTCON,GIE comf PRESH,w movwf V10H comf PRESL,w bsf INTCON,GIE movwf V10L incf V10L,f btfsc STATUS,Z incf V10H,f call SAUVEEP goto S3G ;touche S4 S4A btfss S4 goto S5A btfsc SUTATS,TS4 goto SETV15 btfsc SUTATS,TS goto SETPOS15 movf V15H,w btfss STATUS,Z goto S4B movf V15L,w btfsc STATUS,Z goto S4E S4B bcf INTCON,GIE movf PRESH,w movwf TEMPH movf V15L,w addwf PRESL,w bsf INTCON,GIE btfsc STATUS,C incf TEMPH,f movf V15H,w addwf TEMPH,w btfss STATUS,C goto S4E S4G clrf SUTATS btfsc S4 goto $-1 goto ATTTMR1 S4E movf POS15H,w btfss STATUS,Z goto S4F movf POS15L,w btfsc STATUS,Z goto S4G S4F movf POS15H,w movwf TPOSH movf POS15L,w movwf TPOSL goto INITCPOS ;mémorisation de la position actuelle pour la touche 15° SETPOS15 bcf INTCON,GIE comf POSH,w movwf POS15H comf POSL,w bsf INTCON,GIE movwf POS15L incf POS15L,f btfsc STATUS,Z incf POS15H,f call SAUVEEP goto S4G ;mémorisation de la vitesse actuelle pour la touche 15° SETV15 bcf INTCON,GIE comf PRESH,w movwf V15H comf PRESL,w bsf INTCON,GIE movwf V15L incf V15L,f btfsc STATUS,Z incf V15H,f call SAUVEEP goto S4G ;touche S5 S5A btfss S5 goto S6A btfsc SUTATS,TS4 goto SETV30 btfsc SUTATS,TS goto SETPOS30 movf V30H,w btfss STATUS,Z goto S5B movf V30L,w btfsc STATUS,Z goto S5E S5B bcf INTCON,GIE movf PRESH,w movwf TEMPH movf V30L,w addwf PRESL,w bsf INTCON,GIE btfsc STATUS,C incf TEMPH,f movf V30H,w addwf TEMPH,w btfss STATUS,C goto S5E S5G clrf SUTATS btfsc S5 goto $-1 goto ATTTMR1 S5E movf POS30H,w btfss STATUS,Z goto S5F movf POS30L,w btfsc STATUS,Z goto S5G S5F movf POS30H,w movwf TPOSH movf POS30L,w movwf TPOSL goto INITCPOS ;mémorisation de la position actuelle pour la touche 30° SETPOS30 bcf INTCON,GIE comf POSH,w movwf POS30H comf POSL,w bsf INTCON,GIE movwf POS30L incf POS30L,f btfsc STATUS,Z incf POS30H,f call SAUVEEP goto S5G ;mémorisation de la vitesse actuelle pour la touche 30° SETV30 bcf INTCON,GIE comf PRESH,w movwf V30H comf PRESL,w bsf INTCON,GIE movwf V30L incf V30L,f btfsc STATUS,Z incf V30H,f call SAUVEEP goto S5G ;touche S6 S6A btfss S6 goto TS7 ;touche S6 non appuyée btfsc SUTATS,TS4 goto SETVFULL ;touche S6 appuyé plus de 4s et demande de mémorisation de la vitesse actuelle btfsc SUTATS,TS goto SETPOSFULL ;touche S6 appuyé et demande de mémorisation de la position actuelle movf VFH,w btfss STATUS,Z goto S6B ;il y a une vitesse max de programmée movf VFL,w btfsc STATUS,Z goto S6E ;pas de limite de vitesse S6B bcf INTCON,GIE ;il y a une vitesse max de programmée movf PRESH,w movwf TEMPH movf VFL,w ;VF contient le complément à 2 de la vitesse : -VMAX_Full addwf PRESL,w bsf INTCON,GIE btfsc STATUS,C ;on fait Vitesse_actuelle - VMAX_Full incf TEMPH,f movf VFH,w addwf TEMPH,w btfss STATUS,C goto S6E ;résultat négatif : vitesse assez faible > on bouge le volet S6G clrf SUTATS ;résultat positif : vitesse trop élevée > on ne fait rien btfsc S6 goto $-1 ;on attend le relachement de la touche S6 goto ATTTMR1 S6E movf POSFH,w btfss STATUS,Z ;il y a-t-il une position de mémorisée ? goto S6F movf POSFL,w btfsc STATUS,Z goto S6G ;non : on ne fait rien S6F movf POSFH,w ;oui movwf TPOSH ;on charge le comparateur avec la position à atteindre movf POSFL,w movwf TPOSL ;initialisation du mouvement des volets INITCPOS bcf INTCON,GIE ;on stope les IT pour ne pas avoir d'altération de la valeur 10bits car entre les movf POSH,w ; 2 instructions "movf" il peut il y avoir une IT qui change les valeurs POSH ou POSL. movwf TEMP ;détermination du sens du mouvement movf TPOSL,w ;soustraction POS-Position_mémorisée addwf POSL,w bsf INTCON,GIE btfsc STATUS,C incf TEMP,f movf TPOSH,w addwf TEMP,w clrf SUTATS btfsc STATUS,C bsf SUTATS,MUP ;C=1 POS-TPOS >= 0 la position actuelle des volets est plus basse que celle visée : on monte les volets ;C=0 POS-TPOS < 0 la position actuelle est plus haute que celle visée : on descend les volets bsf SUTATS,MVP ;on demande un mouvement programmé movf CLAVAI,w btfss STATUS,Z goto $-2 ;on attend le relachement des touches S1 à S8 btfss SUTATS,MUP ;on programme le sens du mouvement goto descend monte bcf INB nop bsf INA goto ATTTMR1 descend bcf INA nop bsf INB goto ATTTMR1 ;mémorisation de la position actuelle pour la touche FULL SETPOSFULL bcf INTCON,GIE comf POSH,w movwf POSFH comf POSL,w bsf INTCON,GIE movwf POSFL incf POSFL,f btfsc STATUS,Z incf POSFH,f call SAUVEEP goto S6G ;mémorisation de la vitesse actuelle pour la touche FULL SETVFULL bcf INTCON,GIE comf PRESH,w movwf VFH comf PRESL,w bsf INTCON,GIE movwf VFL incf VFL,f btfsc STATUS,Z incf VFH,f call SAUVEEP goto S6G ;touche monte ;on réduit l'angle (les volets remontent, POS se réduit) ;si la touche est active on vérifie qu'il n'y a pas de mouvement en cours ;si mouvement en cours on arrête le moteur, on redescend la puissance à 0, on fait une pause de 0.5s ;si pas de mouvement en cours on regarde si POSMIN est programmée ;si POSMIN n'est pas programmée on monte ;si POSMIN est programmée on compare avec POS ;si POS > POSMIN on monte sinon on stope le moteur TS7 btfss S7 goto TS9 btfsc SUTATS,TS goto SETPOSMIN btfss SUTATS,MVP ;il y a-t-il un mouvement programmé en en cours ? goto S7A ;non bcf SUTATS,MVP ;oui, alors on l'annule btfsc SUTATS,MUP ;était-ce un mouvement de monté ? goto S7A ;oui alors on continu call STOPMOT ;non, alors on stoppe S7A movf POSMINL,w btfss STATUS,Z goto S7B ;POSMIN est programmée movf POSMINH,w btfsc STATUS,Z goto S7D ;POSMIN=0 donc pas programmée on monte inconditionnellement S7B bcf INTCON,GIE movf POSH,w ;POSMIN est programmée, on calcule POS-POSMIN movwf TEMPH movf POSL,w ;POSMIN contient le complément à 2 de la position minimum bsf INTCON,GIE addwf POSMINL,w ;pour faire cette soustration il suffit de faire l'addition et de regarder le signe movwf TEMP btfsc STATUS,C incf TEMPH,f movf POSMINH,w addwf TEMPH,w movwf TEMPH ;TEMP contient la différence entre la position actuelle et la référence btfss STATUS,C goto TSF ;C=0 : POS-POSMIN est négatif on stope la montée S7C bsf SUTATS,MUP ;C=1 : POS-POSMIN est positif ou nul on continue de monter bsf SUTATS,MVT bsf INA nop bcf INB goto POSN ;S7 prioritaire à S8 et S9 on ne scrute pas les autres touches S7D clrf TEMPH ;on définit un résultat dans le cas ou POSMAX n'est pas programmé movlw VPCONS+1 ;pour monter à pleine vitesse movwf TEMP goto S7C ;enregistrement de la position des volets au plus haut (POS minimum = angle minimum des volets) SETPOSMIN bcf INTCON,GIE comf POSH,w movwf POSMINH comf POSL,w bsf INTCON,GIE movwf POSMINL incf POSMINL,f btfsc STATUS,Z incf POSMINH,f clrf SUTATS call SAUVEEP btfsc S7 goto $-1 goto ATTTMR1 ;touche descend ;on augmente l'angle (les volets descendent, POS augmente) ;si la touche est active on vérifie qu'il n'y a pas de mouvement en cours ;si mouvement en cours on arrête le moteur, on redescend la puissance à 0, on fait une pause de 0.5s ;si pas de mouvement en cours on regarde si POSMAX est programmée ;si POSMAX n'est pas programmée on descend ;si POSMAX est programmée on compare avec POS ;si POS > POSMAX on stope le moteur sinon on monte ;Si VMAX est dépassée on regarde la position ;si la position est > à POS 0° on descend les volets ;si la position est < à POS 0° on stope (la remonté se fera par la fonction entrée automatique) TS9 btfss S9 goto TSF btfsc SUTATS,TS4 goto SETVMAX btfsc SUTATS,TS goto SETPOSMAX btfss SUTATS,MVP goto S9A bcf SUTATS,MVP btfss SUTATS,MUP goto S9A call STOPMOT S9A movf VMAXH,w btfss STATUS,Z goto S9B ;il y a une vitesse max de programmée movf VMAXL,w btfsc STATUS,Z goto S9E ;pas de limite de vitesse S9B bcf INTCON,GIE ;il y a une vitesse max de programmée movf PRESH,w movwf TEMPH movf VMAXL,w ;VMAX contient le complément à 2 de la vitesse : -VMAX addwf PRESL,w bsf INTCON,GIE btfsc STATUS,C ;on fait Vitesse_actuelle - VMAX incf TEMPH,f movf VMAXH,w addwf TEMPH,w btfss STATUS,C goto S9E ;résultat négatif : vitesse assez faible > on bouge le volet movf POS0H,w ;résultat positif : vitesse trop élevée > on regarde si POS 0° est programmée btfss STATUS,Z goto S9J ;POS 0° programmée movf POS0L,w btfsc STATUS,Z goto TSF ;POS 0° non programmée > on arréte la descente S9J bcf INTCON,GIE ;POS 0° programmée > on regarde si POS > POS 0° movf POSH,w ; on calcule POS-POS 0° movwf TEMPH ;POS0 contient le complément à 2 de la position 0° movf POSL,w bsf INTCON,GIE addwf POS0L,w ;pour avoir le résultat de cette soustration il suffit de faire l'addition et de regarder le signe btfsc STATUS,C incf TEMPH,f movf POS0H,w addwf TEMPH,w btfss STATUS,C goto S9H ;C=1 : POS-POS 0° est négatif on continue de descendre S9I goto TSF ;C=0 : POS-POS 0° est positif ou nul on stope la descente S9G clrf SUTATS btfsc S9 goto $-1 ;on attend le relachement de la touche S9 goto ATTTMR1 S9E movf POSMAXL,w btfss STATUS,Z goto S9F ;POSMAX est programmée movf POSMAXH,w btfsc STATUS,Z goto S9K ;POSMAX=0 donc pas programmée on descend inconditionnellement S9F bcf INTCON,GIE movf POSH,w ;POSMAX est programmée, on calcule POS-POSMAX movwf TEMPH movf POSL,w ;POSMAX contient le complément à 2 de la position minimum bsf INTCON,GIE addwf POSMAXL,w ;pour faire cette soustration il suffit de faire l'addition et de regarder le signe movwf TEMP btfsc STATUS,C incf TEMPH,f movf POSMAXH,w addwf TEMPH,w movwf TEMPH btfsc STATUS,C goto TSF ;C=0 : POS-POSMAX est positif ou nul on stope la descente S9H bcf SUTATS,MUP ;C=1 : POS-POSMAX est négatif on continue de descendre bsf SUTATS,MVT bcf INA nop bsf INB goto POSC S9K clrf TEMPH ;on définit un résultat dans le cas ou POSMAX n'est pas programmé movlw VPCONS+1 ;pour descendre à pleine vitesse movwf TEMP comf TEMP,f comf TEMPH,f incf TEMP,f btfsc STATUS,Z incf TEMPH,f goto S9H ;enregistrement de la position des volets au plus bas (POS maximum = angle maximum des volets) SETPOSMAX bcf INTCON,GIE comf POSH,w movwf POSMAXH comf POSL,w bsf INTCON,GIE movwf POSMAXL incf POSMAXL,f btfsc STATUS,Z incf POSMAXH,f clrf SUTATS call SAUVEEP goto S9G ;mémorisation de la vitesse actuelle pour la touche DOWN SETVMAX bcf INTCON,GIE comf PRESH,w movwf VMAXH comf PRESL,w bsf INTCON,GIE movwf VMAXL incf VMAXL,f btfsc STATUS,Z incf VMAXH,f call SAUVEEP goto S9G ;fin de la gestion des touches mémoires, UP et DOWN TSF btfsc SUTATS,MVP goto MVPGM ;mouvement programmé en cours btfss SUTATS,MVT goto TSS clrf SUTATS ;aucune touche de mouvement appuyée call STOPMOT ;on stope le moteur goto TSS ;mouvement programmé en cours MVPGM bcf INTCON,GIE movf POSH,w ;soustraction POS-TPOS movwf TEMPH movf POSL,w bsf INTCON,GIE addwf TPOSL,w movwf TEMP btfsc STATUS,C incf TEMPH,f movf TPOSH,w addwf TEMPH,w movwf TEMPH btfsc STATUS,C goto POSI ;C=1 POS-TPOS >= 0 la position actuelle est plus basse que celle visée POSS btfss SUTATS,MUP ;C=0 POS-TPOS < 0 la position des volets actuelle est plus haute que celle visée goto POSC ;si le mouvement est à la baisse on continue de descendre POSF call STOPMOT ;si le mouvement est à la hausse on stope le mouvement clrf SUTATS goto ATTTMR1 POSI btfss SUTATS,MUP ;la position actuelle est plus basse que celle visée goto POSF ;si le mouvement est à la baisse on stope le mouvement ;si le mouvement est à la hausse on continue de monter ;on ralentie à proximité du point de consigne ;POS - TPOS est positif > on le rend négatif POSN incf TEMP,f ;on incrémente de 1 pour éviter le cas particulier du résultat 0 btfsc STATUS,Z incf TEMPH,f comf TEMP,f ;par un complément comf TEMPH,f incf TEMP,f ;à 2 si <> 0 btfsc STATUS,Z incf TEMPH,f ;VPCONS + (POS - TPOS) définit le seuil de changement de puissance POSM movlw VPCONS addwf TEMP,w btfss STATUS,C goto POSJ ;résultat négatif on incrémente la puissance incf TEMPH,w btfss STATUS,Z goto POSJ ;résultat négatif POSK movlw VPDEC ;résultat positif on fixe la puissance movlb .6 ;bank6 movwf CCPR3L movlb .0 ;bank0 goto ATTTMR1 POSJ call PINCMOT goto ATTTMR1 POSC ;si le mouvement est à la baisse on continue de descendre ;POS - TPOS est négatif ;VPCONS + (POS - TPOS) définit le seuil de changement de puissance movlw VPCONS addwf TEMP,w btfss STATUS,C goto POSJ ;résultat négatif on incrémente la puissance incf TEMPH,w btfss STATUS,Z goto POSJ ;résultat négatif goto POSK ;résultat positif on fixe la puissance ;touche SET TSS btfss S8 goto TSA0 btfsc SUTATS,TS goto TSA1 ;la touche SET était déjà enfoncée bsf SUTATS,TS ;la touche SET vient d'être enfoncée on initialise le chronomètre clrf SECONDE clrf MINUTE goto ATTTMR1 TSA1 btfsc SECONDE,4 bsf SUTATS,TS4 ;la touche SET est enfoncée de plus de 4s btfsc SECONDE,7 bsf SUTATS,TS8 ;la touche SET est enfoncée de plus de 8s goto ATTTMR1 TSA0 btfsc SUTATS,TS8 ;aucune touche appuyée, est-ce que S8 l'a été ? goto MEMRESET ;la touche S8 a été enfoncé plus de 8s : effacement des mémoires btfss SUTATS,TS goto ATTTMR1 ;S8 n'a pas été appuyée btfss MINUTE,0 ;S8 a été appuyée goto ATTTMR1 ;la touche SET a été enfoncé clrf SUTATS ;mais il y a plus de 16s alors on annule la fonction clrf SECONDE clrf MINUTE goto ATTTMR1 END