TODOPIC
Microcontroladores PIC => Almacén del Assembler => Mensaje iniciado por: robotdoblador en 21 de Noviembre de 2007, 10:27:03
-
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
-
Este programa no me acuerdo de donde lo saque, ni ahora puedo probar si funciona o no, se que cuando tuve que presentar un proyecto para el 873 que controlara el ancho de un impulso me funciono.
De todas formas, primero te dejo esto, sirva o no, por si acaso encuentras algo que te interesa o algo. un dia de estos dejo el programa verdadero (si este no lo es) y de paso meto una preguntilla.
Nuse si te servira, pero espero que lo haga, pero por intentarlo no se pierde nada verdad??
Un saludo y a cuidarse!
;CONTROL DE POTENCIA
;DEFINIR PIC
;***********************************************************
List p=16F873
Include "P16F873.INC"
__CONFIG _XT_OSC & _WDT_OFF
__IDLOCS H'0007'
;DEFINIR REGISTROS
;***********************************************************
RESUL EQU 0x30
;SALTAR VECTOR DE INTERRUPCION
;********************************************************
ORG 0x00
GOTO INICIO
ORG 0x05
;CONFIGURAR PUERTOS
;***********************************************************
INICIO BSF STATUS,RP0
MOVLW B'00000000'
MOVWF ADCON1
MOVLW B'00011111'
MOVWF TRISA
MOVLW B'11111011'
MOVWF TRISC
MOVLW 0xAA
MOVWF PR2
BCF STATUS,RP0
MOVLW B'00001100' ;PROGRAMAR CCP1 (PWM)
MOVWF CCP1CON
MOVLW B'00000110' ;ACTIVAR TMR2
MOVWF T2CON
MOVLW B'11011001' ;PROGRAMAR MODULO A/D
MOVWF ADCON0
RESTART BSF ADCON0,2 ;CONVERSION
TIME BTFSC ADCON0,2
GOTO TIME ;ESPERA
;GUARDAR RESULTADOS
;***********************************************************
MOVF ADRESH,W
MOVWF RESUL
MOVF RESUL,W
MOVWF CCPR1L
GOTO RESTART
NOP
NOP
END
-
:)Hola, soy nuevo en el foro, estoy tratando de aprender a usar el TIMER0 del 876A pero no tengo practicamente nada en castellano que me de una mano, e leido la hoja de datos del PIC y e podido entender ciertas cosas per se me complica un poco con el ingles. si se pudiera darme una manito lo voy a agradeces muchisimo... el fin de todo esto es haces un cuenta revoluciones de hasta 25000 rpm mas o menos, y anexarlo a un programa que mas adelante mostrare con mas tiempo...
muy agradecido y saludos... :mrgreen:
-
http://www.alos.5u.com/indexpic877.htm
A ver si esto te vale es de 16f877 pero creo que comparten muchas caracteristicas.
suerte tapi8
-
Hola que tal, yo he echo lo mismo que tu, me explico para controlar el servo tienes varias opciones:
Bajar la velocidad de 16f84 del oscilador a 2Mhz, con lo que te da menos velocidad de proceso pero mas precision en la señal para el servo.
Con el 873 puedes utilizar el puerto PWM en modo comparacion cargando los tiempos para el nivel alto y bajo en los registros , y configurando el PWM como comparador, una vez activas la salida y una vez activada configuras la salida para que cuando haga la comparacion la desactive.
co 12f629 puedes hacerlo con la interrupcion del tmr0, con el preescaler en division de 128 ,pues este funciona a 3Mhz. Espero que te ayude en algo
-
Hola de nuevo, en mi anterior respuesta hay un par de errores, cuando dije que el 629 va a 3Mhz es en realidad a 4 Mhz y con un preescaler de 8 consigues un total de 2048 Micros seg, que son el tope de los servos, cargando valores al tmr0 consegiras un total de 255 posibles posiciones del servo, teniendo cuidado de no llevar a este al tope mecanico, empieza cargando 125 y de ahi para arriba o abajo.
El caso del 873 tienes que usar el modulo ccp .