Double Variateur pour moteurs à courant continu
avec un PIC 16F628
(pour hélico

  • Je décris ci-dessous une réalisation qui me donne satisfaction, sachant que je ne suis plus vraiment débutant en électronique. Ce montage est alimenté par un accu Lithium Polymère. Ces accus sont extraordinaires de capacité et de légèreté, mais sont réputés dangereux dans des mains peu expertes. Ils peuvent exploser ou prendre feu en cas de court-circuit ou de surcharge.
  • Ce variateur, au contraire de celui proposé par le constructeur du "petit hélico indoor" bien connu (mais dont je ne citerai par la marque...) ne comporte PAS de gyroscope électronique. Autrement dit, si vous n'êtes pas pilote hélico RC confirmé, c'est le crash assuré !

Donc je montre ici ce que je fais, mais je ne vous encourage pas à en faire autant, c'est vous qui voyez. 

Si vous n'êtes pas expert, je vous conseille d'acheter un variateur double + gyro tout fait, on en trouve à 20 euros.

Bon, pour ceux qui ne sont pas partis, je vous raconte la suite:


1 L'hélico à propulsion électrique sur lequel j'ai monté ce variateur:

2 Le variateur en CMS (composants miniature pour montage en surface, SMD en anglais)

3 -

On distingue les deux transistors MOSFET IRF7455 (dans des boîtiers de 'circuits intégrés') qui découpent la tension d'alimentation de l'accu LiPO afin d'alimenter le moteur avec un rapport cyclique variable, ainsi que le microcontrôleur PIC16F628. Le régulateur LM2940 (Low drop-out) qui parait énorme donne l'échelle.

Masse: 7g (sans les fils)

4 Schéma du variateur:

5 Le firmware en langage PIC Microchip

CODE SOURCE en assembleur PIC
  1. ;choisir Tab Size = 10 dans les options de l'editeur de MPLAB IDE
  2. ;pour obtenir un alignement correct du listing
  3. ;
  4. ;si vous visualisez avec Wordpad, vous aurez des soucis d'alignement...
  5. ;choisissez dans les options de Wordpad "pas de retour a la ligne"
  6. ;sinon les longues lignes de commentaires seront tronquees
  7. ;et passeront dans les colonnes etiquettes et code
  8. ;**********************************************************************
  9. ;
  10.  
  11. ;
  12. ;
  13. ;LISTE DES PRINCIPALES PROCEDURES: (Double-clic sur 1 mot puis F3 dans MPLAB, c'est pratique...)
  14. ;TESTS
  15. ;MACROS
  16. ;mot16A macro ;charge AH et AL avec le mot code sur 16 bits transmis
  17. ;mot16B macro ;charge BH et BL avec le mot code sur 16 bits transmis
  18. ;Changements de banques
  19. ;R_EEPROM
  20. ;W_EEPROM
  21. ;CONSTANTES
  22. ;VARIABLES_EN_BANQUE0
  23.  
  24. ;INITIALISATION DES PORTS
  25. ;PROGRAMMATION DU REGISTRE OPTION (BANK1)
  26. ;PROG DU REGISTRE INTCON (BANK0)
  27. ;PROG DU REGISTRE T1CON (BANK0)
  28. ;PROG DU REGISTRE T2CON (BANK0)
  29. ;PROG DU REGISTRE PR2 (BANK1)
  30. ;PROG DU REGISTRE PIE1 (BANK1)
  31.  
  32. ;Initialisation_des_variables
  33.  
  34. ;BOUCLE_PRINCIPALE
  35.  
  36. ;inttimer0 -> le Timer0 est utilise au sein de l'INT portB0 (voir plus bas) pour mesurer la duree PPM voie GAZ
  37. ;inttimer1 -> le Timer1 est utilise dans l'INT portB4-7 (voir plus bas) pour mesurer la duree PPM voie ANTI-COUPLE
  38. ;inttimer2 -> generation du signal de sortie
  39. ;intB0
  40. ;intB5
  41.  
  42.  
  43. ;convhbin ;conversion sexadecimale -> binaire ;entree: AA, BB ;resultat: AH,AL = 60*AA+BB
  44. ;multi ;mutiplication 8 bits x 8 bits de AA par w (donnees sur 1 octet) ;resultat (sur 2 octets) dans AH,AL
  45. ;divi2 ;division d'une valeur codee sur 16 bits (AH,AL) par 2
  46. ;divi60 ;division d'une valeur codee sur 16 bits (AH,AL) par 60 ;resultat dans w ;reste de la division dans (BH,BL)
  47. ;add16A ;addition 16bits resultat dans A ;(AH,AL)+(BH,BL) -> (AH,AL)
  48. ;add16B ;addition 16bits resultat dans B ;(AH,AL)+(BH,BL) -> (BH,BL)
  49. ;cpl16x ;complement a deux de la variable codee sur 2 octets situes aux adresses w et w+1 permet les soustractions
  50. ;compa16p ;comparaison de deux valeurs codees sur 16 bits (AH,AL a BH,BL) ;resultat dans STATUS carry et zero
  51. ;movxA ;mov la variable codee sur 2 octets situes aux adresses w et w+1 dans -> AH,AL
  52. ;movAx ;mov AH,AL dans -> la variable codee sur 2 octets situes aux adresses w et w+1
  53. ;movxB ;mov la variable codee sur 2 octets situes aux adresses w et w+1 dans -> BH,BL
  54. ;movBx ;mov BH,BL dans -> la variable codee sur 2 octets situes aux adresses w et w+1
  55.  
  56. ;procedures d'affichage LCD
  57.  
  58. ;cvBDU ;CONVERSION BINAIRE(1) (1 octet incomplet 0..99 et pas 0..255) --> BCD ;nombre a convertir dans AA
  59. ;cvBCU ;CONVERSION BINAIRE(2) (1 octet complet 0..255) --> BCD ;resultat dans BB (centaines) et dans AA (unites)
  60.  
  61. ;tp154us
  62. ;tp1ms
  63. ;tp2ms
  64. ;tp10ms
  65. ;tp100ms
  66.  
  67. ;vari_vit
  68.  
  69. ;TABLEAUX
  70. ;
  71. ;
  72. ; ;pour Qx=20,000 Mhz
  73. ;
  74. ;
  75. ;
  76. ;
  77.  
  78. ;***********************************************************************************************
  79. ; VARIATEUR pour moteur DC (pour helico Piccolo) : variat2_05.asm
  80. ; pour PIC16F628
  81. ; par Silicium 628
  82. ;************************************************************************************************
  83. ;derniere mise a jour: 29/05/2005
  84. ;remarque: suite aux modifications (=ameliorations!) certains commentaires peuvent se reveler faux !!!
  85. ;j'en suis desole. Je relis regulierement les commentaires et essaye de les tenir a jour.
  86. ;toutefois il m'arrive de trouver des enormites ! que je corrige...
  87. ;------------------------------------------------------------------------------------------------
  88.  
  89.  
  90.  
  91.  
  92. ;*********************************************** PRINCIPE *****************************************
  93. ;int Exterieure par bit 0 du port B sert a detecter les fronts du signal PPM du recepteur de radio-commande
  94. ;on en deduit sa duree (1 a 2,2 ms)
  95.  
  96.  
  97.  
  98. ;******************************** REMARQUES GENERALES *********************************************
  99.  
  100. ;representation d'un nombre hexadecimal: commence par "0x" ex: 0x20
  101. ;representation d'un nombre decimal: commence par "." ex: .20
  102. ; ex: 0x20 = .32
  103. ; B'00010000' represente une valeur binaire
  104. ;Utiliser une version recente de MPLAB afin que le PIC16F628 soit pris en compte (ma version= 5.70.00 )
  105. ;voir sur le site de Microchip(R): http://www.microchip.com
  106.  
  107. ;***************************************************************************************************
  108.  
  109. ;----------------------------------------------------------------------
  110.  
  111. list p=16f628 ; list directive to define processor
  112. #include <p16f628.inc> ; processor specific variable definitions
  113.  
  114.  
  115. __CONFIG _CP_OFF & _WDT_OFF & _BODEN_ON & _PWRTE_ON & _HS_OSC & _MCLRE_ON & _LVP_OFF
  116.  
  117.  
  118. ; '__CONFIG' precise les parametres encodes dans le processeur au moment de
  119. ; la programmation du processeur. Les definitions sont dans le fichier include.
  120. ; Voici les valeurs et leurs definitions :
  121. ; _CP_ON Code protection ON : impossible de relire
  122. ; _CP_OFF Code protection OFF
  123.  
  124. ; _PWRTE_ON Timer reset sur power on en service
  125. ; _PWRTE_OFF Timer reset hors-service
  126.  
  127. ; _WDT_ON Watch-dog en service
  128. ; _WDT_OFF Watch-dog hors service
  129.  
  130. ; _LP_OSC Oscillateur quartz basse vitesse (32<F<200Khz)
  131. ; _XT_OSC Oscillateur quartz moyenne vitesse (200Khz<F<4Mhz)
  132. ; _HS_OSC Oscillateur quartz grande vitesse (4Mhz<F<20Mhz)
  133. ; _RC_OSC Oscillateur a reseau RC
  134.  
  135. ; Reset du PIC si tension <4V
  136. ; ------------------------------
  137. ; _BODEN_ON Reset tension en service Valide PWRTE_ON automatiquement
  138. ; _BODEN_OFF Reset tension hors service
  139.  
  140. ; Programmation sur circuit
  141. ; -------------------------
  142. ; _LVP_ON RB4 permet la programmation serie du PIC
  143. ; _LVP_OFF RB4 en utilisation normale
  144.  
  145.  
  146. ;
  147. ; "departRam equ 0x20"
  148. ;----------------------------------------------------------------------
  149.  
  150. ;*****************************************************************************
  151. ; MACROS *
  152. ;*****************************************************************************
  153.  
  154. mot16A macro mot16 ;charge AH et AL avec le mot code sur 16 bits transmis
  155. movlw low mot16
  156. movwf AL
  157. movlw high mot16
  158. movwf AH
  159. endm
  160.  
  161. mot16B macro mot16 ;charge BH et BL avec le mot code sur 16 bits transmis
  162. movlw low mot16
  163. movwf BL
  164. movlw high mot16
  165. movwf BH
  166. endm
  167.  
  168.  
  169. ; Changements de banques
  170.  
  171. BANK0 macro ; passer en banque0
  172. bcf STATUS,RP0
  173. bcf STATUS,RP1
  174. endm
  175.  
  176. BANK1 macro ; passer en banque1
  177. bsf STATUS,RP0
  178. bcf STATUS,RP1
  179. endm
  180.  
  181. BANK2 macro ; passer en banque2
  182. bcf STATUS,RP0
  183. bsf STATUS,RP1
  184. endm
  185.  
  186. BANK3 macro ; passer en banque3
  187. bsf STATUS,RP0
  188. bsf STATUS,RP1
  189. endm
  190.  
  191. ; lire eeprom (adresse et resultat en w)
  192. R_EEPROM macro
  193. clrwdt
  194. bsf STATUS,RP0 ; Bank 1
  195. movwf EEADR ; Adresse to read
  196. bsf EECON1,RD ; ordre de lecture
  197. movf EEDATA,w ; W = EEDATA
  198. bcf STATUS,RP0 ; Bank 0
  199. endm
  200.  
  201. ;ecriture en EEPROM (adresse dans DDD (commun 4 banques), data dans w)
  202. W_EEPROM macro
  203. clrwdt
  204. LOCAL loop
  205. bsf STATUS,RP0 ; Bank 1
  206. movwf EEDATA ; Data to write
  207. ; movlw adress1 ; adresse passee en parametre a la macro (moins souple que par registre)
  208. movf DDD,w ; adresse passee par registre DDD, commun aux 4 banques
  209. movwf EEADR
  210. bsf EECON1, WREN ; Enable Write
  211. bcf INTCON, GIE ; Disable INTs
  212. movlw 0x55
  213. movwf EECON2 ; Write 55
  214. movlw 0xAA
  215. movwf EECON2 ; Write AA
  216. bsf EECON1, WR ; lancer cycle d'ecriture
  217. bsf INTCON, GIE ; reautoriser INTs
  218.  
  219. loop clrwdt
  220. btfsc EECON1 , WR ; tester si ecriture terminee
  221. goto loop ; non, attendre
  222. bcf EECON1 , WREN ; verrouiller prochaine ecriture
  223. bcf STATUS , RP0 ; passer en banque0
  224. endm
  225.  
  226. ;*****************************************************************************
  227. ;CONSTANTES
  228.  
  229. w equ 0
  230. f equ 1
  231.  
  232. RESET_V equ 0x0000 ; adresse du vecteur de reset
  233. ISR_V equ 0x0004 ; adresse du vecteur d'interruption general
  234.  
  235.  
  236.  
  237. ;----------------------------------------------------------------------
  238.  
  239. ;VARIABLES_EN_BANQUE0
  240. ;le PIC16F628 possede 224 octets de RAM repartis en 3 emplacements (96+80+48 octets)
  241. ;ici premiere banque de 96 octets, debut a l'adresse 0x20
  242. ;verifier sur le listing absolu que la derniere adresse soit < 7Fh
  243. ;L'utilisation de CBLOCK permet de permutter facilement les variables (par rapport a "equ" )
  244.  
  245. CBLOCK 0x20 ;debut de la zone RAM utilisateur de 96 octets en banque 0
  246. AA : 1 ;registre de travail
  247. BB : 1 ;registre de travail
  248. CC : 1 ;registre de travail
  249. DD : 1 ;registre de travail
  250.  
  251. AH : 1 ;registre de travail poids fort
  252. AL : 1 ;registre de travail poids faible
  253. BH : 1 ;registre de travail poids fort
  254. BL : 1 ;registre de travail poids faible
  255.  
  256. count0 : 1 ;
  257. count1 : 1 ;utilise dans la multiplication 8bits x 8bits
  258. count2 : 1 ;utilise dans la procedure vari_vit
  259.  
  260. dtlcd : 1 ;data vers afficheur LCD
  261.  
  262. aff1 : 1
  263. aff2 : 1
  264. aff3 : 1
  265. aff4 : 1
  266.  
  267. bitn : 1
  268.  
  269. t1 : 1 ;pour les tempos
  270. t2 : 1 ;pour les tempos
  271. t3 : 1 ;pour les tempos
  272.  
  273. rapcyc1 : 1 ;pour faire varier le rapport cyclique du signal de sortie voie ANTI-COUPLE
  274. rapcyc2 : 1 ;pour faire varier le rapport cyclique du signal de sortie voie GAZ
  275. butcyc2 : 1
  276.  
  277. T_PPM_G : 1 ;temps (duree) du signal PPM (voie des GAZ en sortie du recepteur de radiocommande)
  278. T_PPM_A : 1 ;temps (duree) du signal PPM (voie des ANTI-COUPLE en sortie du recepteur de radiocommande)
  279.  
  280. memo1 : 1 ;variable locale
  281. memo2 : 1 ;variable locale
  282.  
  283. adrEE : 1 ;pour memoriser en EEPROM
  284.  
  285.  
  286. ;voir fonctionnement des timer pour l'explication du 255-...
  287.  
  288. mesflags : 1 ;8 flags perso divers
  289. ;b0: stop moteur principal (GAZ) par ordre emis par la radio-commande (trim des gaz en bas...)
  290. ;b1: phase du signal de sortie voie ANTI-COUPLE (Timer1)
  291. ;b2: phase du signal de sortie voie GAZ (Timer2)
  292. ;b3:
  293. ;b4: memorise si front montant/descendant en cours sur l'entree RB0
  294. ;b5:
  295. ;b6:
  296. ;b7:
  297.  
  298. ENDC ; Fin de la zone
  299.  
  300.  
  301. ;----------------------------------------------------------------------
  302. ; VARIABLES ZONE COMMUNE
  303. ; Zone de 16 bytes
  304. CBLOCK 0x70 ;Debut de la zone (0x70 a 0x7F)
  305. WW : 1 ;pour sauvegarder w pendant INT
  306. STUS_TMP : 1 ;pour sauvegarder STATUS pendant INT
  307. FSR_temp : 1 ;sauvegarde FSR (si indirect en interrupt)
  308. PLATH_tmp : 1
  309.  
  310. DDD : 1 ;registre d'adresses commun
  311.  
  312. ENDC ; Fin de la zone
  313.  
  314. ;----------------------------------------------------------------------
  315. ;VARIABLES EN BANQUE1 accessible avec IRP=0 si adressage indirect
  316. CBLOCK 0xA0 ;=.160 debut de la zone RAM utilisateur de 80 octets en banque 1
  317.  
  318. ENDC ;Fin de la zone
  319. ;----------------------------------------------------------------------
  320.  
  321. ORG RESET_V ; Vecteur de RESET
  322. RESET goto start
  323.  
  324.  
  325. ;***********************************************************************
  326. ; TRAITEMENT DES INTERRUPTIONS (Aiguillage vers routines)
  327. ;***********************************************************************
  328.  
  329. ;ici INT par le Timer 0
  330. ;RAPPEL Un seul vecteur d'interruption, d'adresse 004 est diponible
  331. ;Quelle que soit la cause de l'interruption, le PC est donc charge par 004
  332. ;a vous ensuite de tester les differents indicateurs pour savoir quel est la source de l'INT.
  333. ;voir le registre INTCON
  334.  
  335. ORG ISR_V ; Vecteur d'Interruption
  336.  
  337. movwf WW
  338. swapf STATUS,w
  339. movwf STUS_TMP
  340. movf FSR , w
  341. movwf FSR_temp
  342. movf PCLATH , w ;charger PCLATH
  343. movwf PLATH_tmp ;le sauver
  344. clrf PCLATH ;on est en page 0
  345. BANK0 ;passer en banque0
  346.  
  347. intRB0 btfss INTCON,1 ;test FLAG INT exterieure bit 0 du port B
  348. goto intRB5 ;non suite
  349. call intB0 ;oui, traiter interrupt PORTB,0
  350. bcf INTCON,1 ;effacer flag interupt portB: reautorise interruption PORTB,0
  351. goto restorREG
  352.  
  353. intRB5 btfss INTCON,0 ;test FLAG INT exterieure bits 4 a 7 du port B
  354. goto intTMR1 ;non suite
  355. call intB5 ;oui, traiter interrupt PORTB,0
  356. bcf INTCON,0 ;effacer flag interupt portB: reautorise interruption PORTB,0
  357. goto restorREG
  358.  
  359.  
  360. intTMR1 btfss PIR1,TMR1IF ;test FLAG timer1
  361. goto intTMR0 ;non test suivant
  362. call inttimer1 ;oui, traiter interrupt timer1
  363. bcf PIR1,TMR1IF ;reautorise l'INT par Timer1
  364. goto restorREG
  365.  
  366. intTMR0 btfss INTCON,2 ;test FLAG timer0
  367. goto intTMR2 ;non suite
  368. call inttimer0 ;oui, traiter interrupt timer0
  369. bcf INTCON,2 ;effacer flag interupt timer: reautorise l'INT Timer0
  370. goto restorREG
  371.  
  372. intTMR2 btfss PIR1,TMR2IF ;test FLAG timer2
  373. goto restorREG ;non suite...
  374. call inttimer2 ;oui, traiter interrupt timer2
  375. bcf PIR1,TMR2IF ;reautorise l'INT par Timer2
  376. goto restorREG
  377.  
  378.  
  379. restorREG movf PLATH_tmp, w ;recharger ancien PCLATH
  380. movwf PCLATH
  381. movf FSR_temp,w
  382. movwf FSR
  383. swapf STUS_TMP,w ;swap STATUS_TMP, resultat dans w
  384. movwf STATUS ;restaurer status
  385. swapf WW,f ;Inversion L et H de l'ancien W sans modifier Z
  386. swapf WW,w ;Re-inversion de L et H dans W
  387.  
  388. retfie ;remet GIE a 1 puis return
  389.  
  390.  
  391. ;***********************************************************************
  392. ; START START START START START START START START START START START
  393. ;***********************************************************************
  394.  
  395. org ISR_V+.60
  396.  
  397. start clrwdt
  398. bcf STATUS,IRP ;pour l'adressage indirect
  399. ;IRP: Register Bank Select bit (used for indirect addressing)
  400. ;=0 -> Bank 0, 1 (00h - FFh)
  401. ;=1 -> Bank 2, 3 (100h - 1FFh)
  402.  
  403. BANK0 ;pour l'adressage direct
  404.  
  405. ;***********************************************************************
  406. ;ZONE de TESTS de procedures
  407.  
  408. ; mot16B .61000
  409. ; movlw .335
  410. ; call divi16_8
  411. ; nop
  412.  
  413. ; movlw .200
  414. ; movwf rapcyc2 ;G
  415.  
  416. ;la movlw .255
  417. ; movwf BB ;mancheAC
  418. ; call calc_AC
  419.  
  420. ; movlw .10
  421. ; addwf rapcyc2,f
  422. ; goto la
  423.  
  424.  
  425.  
  426.  
  427.  
  428.  
  429. ;***********************************************************************
  430.  
  431. call tp100ms
  432.  
  433. clrwdt
  434.  
  435.  
  436. ;***********************************************************************
  437. ; INITIALISATION DES PORTS
  438. ;***********************************************************************
  439.  
  440. ;RA0=entree: signal du capteur magnetique (detection de la phase du rotor)
  441. ;RA1=entree: signal en provenance du circuit de detection de vitesse faible ou nulle suite a decrochage du moteur
  442. ;RA2=entree: detection tension alim faible ( "BEC" )
  443. ;RA3=sortie: LED alim faible
  444. ;RA3=
  445.  
  446. ;RB0=entree: signal PPM du recepteur de radio-commande, voie 'gaz'
  447. ;RB1=
  448. ;RB2=sortie: commande MOSFET canal N
  449. ;RB3=
  450. ;RB4=
  451. ;RB5=s
  452. ;RB6=s
  453. ;RB7=
  454.  
  455. BANK0
  456. movlw 0x07
  457. movwf CMCON ; PORT A en E/S numeriques (BANK0)
  458.  
  459. BANK1
  460. movlw B'00000000' ;0=sortie 1=entree attention RA4 =drain ouvert
  461. movwf TRISA ;config du port A (TRISA en page 1)
  462. movlw B'00101001'
  463. movwf TRISB ;config du port B
  464.  
  465. bcf OPTION_REG,7 ;Enable PORTB pull-ups
  466.  
  467. ;----------------------------------------------------------------------
  468. ;PROGRAMMATION DU REGISTRE OPTION (BANK1) - voir datasheet p:20 du datasheet PIC16F62X.pdf
  469.  
  470. ;bit7: RBPU =0 -> R tirage a Vdd du port B
  471. ;bit6: INTEDG=1 -> INT sur front montant ou descendant de RB0
  472. ; 1 = Interrupt on rising edge of RB0/INT pin
  473. ; 0 = Interrupt on falling edge of RB0/INT pin
  474.  
  475. ;bit5: T0CS = 0 -> TMR0 Clock Source Select bit
  476. ; 1 = Transition on RA4/T0CKI pin (Fonctionnement en mode compteur)
  477. ; 0 = Internal instruction cycle clock (CLKOUT) (Fonctionnement en mode timer)
  478.  
  479. ;bit4: RTE = 0 -> inc sur front montant
  480.  
  481. ;bti3: PSA = 0 -> prediv affecte au timer0
  482. ;bits2,1,0:PS2,1,0
  483. ;Bit Value TMR0 Rate WDT Rate
  484. ;000 1 : 2 1 : 1
  485. ;001 1 : 4 1 : 2
  486. ;010 1 : 8 1 : 4
  487. ;011 1 : 16 1 : 8
  488. ;100 1 : 32 1 : 16
  489. ;101 1 : 64 1 : 32 ***** ICI 100b -> Timer0 = 1/64 *****
  490. ;110 1 : 128 1 : 64
  491. ;111 1 : 256 1 : 128
  492.  
  493. BANK1
  494. ; nº bits: '76543210'
  495. movlw B'01000101'
  496. movwf OPTION_REG
  497.  
  498.  
  499. ;----------------------------------------------------------------------
  500. ;PROG DU REGISTRE INTCON (BANK0) - voir datasheet p:21
  501. ;bit7 GIE =0 -> INT GLOBALE interdite. (voir + bas)
  502. ;bit6 PEIE=1 -> INT PERIPHERIQUES autorisees. (timer1 en fait partie)
  503. ;bit5 T0IE=0 -> INT par debordement Timer0 autorisee.
  504. ;bit4 INTE=0 -> INT de RB0/INT autorisees (INTERRUPTIONS EXTERNES)
  505. ;bit3 RBIE=1 -> INT du port RB4 a RB7 autorisees.
  506. ;bit2 T0IF=x (flag mis a 1 par debordement du Timer0)
  507. ;bit1 INTF=x (flag mis a 1 par une INT provoquee par la libne RB0/INT du port B)
  508. ;bit0 RBIF=x (flag mis a 1 si changement d'etat des entrees RB4 a RB7 du port B. attention RB1 a RB3 -> pas d'INT)
  509.  
  510. BANK0
  511. ; nº bits: '76543210'
  512. movlw B'01111000'
  513. movwf INTCON
  514.  
  515.  
  516. ;----------------------------------------------------------------------
  517. ;PROG DU REGISTRE T1CON (BANK0)
  518. ;bit7 : Inutilise : lu comme « 0 »
  519. ;bit6 : Inutilise : lu comme « 0 »
  520. ;bit5 : T1CKPS1 : Timer 1 oscillator ClocK Prescale Select bit 1
  521. ;bit4 ; T1CKPS0 : Timer 1 oscillator ClocK Prescale Select bit 0
  522. ;bit3 : T1OSCEN : Timer 1 OSCillator ENable control bit (oscillateur interne)
  523. ;bit2 : T1SYNC : Timer 1 external clock input SYNChronisation control bit
  524. ;bit1 : TMR1CS : TiMeR 1 Clock Source select bit (0=internal clock)
  525. ;bit0 : TMR1ON : TiMeR 1 ON bit
  526.  
  527. BANK0
  528. ; nº bits: '76543210'
  529. movlw B'00110001' ;prescale Timer1=1/8
  530. movwf T1CON
  531.  
  532. ;----------------------------------------------------------------------
  533.  
  534. ;PROG DU REGISTRE T2CON (BANK0)
  535.  
  536. ;bit 7: Unimplemented: Read as '0'
  537. ;bit 6-3: TOUTPS3:TOUTPS0: Timer2 Output Postscale Select bits
  538. ;0000 = 1:1 Postscale
  539. ;0001 = 1:2 Postscale
  540. ;0010 = 1:3 Postscale
  541. ;0011 = 1:4 Postscale
  542. ;0100 = 1:5 Postscale etc... (valeur binaire +1)
  543. ;1111 = 1:16 Postscale
  544.  
  545. ;bit 2: TMR2ON: Timer2 On bit =1 : Timer2 is on
  546. ;bit 1-0: T2CKPS1:T2CKPS0: Timer2 Clock Prescale Select bits
  547. ;00 = Prescaler = 1
  548. ;01 = Prescaler = 4
  549. ;1x = Prescaler = 16 (valeur choisie ici)
  550.  
  551. BANK0
  552. ; nº bits: '76543210'
  553. movlw B'00000110'
  554. movwf T2CON
  555.  
  556. ;----------------------------------------------------------------------
  557. ;PROG DU REGISTRE PR2 (BANK1)
  558. ;utilise par timer2
  559. BANK1
  560. movlw .64
  561. movwf PR2
  562.  
  563. ;----------------------------------------------------------------------
  564. ;PROG DU REGISTRE PIE1 (BANK1)
  565. ;bit7 : PSPIE b7 : Toujours 0 sur PIC 16F876
  566. ;bit6 : ADIE : masque int convertisseur A/D
  567. ;bit5 : RCIE : masque int reception USART
  568. ;bit4 : TXIE : masque int transmission USART
  569. ;bit3 : SSPIE : masque int port serie synchrone
  570. ;bit2 : CCP1IE: masque int CCP1
  571. ;bit1 : TMR2IE: masque int TMR2 = PR2
  572. ;bit0 : TMR1IE: masque int debordement tmr1
  573.  
  574. BANK1
  575. ; nº bits: '76543210'
  576. movlw B'00000011' ;enable INT TIMER1 - enable INT TIMER2 - disable int reception USART (port serie)
  577. movwf PIE1
  578.  
  579.  
  580. ;----------------------------------------------------------------------
  581.  
  582. ;Initialisation_des_variables
  583.  
  584. initvar clrwdt
  585. BANK0
  586.  
  587. movlw B'00000001' ;STOP moteur !
  588. movwf mesflags
  589.  
  590. clrf count2
  591. clrf DDD
  592.  
  593. movlw .200
  594. movwf TMR0
  595.  
  596. clrf TMR1L
  597. clrf TMR1H
  598.  
  599. movlw .128
  600. movwf TMR2
  601.  
  602. movlw .5
  603. movwf T_PPM_G
  604. movlw .128
  605. movwf T_PPM_A
  606.  
  607. movlw .1
  608. movwf rapcyc1
  609. movwf rapcyc2
  610.  
  611. bsf INTCON, GIE ;->INT GLOBALE autorisee
  612.  
  613.  
  614. ;-----------------------------------------------------------------------
  615. ; clrwdt
  616.  
  617. ;RAZ LCD
  618. ; call dspclr
  619. ; call home
  620. ; call fset
  621. ; call setmod0
  622. ; call dsp10
  623.  
  624. ; movlw "V"
  625. ; call ecrire
  626. ; movlw "a"
  627. ; call ecrire
  628. ; movlw "r"
  629. ; call ecrire
  630. ; movlw "i"
  631. ; call ecrire
  632. ; movlw "a"
  633. ; call ecrire
  634. ; movlw "t"
  635. ; call ecrire
  636. ; call tp100ms
  637.  
  638.  
  639. ;------------------------------------------------------------------------------------------------------------------
  640. ;BOUCLE_PRINCIPALE
  641.  
  642. boucle1 BANK0
  643.  
  644. call tp10ms ;DETERMINE LA VITESSE DE REPONSE
  645.  
  646. ; btfss PORTB,3
  647. ; call ecrireEE ;pour test uniquement
  648.  
  649. ;CES AFFICHAGES SONT DESTINES A UN AFFICHEUR LCD INTERFACE SUR LE PORT A
  650. ;pour la phase de mise au point uniquement. (Ralentit la reponse globale)
  651.  
  652. ; movlw 00h ;affiche en ligne1 du LCD
  653. ; call ddras
  654. ; movf rapcyc2,w
  655. ; call affiw
  656. ; movlw 40h ;affiche en ligne2 du LCD
  657. ; call ddras
  658. ; comf rapcyc1,w
  659. ; call affiw
  660.  
  661. ;------------------------------------------------------------------------------------------------------------------
  662. ;ajustement du rapport cyclique en fonction du signal ' VOIE GAZ'
  663. ;T_PPM est calcule dans la procedure duree du signal PPM VOIE GAZ
  664. ;(T_PPM = 84..173 avec un Qx=20MHz)
  665.  
  666.  
  667. ;arret moteur en dessous d'une valeur palier
  668.  
  669. movlw .88 ;valeur de T_PPM au dessous de laquelle on va stopper le moteur
  670. subwf T_PPM_G,w ;w:= T_PPM - 88 (result -> w : ne touche pas a T_PPM)
  671. btfsc STATUS,0 ;c=0 ? (c=0 si f < 5 )
  672. goto test2
  673. bsf mesflags,0 ;oui: ARRET D'URGENCE (si manche + trim gaz au mini)
  674. goto tppm1
  675.  
  676. test2 movlw .5 ;valeur de rapcyc2 au dessous de laquelle on va stopper le moteur
  677. subwf rapcyc2,w ;w:= rapcyc2 - 5 (result -> w : ne touche pas a rapcyc2)
  678. btfss STATUS,0 ;c=0 ? (c=0 si f < 5 )
  679. goto stop ;oui
  680. goto go ;non
  681.  
  682. stop bsf mesflags,0 ;oui: STOP
  683. ; clrf butcyc2
  684. ; clrf rapcyc2
  685. goto tppm1
  686.  
  687. go btfsc STATUS,0 ;meme question
  688. bcf mesflags,0 ;non: pas STOP
  689.  
  690. ;calcul du rapport cyclique
  691. tppm1 movf T_PPM_G,w
  692. movwf memo1
  693. movlw .84 ; T_PPM_G mini CETTE VALEUR EST A AJUSTER EN FONCTION DE VOTRE RADIO
  694. subwf memo1,f ; T_PPM_G:= T_PPM_G - 84 (pre-ofset)
  695. btfss STATUS,0 ;debordement ?
  696. clrf memo1 ;oui
  697. rlf memo1,w ; w:= 2 x T_PPM_G
  698. addwf memo1,w ; w:= 3 x T_PPM_G
  699. btfsc STATUS,0 ;debordement ? (result > 255 ?)
  700. movlw .253 ;oui, butee haute
  701. movwf butcyc2
  702.  
  703. ;calibrage final
  704. movlw .253 ;valeur max de rapcycl admissible (attention: si > 253 -> int Timer2 = HS)
  705. ;avec prediv =1/16 (voir T2CON)
  706. subwf butcyc2,w ;w:= rapcycl - 240 (result -> w : ne touche pas a rapcycl) d=f-w
  707. btfss STATUS,0 ;c=0 ? rapcycl < 240 ? (c=0 si w > f )
  708. goto fincal ;oui
  709. movlw .253 ;non alors on bloque a butee max
  710. movwf butcyc2
  711.  
  712. fincal nop
  713. ;progressivite de la reponse (pour eviter de casser les dents de la roue dentee en plastique sur l'arbre rotor)
  714. ;on fait tendre progressivement rapcyc2 vers butcycl2
  715. ;-------------------------------
  716. rapvari movf rapcyc2,w
  717. subwf butcyc2,w
  718. btfsc STATUS,2 ;z
  719. goto finrapv
  720. btfss STATUS,0 ;c
  721. goto moins
  722. goto plus
  723.  
  724. moins decf rapcyc2,f
  725. ; movlw .2
  726. ; call tx10ms ;decroissance lente
  727. goto finrapv
  728.  
  729. plus incf rapcyc2,f
  730.  
  731. finrapv nop
  732.  
  733.  
  734. ;------------------------------------------------------------------------------------------------------------------
  735. ;ajustement du rapport cyclique en fonction du signal ' voie ANTI-COUPLE'
  736. ;T_PPM est calcule dans la procedure duree du signal PPM voie ANTI-COUPLE
  737. ;=========================================
  738. ;RAPPEL:
  739. ;les valeurs du rapport cycliques sont codees sur un octet
  740. ;le rapport cyclique varie entre 0% et 100% c.a.d. en analogique [0..1] ce qu'on code ici sur un octet [0..255]
  741. ;il y a donc 256 pas possibles
  742.  
  743. ;VOICI LE MIXAGE UTILISE:
  744. ;AC=(G*G/256 * Manche_AC /170 + G)/2 qui s'annule pour GAZ=0 mais pas pour AC=0
  745. ;ou son equivalent qui evite 1 debordement:
  746. ;AC=G*G/256/2*Manche_AC/170 + G/2
  747. ;cette courbe du second degre (gaz " au carre") a ete determine empiriquement
  748. ;Les calculs se font sur deux octets mais les resultats sont reencodes sur un octet
  749. ;=========================================
  750.  
  751. ;calcul du signal voie ANTI-COUPLE
  752. tppm2 movf T_PPM_A,w ;manche anti-couple
  753. movwf memo1
  754. movlw .84 ; T_PPM_A mini CETTE VALEUR EST A AJUSTER EN FONCTION DE VOTRE RADIO
  755. subwf memo1,f ; T_PPM_A:= T_PPM_A - 84 (pre-ofset)
  756. btfss STATUS,0 ;debordement ?
  757. clrf memo1 ;oui
  758. rlf memo1,w ; w:= 2 x T_PPM_A
  759. addwf memo1,w ; w:= 3 x T_PPM_A
  760. btfsc STATUS,0 ;debordement ? (result > 255 ?)
  761. movlw .250 ;oui, butee haute
  762. movwf BB ;non, on garde le resultat obtenu BB=AntiCouple
  763.  
  764. ;calcul du rapport cyclique (mixage de la valeur obtenue avec celle de la voie "GAZ")
  765. calc_AC movf rapcyc2,w ;w=GAZ
  766. movwf AA
  767. call multi ;w*AA -> AH,L = GAZ*GAZ =GAZ^2 ; AL=GAZ^2/256
  768. movf BB,w ;w=manche AntiCouple
  769. movwf AA ;AA=manche AntiCouple
  770. bcf STATUS,0 ;RAZ c
  771. rrf AH,w ;w=G*G/256/2
  772. call multi ;w*AA -> AH,L = G*G/256/2 * Manche_AC
  773. movlw AH ;w=adresse du registre AA
  774. call movxB ;BH,L = AH,L donc BH,L := G*G/256/2 * Manche_AC
  775. movlw .170 ;dividende
  776. call divi16_8 ; w:=BH,L / 170 = G*G/256/2 * Manche_AC / 170
  777. movwf AA ;AA:=BH,L / 170 = G*G/256/2 * Manche_AC / 170
  778. bcf STATUS,0 ;RAZ c
  779. rrf rapcyc2,w ;w:=G/2
  780. addwf AA,f ;AA:=G*G/256/2 * Manche_AC / 170 +G/2
  781. btfss STATUS,0 ;c depassement ?
  782. goto clc2 ;non
  783. movlw 0xFF ;oui, on force a 255
  784. movwf AA
  785.  
  786. clc2 comf AA,w ;pour agir dans le bon sens (les 2 moteurs doivent accelerer en meme temps)
  787.  
  788. movwf rapcyc1 ;rapcyc1=resultat
  789.  
  790. ; comf rapcyc1,f ;POUR TEST SEULEMENT
  791. ; return ;POUR TEST SEULEMENT
  792.  
  793. ;calibrage final
  794. movlw .250 ;valeur max de rapcycl admissible (attention: si > 250 -> int Timer2 = HS)
  795. ;avec prediv =1/8 (voir T1CON)
  796. subwf rapcyc1,w ;w:= rapcycl - 240 (result -> w : ne touche pas a rapcycl) d=f-w
  797. btfss STATUS,0 ;c=0 ? rapcycl < 240 ? (c=0 si w > f )
  798. goto finbcl1 ;oui
  799. movlw .250 ;non alors on bloque a butee max
  800. movwf rapcyc1
  801.  
  802.  
  803. ;------------------------------------------------------------------------------------------------------------------
  804.  
  805. finbcl1 goto boucle1
  806.  
  807. ;-----------------------------------------------------------------------
  808. ;DEBUT DES PROCEDURES
  809. ;-----------------------------------------------------------------------
  810.  
  811. ;***********************************************************************
  812. ; SOUS-ROUTINES d'INTERRUPTIONS
  813. ;***********************************************************************
  814. ;int timer0
  815. ;en principe ne deborde jamais ici.
  816. ;est utilise au sein de l'INT portB0 (voir plus bas) pour mesurer la duree PPM voie GAZ
  817.  
  818. inttimer0
  819.  
  820. fintimer0 return
  821.  
  822. ;----------------------------------------------------------------------
  823. ;int timer1
  824. ;generation du signal de sortie voie ANTI-COUPLE
  825. ;ce timer fonctionne ici suivant 2 alternances consecutives de durees inegales, mais dont la somme est constante
  826. ;on obtient dont une frequence constante avec un rapport cyclique variable
  827. ;valeur max de rapcycl admissible =253 (avec prediv =1/8 (voir T1CON))
  828.  
  829. inttimer1 movlw B'00000010'
  830. xorwf mesflags,f ;inverse le flag de phase
  831.  
  832. btfsc mesflags,1 ;test du flag de phase
  833. goto int1_a
  834.  
  835. movf rapcyc1,w ;ici w=rapcycl
  836. sublw .255 ;ici w=255-rapcycl
  837. movwf TMR1L
  838. movlw 0xFF ;pour utiliser le timer1 sur 8 bits seulement
  839. movwf TMR1H
  840.  
  841. goto int1_b
  842.  
  843. int1_a movf rapcyc1,w
  844. movwf TMR1L
  845. movlw 0xFF
  846. movwf TMR1H
  847.  
  848. btfsc mesflags,0 ;STOP ?
  849. goto int1_b ;oui, on va bloquer le MOSFET
  850.  
  851. bsf PORTB,1 ;SORTIE PHYSIQUE sur le port B pour commander le MOSFET voie ANTI-COUPLE
  852. return
  853.  
  854. int1_b bcf PORTB,1 ;SORTIE PHYSIQUE sur le port B pour commander le MOSFET voie ANTI-COUPLE
  855.  
  856. fin_int1 return
  857.  
  858.  
  859.  
  860. ;----------------------------------------------------------------------
  861. ;int timer2
  862. ;generation du signal de sortie VOIE GAZ
  863. ;ce timer fonctionne ici suivant 2 alternances consecutives de durees inegales, mais dont la somme est constante
  864. ;on obtient dont une frequence constante avec un rapport cyclique variable
  865. ;valeur max de rapcycl admissible =253 (avec prediv =1/16 (voir T2CON))
  866. ;attention: si prediv<1/16 ou si rapcycl > 253 alors-> int Timer2 = HS (pas le temps de reinitialier PR2)
  867.  
  868. inttimer2 movlw B'00000100'
  869. xorwf mesflags,f ;inverse le flag de phase
  870.  
  871. btfsc mesflags,2 ;test du flag de phase
  872. goto int2_a
  873.  
  874. movf rapcyc2,w ;ici w=rapcycl
  875. sublw .255 ;ici w=255-rapcycl
  876.  
  877. BANK1
  878. movwf PR2 ;PR2 = registre 8bits de periode du Timer2 situe en banque1
  879. BANK0
  880.  
  881. goto int2_b
  882.  
  883. int2_a movf rapcyc2,w
  884.  
  885. BANK1
  886. movwf PR2 ;PR2 = registre 8bits de periode du Timer2
  887. BANK0
  888.  
  889. btfsc mesflags,0 ;STOP ?
  890. goto int2_b ;oui, on va bloquer le MOSFET
  891.  
  892. bsf PORTB,2 ;SORTIE PHYSIQUE sur le port B pour commander le MOSFET VOIE GAZ
  893. return
  894.  
  895. int2_b bcf PORTB,2 ;SORTIE PHYSIQUE sur le port B pour commander le MOSFET VOIE GAZ
  896. fin_int2 return
  897.  
  898.  
  899. ;----------------------------------------------------------------------
  900. ;int Exterieure par bit 0 du port B
  901. ;sert a detecter les fronts du signal PPM du recepteur de radio-commande, voie GAZ
  902. ;et a mesurer la duree du signal a 1
  903.  
  904.  
  905. intB0 btfss mesflags,4 ;quel front vient-on de detecter ?
  906. goto frontD0 ;le front descendant
  907.  
  908. frontM0 clrf TMR0 ;le front montant. RAZ Timer0
  909. BANK1
  910. bcf OPTION_REG,6 ;Interrupt on falling edge of RB0/INT pin (detectera le front descendant)
  911. BANK0
  912. bcf mesflags,4 ;pour eviter une lecture en bank1 au debut de cette procedure, on testera ce flag
  913. return
  914.  
  915. frontD0 movf TMR0,w ;le timer0 a compte (l'horloge du PIC) depuis le front montant precedent
  916. movwf T_PPM_G ;MEMORISATION DE LA MESURE DU SIGNAL PPM voie GAZ pour le reste du programme
  917. BANK1
  918. bsf OPTION_REG,6 ;(detectera le front montant)
  919. BANK0
  920. bsf mesflags,4
  921. clrf TMR0
  922. return
  923. ;----------------------------------------------------------------------
  924. ;int Exterieure par bit5 du port B
  925. ;sert a detecter les fronts du signal PPM du recepteur de radio-commande, voie ANTI-COUPLE
  926. ;et a mesurer la duree du signal a 1
  927. ;REMARQUE: contrairement a l'intRB0, les INT RB4-7 sont declenchees par les fronts montants ET descendants
  928. ;sans que l'on puisse choisir lequel
  929. ;Mais en fait ceci aboutit a simplifier la procedure
  930. ;lorsque l'int est declenchee, il suffit de tester l'etat du port pour savoir si elle a ete declenchee par un
  931. ;front montant ou descendant.
  932. ;REMARQUE2: Cette procedure utilise volontairement LE MEME timer (le Timer0) que la precedente (intB0)
  933. ;ceci est possible car les signaux PPM des differentes voies ne sont jamais simultanes, mais sont successifs.
  934. ;Donc les comptages des temps par le Timer0 ne se chevauchent pas (voir plus bas la precaution a prendre)
  935. ;ET AINSI ON GAGNE UN TIMER !
  936. ;(on peut eenddre ce principe pour un plus grand nombre de voies ! avec 1 seul timer, on peut mesurer
  937. ;autant de periodes de temps qu' on veut, pourvu qu' elles soient disjointes)
  938.  
  939. ;************* ATTENTION ****************
  940. ;Pour eviter un RAZ intempestif du Timer0 d'une voie par l'autre,
  941. ;LES VOIES GAZ ET ANTI-COUPLE NE DOIVENTS PAS ETRE 2 VOIES CONSECUTIVES SUR LA RADIO !!!
  942. ;choisir par exemple les voies 2et4 MAIS PAS les voies 3et4 ou 2et3 pour l'anti-couple et les gaz.
  943. ;****************************************
  944.  
  945.  
  946. intB5 btfss PORTB,5 ;quel front vient-on de detecter ?
  947. goto frontD5 ;le front descendant
  948.  
  949. frontM5 clrf TMR0 ;le front montant. RAZ Timer0
  950. return
  951.  
  952. ;le timer1 a compte (l'horloge du PIC) depuis le front montant precedent
  953. frontD5 movf TMR0,w ;le timer0 a compte (l'horloge du PIC) depuis le front montant precedent
  954. movwf T_PPM_A ;MEMORISATION DE LA MESURE DU SIGNAL PPM voie A.Couple pour le reste du programme
  955.  
  956. clrf TMR0
  957. return
  958.  
  959.  
  960.  
  961.  
  962. ;------------------------------------------------------------------------
  963. ;Pour test seulement: memorise en EEPROM les valeurs simultanees de la vitesse Rotor et AntiCouple
  964. ;afin d'etudier la courbe obtenue (sous Excel par exemple)
  965.  
  966. ecrireEE movf adrEE,w
  967. movwf DDD
  968. movf rapcyc2,w
  969. W_EEPROM
  970. incf adrEE,f
  971.  
  972. movf adrEE,w
  973. movwf DDD
  974. comf rapcyc1,w
  975. W_EEPROM
  976. incf adrEE,f
  977.  
  978. call tp100ms ;anti-rebond
  979. call tp100ms
  980. call tp100ms
  981. call tp100ms
  982. call tp100ms
  983. return
  984.  
  985.  
  986.  
  987. ;************************************************************************
  988. ;debut des procedures d'affichage LCD (utilisent le portA)
  989. ;************************************************************************
  990.  
  991. ;FUNCTION SET
  992.  
  993. fset bcf PORTA,2 ;E=0
  994. bcf PORTA,3 ;R/S=0
  995.  
  996. movlw .56 ;(32+16+8)
  997. movwf dtlcd
  998.  
  999. call dt_out ;transmission serie vers 4015 -> DATA // LCD
  1000. call impuls
  1001. return
  1002. ;----------------------------------------------------------------------
  1003. ;DISPLAY CLEAR
  1004. dspclr bcf PORTA,2 ;E=0
  1005. bcf PORTA,3 ;R/S=0
  1006.  
  1007. movlw .1
  1008. movwf dtlcd
  1009. call dt_out
  1010. call impuls
  1011. return
  1012. ;----------------------------------------------------------------------
  1013. ;RETURN HOME
  1014. home clrf PORTA
  1015. movlw .2
  1016. movwf dtlcd
  1017. call dt_out
  1018. call impuls
  1019. return
  1020.  
  1021. ;----------------------------------------------------------------------
  1022. ;ENTRY MODE SET 0
  1023. ;le curseur se deplace
  1024.  
  1025. setmod0 bcf PORTA,2 ;E=0
  1026. bcf PORTA,3 ;R/S=0
  1027.  
  1028. movlw .6 ;( 4+2 sens inverse si 4+0 )
  1029. movwf dtlcd
  1030. call dt_out
  1031. call impuls
  1032. return
  1033. ;----------------------------------------------------------------------
  1034. ;ENTRY MODE SET 1
  1035. ;curseur gele
  1036. setmod1 bcf PORTA,2 ;E=0
  1037. bcf PORTA,3 ;R/S=0
  1038.  
  1039. movlw .7 ;( 4+2+1 )
  1040. movwf dtlcd
  1041. call dt_out
  1042. call impuls
  1043. return
  1044.  
  1045. ;----------------------------------------------------------------------
  1046. ;DISPLAY ON OFF
  1047. dsp10 bcf PORTA,2 ;E=0
  1048. bcf PORTA,3 ;R/S=0
  1049.  
  1050. movlw .12 ;( 8+4 )
  1051. movwf dtlcd
  1052. call dt_out
  1053. call impuls
  1054.  
  1055. return
  1056. ;----------------------------------------------------------------------
  1057. ;DDRAM ADRESS SET (A)
  1058. ;w doit contenir l'adresse (position d'affichage. voir doc)
  1059. ddras bcf PORTA,2 ;E=0
  1060. bcf PORTA,3 ;R/S=0
  1061. addlw .128
  1062. movwf dtlcd
  1063. call dt_out
  1064. call impuls
  1065. return
  1066. ;----------------------------------------------------------------------
  1067. ;CURSOR OR DISPLAY SHIFT
  1068. ;DEFILEMENT DU TEXTE
  1069. shiftT bcf PORTA,2 ;E=0
  1070. bcf PORTA,3 ;R/S=0
  1071.  
  1072. movlw .24 ;( 16+8 )
  1073. movwf dtlcd
  1074. call dt_out
  1075. call impuls
  1076. return
  1077. ;----------------------------------------------------------------------
  1078. ;CURSOR OR DISPLAY SHIFT
  1079. ;DEFILEMENT DE LA POSITION D'AFFICHAGE (CURSEUR)
  1080. shiftC bcf PORTA,2 ;E=0
  1081. bcf PORTA,3 ;R/S=0
  1082.  
  1083. movlw .16 ;( 16 )
  1084. movwf dtlcd
  1085. call dt_out
  1086. call impuls
  1087. return
  1088.  
  1089. ;----------------------------------------------------------------------
  1090. ;ECRIRE
  1091. ;w doit contenir lavaleur ASCII du caractere a afficher
  1092. ecrire bcf PORTA,2 ;E=0
  1093. bsf PORTA,3 ;R/S=1
  1094.  
  1095. movwf dtlcd
  1096.  
  1097. call dt_out
  1098.  
  1099. bsf PORTA,2 ;impuls E a 1 avec RS=1
  1100. call tp10ms
  1101. bcf PORTA,2 ;fin impulsion
  1102. call tp10ms
  1103. return
  1104.  
  1105. ;----------------------------------------------------------------------
  1106. ;impulsion E a 1 avec RS=0
  1107. impuls bcf PORTA,3 ;R/S=0
  1108. bsf PORTA,2 ;impulsion E a 1
  1109. call tp10ms
  1110. bcf PORTA,2 ;fin impulsion
  1111. call tp10ms
  1112. return
  1113.  
  1114. ;----------------------------------------------------------------------
  1115. ;SORTIE DATA (8 bits) en serie sur PA0 vers CD4015. PA1=Clock 4015.
  1116.  
  1117. dt_out movlw .8
  1118. movwf bitn
  1119. dtbcl rlf dtlcd,f
  1120. bcf PORTA,0 ;bit = 0 (a priori)
  1121. btfsc STATUS,0 ;test carry
  1122. bsf PORTA,0 ;non, bit = 0
  1123.  
  1124. out bsf PORTA,1 ;clock 4015
  1125. call tp154us
  1126. bcf PORTA,1 ;fin clock
  1127. call tp154us
  1128. decfsz bitn,f
  1129. goto dtbcl
  1130. return
  1131.  
  1132.  
  1133. ;------------------------------------------------------------------------
  1134. affi4 movf aff4,w
  1135. addlw .48 ;code ASCII de zero
  1136. call ecrire
  1137.  
  1138. affi3 movf aff3,w
  1139. addlw .48 ;code ASCII de zero
  1140. call ecrire
  1141.  
  1142. affi2 movf aff2,w
  1143. addlw .48 ;code ASCII de zero
  1144. call ecrire
  1145.  
  1146. movf aff1,w
  1147. addlw .48 ;code ASCII de zero
  1148. call ecrire
  1149.  
  1150.  
  1151. return
  1152.  
  1153.  
  1154.  
  1155. ;------------------------------------------------------------------------
  1156. ;nb decimaux dans AA(unites) et BB(centaines) au prealable
  1157. affdeci movf BB,w
  1158. movwf CC ;memo BB danc CC because cvBDU utilise BB
  1159. call cvBDU
  1160. movf AA,w ;ld A,V
  1161. movwf aff1 ;ld Aff1,A
  1162. movf BB,w ;ld A,W
  1163. movwf aff2 ;ld Aff2,A
  1164.  
  1165. movf CC,w ;ld A,BB ;0..99
  1166. movwf AA
  1167. call cvBDU
  1168. movf AA,w
  1169. movwf aff3
  1170. movf BB,w
  1171. movwf aff4
  1172. return
  1173.  
  1174. ;-----------------------------------------------------------------------
  1175. ;affiche un octet complet sur aff1..4 (4 TIL 702)
  1176. ;W doit contenir l'octet a afficher
  1177. affiw movwf AA
  1178. call cvBDU ;BB=18 et AA=4
  1179. movf AA,w
  1180. movwf aff1 ;aff1=4
  1181.  
  1182. movf BB,w ;w=18
  1183. movwf AA ;AA=18
  1184. call cvBDU ;BB=1 et AA=8
  1185.  
  1186. movf AA,w
  1187. movwf aff2 ;aff2=8
  1188. movf BB,w
  1189. movwf aff3 ;aff3=1
  1190.  
  1191. clrf aff4
  1192. call affi4
  1193. return
  1194.  
  1195. ;-----------------------------------------------------------------------
  1196. ;affichage nombre 0..9999
  1197. ;AH et AL contiennent un nb 0..9999
  1198. affnb movf AL,w ;ld A,AL
  1199. movwf AA
  1200. call cvBCU ;convertit period0 en BCD
  1201. ;resultat dans AA(unites) et BB(centaines)
  1202.  
  1203. ;on va ajouter valbin1 x 256
  1204.  
  1205. movf AH,w ;ld A,AH
  1206. movwf DD ;ld memo3,A pour'pas toucher period1
  1207.  
  1208. incf DD,f ;hors boucle
  1209. afn1 decfsz DD,f
  1210. goto saut1 ;jrnz ici1
  1211. goto suitef
  1212. ;ld A,AA
  1213. saut1 movlw .56
  1214. addwf AA,f ;addi A,56 (+56) retenue decimale possible
  1215. movf AA,w
  1216. sublw .99 ;carry =0 si AA>99
  1217. btfsc STATUS,0 ;bit de carry
  1218. goto st1 ;donc saut->conv3 si carry=1, c.a.d si A>99
  1219. ;jrc st1
  1220. movlw .100
  1221. subwf AA,f
  1222. incf BB,f ;ajout retenue decimale
  1223.  
  1224. st1 movlw .2
  1225. addwf BB,f ;(+200) soit en tout +256
  1226.  
  1227. goto afn1
  1228.  
  1229. suitef call affdeci
  1230. return
  1231.  
  1232. ;------------------------------------------------------------------------
  1233.  
  1234. ;CONVERSION BINAIRE(1) (1 octet incomplet 0..99 et pas 0..255) --> BCD
  1235. ;nombre a convertir dans AA
  1236. ;resultat dans BB (dizaines) et dans AA (unites)
  1237. ;ex: AA=237 -> BB=23 et AA=7
  1238. ;ex2 AA=84 -> BB=8 et AA=4
  1239.  
  1240. cvBDU clrf BB
  1241.  
  1242. conv2 movlw .10
  1243. subwf AA,w ;w=AA-10 positionne le bit de carry si A<10
  1244. btfss STATUS,0 ;bit de carry
  1245. goto conv3 ;donc saut ->conv3 si carry=1, c.a.d si A<10
  1246. movlw .10
  1247. subwf AA,f ;en boucle : revient a diviser A par 10
  1248. incf BB,f
  1249. goto conv2 ;9 passages au max si nb <= 99
  1250. conv3 return
  1251.  
  1252. ;--------------------------------------------------------------------
  1253. ;CONVERSION BINAIRE(2) (1 octet complet 0..255) --> BCD
  1254. ;nombre a convertir dans AA
  1255. ;resultat dans BB (centaines) et dans AA (unites)
  1256. ;ex: AA=237 -> BB=23 et AA=7
  1257.  
  1258. cvBCU clrf BB
  1259.  
  1260. conv4 movlw .100
  1261. subwf AA,w ;w=AA-100 positionne le bit de carry si A<100
  1262. btfss STATUS,0 ;bit de carry
  1263. goto conv5 ;donc saut ->conv3 si carry=1, c.a.d si A<100
  1264. movlw .100
  1265. subwf AA,f ;en boucle : revient a diviser A par 100
  1266. incf BB,f
  1267. goto conv4 ;9 passages au max si nb <= 999
  1268. conv5 return
  1269.  
  1270.  
  1271. ;--------------------------------------------------------------------
  1272.  
  1273.  
  1274.  
  1275. ;***********************************************************************
  1276. ; ROUTINES MATH
  1277. ;***********************************************************************
  1278.  
  1279. ;------------------------------------------------------------------------
  1280. ;conversion sexadecimale -> binaire
  1281. ;entree: AA, BB
  1282. ;resultat: AH,AL = 60*AA+BB
  1283.  
  1284. convhbin movlw .60
  1285. call multi ;AA contient la donnee a multiplier
  1286. movf BB,w
  1287. addwf AL,f
  1288. btfsc STATUS,0 ;carry
  1289. incf AH,f
  1290. return
  1291.  
  1292. ;------------------------------------------------------------------------
  1293. ;mutiplication 8 bits x 8 bits de AA par w (donnees sur 1 octet)
  1294. ;d'apres note AN526 Microchip
  1295. ;resultat (sur 2 octets) dans AH,AL (poids fort et poids faible)
  1296. multi clrf AH
  1297. movwf AL
  1298. movlw .8
  1299. movwf count1
  1300. movf AL,w
  1301. clrf AL
  1302. bcf STATUS,0 ;RAZ carry
  1303. loop rrf AA,f
  1304. btfsc STATUS,0
  1305. addwf AH,f
  1306. rrf AH,f
  1307. rrf AL,f
  1308. decfsz count1,f
  1309. goto loop
  1310. return
  1311.  
  1312. ;------------------------------------------------------------------------
  1313. ;division d'une valeur codee sur 16 bits (AH,AL) par 2
  1314. divi2 bcf STATUS,0 ;RAZ carry c=0
  1315. rrf AH,f ;le bit de poids faible tombe dans -> c ; le bit de poids fort de AH devient nul
  1316. rrf AL,f ;le bit de poids faible de AH devient le bit de poids fort de AL
  1317. return
  1318.  
  1319. ;------------------------------------------------------------------------
  1320. ; addwf AL,f ;(f+w) -> dest ; c=1 si retenue (a traiter)
  1321. btfsc STATUS,0 ;c
  1322. incf BH,f ;ajout retenue
  1323. movf BH,w
  1324. addwf AH,f ;(f+w) -> dest ; c=1 si retenue
  1325. return
  1326.  
  1327. ;------------------------------------------------------------------------
  1328. ;addition 16bits
  1329. ;(AH,AL)+(AH,AL) -> (BH,BL)
  1330. ;remarque seule la destination (B) est differente par rapport a la procedure add16A
  1331. add16B movf AL,w
  1332. addwf BL,f ;(f+w) -> dest ; c=1 si retenue (a traiter)
  1333. btfsc STATUS,0 ;c
  1334. incf AH,f ;ajout retenue
  1335. movf AH,w
  1336. addwf BH,f ;(f+w) -> dest ; c=1 si retenue
  1337. return
  1338.  
  1339. ;------------------------------------------------------------------------
  1340. ;complement a deux de la variable codee sur 2 octets situes aux adresses w et w+1
  1341. cpl16x movwf FSR
  1342. comf INDF,f ;w=complement (H)
  1343. incf FSR,f
  1344. comf INDF,f ;w=complement (L)
  1345. incf INDF,f ;w=complement a 2 de L
  1346. btfss STATUS,2 ;z
  1347. return
  1348. decf FSR,f ;pointe H
  1349. incf INDF,f ;retenue
  1350. return
  1351. ;------------------------------------------------------------------------
  1352. ;division 16bits par 8 bits resultat sur 8 bits : BH,L / w -> w
  1353. ;par approximations succesives sur les 8 bits (methode rapide, 8 passages max dans la boucle)
  1354. ;ATTENTION si le resultat est >255 il sera retourne = 255
  1355. ;il est evident par exemple que 65535 / 1 = 65535 ne tient pas sur 1 octet
  1356. ;toutefois dans ce programme, le resultat est borne sur 1 octet
  1357. ; x/0 donne 255
  1358. ; 0/0 donne 255
  1359. ; 0/x (x<>0) donne 0
  1360.  
  1361.  
  1362. divi16_8 movwf CC ;CC contient le diviseur
  1363. clrf BB
  1364. movlw B'10000000';masque du bit teste
  1365. movwf DD
  1366. movwf BB
  1367.  
  1368.  
  1369. divi1 movf CC,w
  1370. movwf AA
  1371.  
  1372. movf BB,w
  1373. call multi ;AH,L=AA*w = diviseur * BB ;ne touche pas
  1374. call compar16p ;ne touche pas AA ni BB
  1375. btfss STATUS,0
  1376. goto trop ;test bit suivant
  1377. goto pastrop
  1378.  
  1379. decf BB,w ;resultat
  1380. return
  1381.  
  1382. trop movf DD,w
  1383. xorwf BB,f ;eteint le bit precedent
  1384. bcf STATUS,0
  1385. rrf DD,f ;bit suivant
  1386. btfsc STATUS,0 ;c c'etait le dernier ?
  1387. goto findiv ; oui
  1388. movf DD,w
  1389. iorwf BB,f ;allume le bit suivant
  1390. goto divi1
  1391.  
  1392. pastrop bcf STATUS,0
  1393. rrf DD,f ;bit suivant
  1394. btfsc STATUS,0 ;c c'etait le dernier ?
  1395. goto findiv ; oui
  1396. movf DD,w
  1397. iorwf BB,f ;allume le bit suivant
  1398. goto divi1
  1399.  
  1400. findiv movf BB,w
  1401. return
  1402.  
  1403.  
  1404. ;------------------------------------------------------------------------
  1405. ;mov la variable codee sur 2 octets situes aux adresses w et w+1 dans -> AH,AL
  1406. movxA movwf FSR
  1407. movf INDF,w
  1408. movwf AH
  1409. incf FSR,f
  1410. movf INDF,w
  1411. movwf AL
  1412. return
  1413. ;------------------------------------------------------------------------
  1414. ;mov AH,AL dans -> la variable codee sur 2 octets situes aux adresses w et w+1
  1415. movAx movwf FSR
  1416. movf AH,w
  1417. movwf INDF
  1418. incf FSR,f
  1419. movf AL,w
  1420. movwf INDF
  1421. return
  1422. ;------------------------------------------------------------------------
  1423. ;mov la variable codee sur 2 octets situes aux adresses w et w+1 dans -> BH,BL
  1424. movxB movwf FSR
  1425. movf INDF,w
  1426. movwf BH
  1427. incf FSR,f
  1428. movf INDF,w
  1429. movwf BL
  1430. return
  1431. ;------------------------------------------------------------------------
  1432. ;mov BH,BL dans -> la variable codee sur 2 octets situes aux adresses w et w+1
  1433. movBx movwf FSR
  1434. movf BH,w
  1435. movwf INDF
  1436. incf FSR,f
  1437. movf BL,w
  1438. movwf INDF
  1439. return
  1440.  
  1441. ;------------------------------------------------------------------------
  1442. ;comparaison de deux valeurs codees sur 16 bits (AH,AL a BH,BL)
  1443. ;resultat dans STATUS carry et zero
  1444. ;les valeurs doivent representer des nombres tous deux positifs (pas ok si valeurs codees en complement a 2)
  1445. ;sauf pour le test d'egalite STATUS,2 ('z')
  1446. ;16p-> p comme positifs
  1447.  
  1448. compar16p movf AH,w
  1449. subwf BH,w ;c=0 si AH>BH
  1450. btfss STATUS,2 ;z=1 si AH=BH il faut alors comparer AL a BL
  1451. return
  1452. movf AL,w
  1453. subwf BL,w ;z=1 si AL=BL et comme on sait deja que AH=BH, si z=1 -> A=B
  1454. return
  1455.  
  1456. ;------------------------------------------------------------------------
  1457.  
  1458.  
  1459.  
  1460.  
  1461.  
  1462. ;***********************************************************************
  1463. ; TEMPOS GENERALES
  1464. ;***********************************************************************
  1465.  
  1466. ; Qx = 20,000 Mhz
  1467. ;TEMPO 154us pile
  1468. ;tiens compte du call de l'appelant et du return final
  1469.  
  1470. tp154us movlw .255 ;1 cycle
  1471. movwf t1 ;1 cycle
  1472.  
  1473. t3loop1 decfsz t1,f ;1 cycle
  1474. goto t3loop1 ;2 cycles
  1475.  
  1476. return ;2 cycles
  1477.  
  1478. ;----------------------------------------------------------------------
  1479. ; Qx = 20,000 Mhz
  1480. ; 2,0004ms
  1481. ;tiens compte du call de l'appelant et du return final
  1482.  
  1483. tp2ms movlw .13
  1484. movwf t1
  1485.  
  1486. t4loop1 movlw .255
  1487. movwf t2
  1488.  
  1489. t4loop2 decfsz t2,f
  1490. goto t4loop2
  1491. decfsz t1,f
  1492. goto t4loop1
  1493. return
  1494. ;----------------------------------------------------------------------
  1495. ; Qx = 20,000 Mhz
  1496. ; 1,000ms
  1497. ;tiens compte du call de l'appelant et du return final
  1498.  
  1499. tp1ms movlw .11
  1500. movwf t1
  1501.  
  1502. t5loop1 movlw .150
  1503. movwf t2
  1504.  
  1505. t5loop2 decfsz t2,f
  1506. goto t5loop2
  1507. decfsz t1,f
  1508. goto t5loop1
  1509. return
  1510. ;----------------------------------------------------------------------
  1511. ; Qx = 20,000 Mhz
  1512. ; 9,998ms
  1513. ;tiens compte du call de l'appelant et du return final
  1514.  
  1515. tp10ms movlw .65
  1516. movwf t1
  1517.  
  1518. t1loop1 movlw .255
  1519. movwf t2
  1520.  
  1521. t1loop2 decfsz t2,f
  1522. goto t1loop2
  1523. decfsz t1,f
  1524. goto t1loop1
  1525. return
  1526.  
  1527. ;----------------------------------------------------------------------
  1528. ; Qx = 20,000 Mhz
  1529.  
  1530. tp100ms clrwdt
  1531. movlw .10
  1532. movwf t3
  1533.  
  1534. t2loop2 clrwdt
  1535. call tp10ms
  1536. decfsz t3,f
  1537. goto t2loop2
  1538. return
  1539.  
  1540. ;----------------------------------------------------------------------
  1541. ; Qx = 20,000 Mhz
  1542. ;tempo n x 10ms
  1543. ;charger w avec n avant l'appel de cette procedure
  1544. ;
  1545. tx10ms movwf t3
  1546.  
  1547. txlp2 call tp10ms
  1548. decfsz t3,f
  1549. goto txlp2
  1550. return
  1551. ;----------------------------------------------------------------------
  1552. ; Qx = 20,000 Mhz
  1553. ;tempo n x 1ms
  1554. ;charger w avec n avant l'appel de cette procedure
  1555. ;
  1556. tx1ms movwf t3
  1557.  
  1558. txlp3 call tp1ms
  1559. decfsz t3,f
  1560. goto txlp3
  1561. return
  1562.  
  1563.  
  1564.  
  1565.  
  1566.  
  1567. ;***********************************************************************
  1568. ; TABLEAUX DE DONNEES
  1569. ;***********************************************************************
  1570.  
  1571. ;NOTE: les tableaux doivent se situer chacun sur 1 seule page d'adresse codee sur 8 bits (longueur<=255, 00FF h)
  1572. ;c.a.d qu'un tableau ne doit pas etre a cheval sur dex pages
  1573. ;verifier sur le listing absolu obtenu apres compilation.
  1574. ;je le place en page6
  1575. ;NOTE: en exa, chaque page de 256octets = 100 (note 0x100)
  1576. ;RAM page1=0000 a 00FF
  1577. ;RAM page2=0100 a 01FF
  1578. ;RAM page3=0200
  1579. ;etc... jusqu'a
  1580. ;RAM page8=0700 a 07FF (8 pages de 256 octets pour le PIC16F628, soit 2kO RAM)
  1581.  
  1582. org 07C0h
  1583.  
  1584. ;Le datasheet de Microchip precise ceci:
  1585.  
  1586. ;A computed GOTO is accomplished by adding an offset
  1587. ;to the program counter (ADDWF PCL). When doing a table
  1588. ;read using a computed GOTO method, care should be
  1589. ;exercised if the table location crosses a PCL memory
  1590. ;boundary (each 256 word block). Refer to the application
  1591. ;note "Implementing a Table Read" (AN556).
  1592.  
  1593.  
  1594.  
  1595.  
  1596.  
  1597.  
  1598. ;--------------------------fin des tableaux en FLASH -----------------------------------
  1599.  
  1600.  
  1601. ;=======================================================================================
  1602. ;DATA EN EEPROM
  1603. ;=======================================================================================
  1604.  
  1605.  
  1606. ORG 0x2100 ; zone EEPROM
  1607.  
  1608.  
  1609.  
  1610. ;=======================================================================================
  1611. end
  1612.  
  1613.  
  1614.  

6 Concernant le firmware:

Ce petit hélico électrique n'a pas d'arbre de transmission du mouvement du rotor principal vers l'hélice d'anti-couple, mais un deuxième moteur à l'arrière.

La partie la plus délicate de la programmation a été de déterminer la courbe de vitesse du moteur d'anti-couple (et donc la valeur du rapport cyclique de découpage de son alimentation) en fonction de la vitesse du rotor principal (la valeur du rapport cyclique...), avec comme paramètre la position du manche d'anti-couple. Ce dernier maintenu au neutre, la poussée de l'anti-couple doit équilibrer le couple moteur du rotor sur toute la plage de vitesses de rotation, de zéro à la vitesse max. C'est ainsi que j'ai déterminé empiriquement cette courbe et que j'ai ensuite trouvé une fonction mathématique y collant au plus près.

7 -

Voici le tracé de ces fonctions dans un tableur : (pour 3 positions du Manche d'anti-couple, mini, neutre et maxi). Dans la position neutre, la courbe se confond avec la valeur stabilisant l'hélico en lacet pour toutes les valeurs de la vitesse de rotation du rotor.

J'ai approché la courbe empirique par la fonction du second degré:

  • y=( G*G /256 * MancheAC /170 + G ) /2

dans laquelle

  • y = rapport cyclique appliqué au découpage de l'alim du moteur arrière
  • G = rapport cyclique de la voie gaz (calculé en fonction des signaux PPM issus du récepteur de radiocommande)
  • MancheAC = position du manche d'anti-couple (calculé en fonction des signaux PPM issus du récepteur de radiocommande)

8 -



15765