Hola a todos,
tengo que controlar un servomotor de radiocontrol con una precisión menor a un grado y no sé cómo lograrlo.
Utilizando un 16f84 he conseguido generar los pulsos con 10us de precisión mediante desbordamiento del tmr0. El problema es que no puedo lograr una frecuencia mayor para la rutina de interrupción debido al número de instrucciones (he tenido que añadir “nops” para ajustar los tiempos) y a la limitación de 20 Mhz del cristal (utilizo el 16f84A-20).
He pensado que podría lograrlo con un 16f87 usando el registro ccp (modo pwm) pero me he encontrado con un inconveniente:
Consigo generar el ciclo de trabajo pero no el periodo.
Con un cristal de 20 Mhz y preescalado 16 logro 3.2 us de precisión, que equivale a 0.32 grados de precisión en el posicionamiento del servomotor, cargando el valor correspondiente en el TMR2 consigo generar el ciclo de trabajo adecuado.
Pero cuando quiero cargar el valor correspondiente para el periodo, me encuentro con que necesito una variable de 13 bits (PR2 = 6249) cuando PR2 tiene un tamaño de 1 byte (creo).
Por otra parte, no entiendo cómo para el ciclo de trabajo (la parte del periodo en que la señal está a 1) se puede cargar un valor de hasta 10 bits y para el ciclo, que siempre será mayor (unas 10 veces) sólo se permiten 8 bits.
De verdad que no se me ocurre qué estoy haciendo mal.
A continuación os envío el código con el que logré el grado de precisión con el 84.
A ver si me podéis echar una mano...
Raúl
LIST P=16F84A
INCLUDE <P16F84A.INC>
__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _HS_OSC
CBLOCK 0x0C
FactorAlto
Auxiliar
Contador_Bucle2
ENDC
TMR0_CARGA EQU -d'38'
ALTO_CERO_GRADOS EQU d'610'
TIEMPO_PATRON EQU d'10'
FACTOR_MINIMO EQU ALTO_CERO_GRADOS/TIEMPO_PATRON
#DEFINE Salida PORTB,0
; ZONA DE CÓDIGOS ********************************************************************
ORG 0
goto Inicio
ORG .4
goto Timer0_Interrupcion
Inicio
bsf STATUS,RP0
bcf Salida
movlw b'11111110'
movwf PORTB
movlw b'00001000'
movwf OPTION_REG
bcf STATUS,RP0
movlw TMR0_CARGA
movwf TMR0
movlw b'10100000'
movwf INTCON
movlw .249
movwf Contador_Bucle2
Principal
movf PORTB,W
movwf Auxiliar
rrf Auxiliar,W
andlw b'01111111'
addlw FACTOR_MINIMO
movwf FactorAlto
goto Principal
CBLOCK
Guarda_W
Guarda_STATUS
Timer0_ContadorA
Contador_Bucle1
ENDC
Timer0_Interrupcion
movwf Guarda_W
swapf STATUS,W
movwf Guarda_STATUS
bcf STATUS,RP0
movlw TMR0_CARGA
movwf TMR0
movf Timer0_ContadorA,W
andlw b'11111111'
btfss STATUS,Z
goto Ajuste
btfsc Salida
goto EstabaAlto
movf Contador_Bucle1,W
andlw b'11111111'
btfss STATUS,Z
goto Bucle_Interrupcion1
EstabaBajo
nop
nop
nop
nop
bsf Salida
movf FactorAlto,W
movwf Timer0_ContadorA
goto Fin_Timer0_Interrupcion
EstabaAlto
nop
nop
nop
nop
nop ;5
nop
nop
nop
bcf Salida
movf FactorAlto,W
sublw .249
movwf Timer0_ContadorA
movlw .7
movwf Contador_Bucle1
Fin_Timer0_Interrupcion
swapf Guarda_STATUS,W
movwf STATUS
swapf Guarda_W,F
swapf Guarda_W,W
bcf INTCON,RBIF
bcf INTCON,T0IF
retfie
Ajuste
nop
nop
nop
nop
nop ;5
nop
nop
nop
nop
nop ;10
nop
nop
nop
decf Timer0_ContadorA
goto Fin_Timer0_Interrupcion
Bucle_Interrupcion1
movf Contador_Bucle2,W
andlw b'11111111'
btfsc STATUS,Z
goto Fin_Bucle2
nop
nop
nop
decf Contador_Bucle2,F
goto Fin_Timer0_Interrupcion
Fin_Bucle2
movlw .249
movwf Contador_Bucle2
decf Contador_Bucle1,F
goto Fin_Timer0_Interrupcion
END