TODOPIC
Microcontroladores PIC => Almacén del Assembler => Mensaje iniciado por: tikalban en 12 de Marzo de 2013, 01:12:33
-
recien me he unido a esta comunidad y espero puedan contestar mi pregunta, se trata del pic16f84a el cual quiero programarlo en ensamblador para que cuando se oprime un push button en ra2 se mueve un servomotor para un lado y en ra1 para el otro lado , (en ra0 se centra) el pwm que le mando al servomotor esta en ra0 y estoy intentando mover otro servomotor pero con el puerto b con la misma configuracion que en el puerto a, pero no lo he logrado, esto es lo que llevo :
-
Bienvenido al foro tikalban.
Yo creo que la mejor manera de hacerlo es con TMR0 marcando la frecuencia (20mS) y con bucles haciendo los tiempos de los DUTTYs, si por ejemplo te vale una precision de 5 grados, haces una temporizacion de 55uS y la llamas tantas veces como sea necesario para cada angulo mas otra de 500uS para -90 o 0 segun como quieras llamarle. Pones TMR0 en preescaler de 128 lo cargas con 100 de offset y ya te da los 20mS pones los dos servos a 1, llamas delay de 500uS y por ejemplo para los dos a 0 grados llamas 18 veces a la de 55uS pones a 0 los servos y ya estaria. para poner SERVO1 a -45 y SERVO2 a +45 pones TMR0 (TMR0 siempre igual) llamas 500uS y llamas 9 veces la de 55 bcf SERVO1 llamas 18 veces la de 55 y bcf SERVO2.
Tendras que apuntar en unos registros el numero d veces a llama para cada posicion de cada servo y con un contador ir contando, los pulsadores iran variando el numero de veces que hay que llamar a la temporizacion.
-
He estado mirando mas detenidamente tu programa y creo que tienes un error importante, envias una señal a cada servo 1.5mS en alto y el resto en bajo hasta 20mS, los tiempos estan bien, pero lo haces alternando a uno y a otro, a los servos para que funcionen y tengan fuerza hay que enviarles señal constantemente, no puede enviar señal 20mS y los siguientes 20mS dejarlo sin señal.
Prueba esto, solo para ver que hace:
lazo
bsf SERVO1 ; pone la señal de servo en 1
bsf SERVO2 ;asi activas los dos
bcf INTCON,T0IF; borra el flag de timer
movlw d'192' ; (256-192 = 64) 64 * 8 us = 0,512 ms
movwf TMR0 ; valor al registro de timer
btfss INTCON,T0IF ; espera por timer = ff -> 00
goto $-1
bcf INTCON,T0IF ; borra el flag de timer
movf Posic,0 ; 256-nn x 8 uS = 1 ms, 1,5 ms, 2,5 ms
movwf TMR0 ; valor al registro de timer
btfss INTCON,T0IF ; espera por timer = ff -> 00
goto $-1
bcf SERVO1 ; pone la señal de servo en 0
bcf SERVO2 ;y bajas los dos
bcf INTCON,T0IF ; borra el flag de timer
movlw d'9' ; cantidad de veces: 9 x 2 ms = 18 ms + 2 ms
movwf acum_A
retardo bcf INTCON,T0IF ; borra el flag de timer
movlw d'6' ; (256-6 = 250) 250 * 8 us = 2 ms
movwf TMR0 ; valor al registro de timer
btfss INTCON,T0IF ; espera por timer = ff -> 00
goto $-1
decfsz acum_A ; decrementa cantidad de veces
goto retardo
Y elimina lazo2, asi deberian estar a 90 grados los dos.
-
muchas gracias por la correccion, pero al añadir el lazo y el retardo que describes haces que los 2 motores siempre tenga la misma posicion (variable posic en mi programa) y sean controlodos los 2 por ra1(centro),ra2(izquierda) y ra3(derecha), lo que sigo intentando hacer es que su posicion no sea la misma que los push buttons de ra1,ra2,ra3 controlen el pulso de ra0 y los push buttons de rb1,rb2 yrb3 controlen los pulsos de rb0 (el otro servomotor), osea dos servomotores independientes, nuevamente gracias por la respuesta, seguire intentando hasta que me salga
-
Si claro, solo era una prueba para ver si asi funcionaban, la manera de hacerlo es como te pongo en el segundo mensaje, despues si tengo un rato te pongo un ejemplito.
-
El fin de semana tuve un poco de tiempo y te hice el ejemplito, se me complico un poco mas de lo que pensaba pero al mismo tiempo tambien comprobe que se puede aplicar para distintos angulos, en principio lo hice para 5º pero si le suprimes la temporizacion (pones un punto y coma delante de ;call DELAY_50 ;llamamos DELAY de 5 grados) te da posiciones de 1,45º, para pasos mas cortos hay que subir la frecuencia (este PIC puede trabajar a 20MHz) pero eso ya tu veras.
Los pulsadores no se exactamente como quieres ponerlos, si uno centra entonces escribira .18 en TIEMPO_SERVO1 o TIEMPO_SERVO2 segun el que sea, si otro incrementa posicion:
btfss PULSADOR3
goto SALIR
movlw .36 ;nunca debe exceder este numero, para 5º y 125 para 1,45º
subwf TIEMPO_SERVO1 ;miramos que servo 1 no esta en posicion maxima
btfsc STATUS,Z
goto NO INCREMENTA ;continuara programa sin incrementar
incf TIEMPO_SERVO1 ;si no esta al maximo incrementamos.
Para decrmentar debes mirar que no sea 0, si no es cero decrementa y si es 0 sigue programa.
Hice varias pruebas y parace que va bien, compruebalo tu a ver que te parace:
list P=16F84A ; definir procesador
#include <P16F84A.INC> ; definiciones de variables específicas del procesador
ERRORLEVEL 1;-302 ; para evitar los mensajes de cambio de
; banco en el resultado del compilador
__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC
; DEFINICIÓN DEL NOMBRE DE ENTRADAS Y SALIDAS
#define SERVO1 PORTA,0 ; puerto de salida de servo 1
#define PULSADOR1 PORTA,1 ; puerto de entrada de pulsador 1
#define PULSADOR2 PORTA,2 ; puerto de entrada de pulsador 2
#define PULSADOR3 PORTA,3 ; puerto de entrada de pulsador 3
#define SERVO2 PORTB,0 ; puerto de salida de servo 1
#define PULSADOR4 PORTB,1 ; puerto de entrada de pulsador 1
#define PULSADOR5 PORTB,2 ; puerto de entrada de pulsador 2
#define PULSADOR6 PORTB,3 ; puerto de entrada de pulsador 3
; VARIABLES
CBLOCK 0x20
TIEMPO_SERVO1 ;repeticiones para tiempo en alto SERVO1
TIEMPO_SERVO2 ;repeticiones para tiempo en alto SERVO1
CONTADOR_SERVOS ;contador para contar desbordes
PDel0 ;registro para temporizaciones
ENDC
org 0x000
goto principal
;
; Principal
;
principal
clrf PORTA ; inicia ports
clrf PORTB ; inicia ports
bsf STATUS,RP0 ; Apunta a banco 1
movlw b'00001110' ; PORTA
movwf TRISA ; salidas menos 1, 2 y 3, entradas
MOVLW b'00001110' ; PORTB
movwf TRISB ; salidas
movlw b'00000110' ; Configuración para TMR0
movwf OPTION_REG ; preescaler 128, 1:128 con CLK interno (que es
; de 1 MHz si el oscilador es de 4 MHz).
; El contador cuenta cada 20mseg
bcf STATUS,RP0 ; Apunta a banco 0
clrf CONTADOR_SERVOS
MOVER
movlw .100
movwf TMR0
bsf SERVO1
bsf SERVO2 ;los dos servos a 1
call DELAY_500 ;delay de 500uS=-90
movf TIEMPO_SERVO1 ;miramos si servo1 tiene que estar a -90
btfsc STATUS,Z
bcf SERVO1 ;tiene que estar a -90, ponemos a 0
movf TIEMPO_SERVO2 ;miramos si servo2 tiene que estar a -90
btfsc STATUS,Z
bcf SERVO2 ;tiene que estar a -90, ponemos a 0
btfsc SERVO1
goto BAJAR_SERVOS
btfsc SERVO1
goto BAJAR_SERVOS
goto PULSADORES
BAJAR_SERVOS
call DELAY_50 ;llamamos DELAY de 5 grados, para 1,45 suprimimos esta instruccion
incf CONTADOR_SERVOS,1;ncrementamos contador para saber numero de repeticiones
btfss SERVO1 ;miramos si SERVO1 esta aun a 1
goto $+5 ;si ya esta a 0 saltamos a mirar el otro servo
movf TIEMPO_SERVO1,0;eemos en que posicion tiene que estar SERVO1
subwf CONTADOR_SERVOS,0;omparamos con contador para ver si ya esta en posicion
btfsc STATUS,Z
bcf SERVO1 ;si son iguales ponemos SERVO1 a 0
btfss SERVO2 ;miramos si SERVO2 esta aun a 1
goto $+5 ;si ya esta a 0 saltamos a mirar el otro servo
movf TIEMPO_SERVO2,0;eemos en que posicion tiene que estar SERVO2
subwf CONTADOR_SERVOS,0;omparamos con contador para ver si ya esta en posicion
btfsc STATUS,Z
bcf SERVO2 ;si son iguales ponemos SERVO2 a 0
btfsc SERVO1
goto BAJAR_SERVOS
btfsc SERVO2
goto BAJAR_SERVOS
clrf CONTADOR_SERVOS ;ya estan los dos a 0, vamos a mirar pulsadores
PULSADORES
;aqui una vez puesto cada servo en su DUTTY solo hay que esperar a que se desborde
;TMRO, como el tiempo maximo de los DUTTYs es de 2,5mS el tiempo restante
;hasta 20mS se chequearan los pulsadores, uno centrara los servos a 0 grados
;por tanto escribira 18 en TIEMPO_SERVO1 o en TIEMPO_SERVO2, 18*5=90 que
;es posicion central, otro pulsador incrementara y otro restara, esto segun lo quieras hacer tu
;al DELAY_50 le reduje el tiempo, porque hay que hacer operaciones y hay que descontar ese tiempo
;los pulsadores normalmente se chequea que se pulso y despues que se solto, tambien se debe hacer
;un antirrebotes, pero esto dejalo para cuando te funcione bien...
btfss INTCON,T0IF
goto $-1
bcf INTCON,T0IF
goto MOVER
DELAY_500 ;retardo 500uS para -90
movlw .123 ; 1 set numero de repeticion
movwf PDel0 ; 1 |
PLoop1 clrwdt ; 1 clear watchdog
decfsz PDel0, 1 ; 1 + (1) es el tiempo 0 ?
goto PLoop1 ; 2 no, loop
PDelL1 goto PDelL2 ; 2 ciclos delay
PDelL2 clrwdt ; 1 ciclo delay
return ; 2+2 Fin.
DELAY_50 ;en realidad es 40uS
movlw .8 ; 1 set numero de repeticion
movwf PDel0 ; 1 |
PLoop0 clrwdt ; 1 clear watchdog
decfsz PDel0, 1 ; 1 + (1) es el tiempo 0 ?
goto PLoop0 ; 2 no, loop
PDelL3 goto PDelL4 ; 2 ciclos delay
PDelL4 clrwdt ; 1 ciclo delay
return ; 2+2 Fin.
END