Autor Tema: ayuda del pic16f84a  (Leído 2292 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado tikalban

  • PIC10
  • *
  • Mensajes: 2
ayuda del pic16f84a
« 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 :

Desconectado tapi8

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1506
Re: ayuda del pic16f84a
« Respuesta #1 en: 13 de Marzo de 2013, 06:38:21 »
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.
« Última modificación: 29 de Marzo de 2013, 10:39:02 por tapi8 »

Desconectado tapi8

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1506
Re: ayuda del pic16f84a
« Respuesta #2 en: 13 de Marzo de 2013, 15:56:06 »
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.

Desconectado tikalban

  • PIC10
  • *
  • Mensajes: 2
Re: ayuda del pic16f84a
« Respuesta #3 en: 14 de Marzo de 2013, 01:18:09 »
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

Desconectado tapi8

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1506
Re: ayuda del pic16f84a
« Respuesta #4 en: 14 de Marzo de 2013, 06:50:16 »
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.

Desconectado tapi8

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1506
Re: ayuda del pic16f84a
« Respuesta #5 en: 18 de Marzo de 2013, 07:47:20 »
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:

Código: [Seleccionar]

  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
« Última modificación: 20 de Marzo de 2013, 06:47:03 por tapi8 »