Autor Tema: Controlar servo con pic16f84a  (Leído 14957 veces)

0 Usuarios y 2 Visitantes están viendo este tema.

Desconectado Fulguitron

  • PIC16
  • ***
  • Mensajes: 122
    • Disfruta de mi blog, hobbies y gadgets diferentes y poco comunes.
Controlar servo con pic16f84a
« en: 06 de Mayo de 2009, 09:55:10 »
  Buenas tardes, soy nuevo por aquí y ha pesar de ser del otro lado del charco, veo que este foro está bastante más animado que otros que hay por aquí. Llevo tiempo intentado programar PIC y ya voy haciendo mis primeros pinitos con leds que se encienden y se apagan y cosas así. Pero mi primer fin es construir algún robot con servos por eso pido vuestra ayuda a ver si alguien pudiera colgar un ejemplo sencillo, como por ejemplo un interruptor y se mueve el servo en asm. o algo así.
  Muchas gracias y espero ser fe ayuda de aquí un tiempo en cuant sepa algo más jejeje.

         Saludos
Disfruta de mi blog, hobbies y gadgets diferentes y poco comunes.

http://hobbiesygadgets.blogspot.com.es/

Desconectado mandoanaiz

  • PIC10
  • *
  • Mensajes: 47
Re: Controlar servo con pic16f84a
« Respuesta #1 en: 07 de Mayo de 2009, 05:11:50 »

Desconectado Miquel_S

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1251
Re: Controlar servo con pic16f84a
« Respuesta #2 en: 22 de Junio de 2009, 12:14:49 »
Hola Fulguitron, te paso parte del programa que estoy desarrollando para mi bipedo, en principio solo tengo escrito la parte del centrado veras que es facil de entender ya que se repite para cada servo.

 ;**************************************************************************************************   
;**************************************************************************************************   
;**                                                                      ***
;**    PROGRAMA:   HUMANOIDE.ASM                                                ***
;**    AUTOR:   MIQUEL SERVERA                                                   ***
;**    FECHA:   25/05/09                                                      ***
;**    Programa para mover un bipedo el cual consta de 5 servos por pierna.               ***
;**                                                                        ***
;**                                                                                             ***
;**                                                                        ***
;**    Revision:0.0 (Solo movimiento de las piernas)            Programa para PIC16F873      ***   
;**    Velocidad del reloj: 4MHz                           Tipo de reloj: XT         ***
;**    Proteccion de codigo: OFF                                                ***
;**                                                                        ***   
;**                        SERVO_1 -------------> RA0                                 ***
;**                     SERVO_2 -------------> RA1                                 ***
;**                     SERVO_3 -------------> RA2                                 ***
;**                     SERVO_4 -------------> RA3                                 ***
;**                     SERVO_5 -------------> RA4                                 ***   
;**                     SERVO_6 -------------> RB0                                 ***
;**                     SERVO_7 -------------> RB1                                 ***
;**                     SERVO_8 -------------> RB2                                 ***
;**                     SERVO_9 -------------> RB3                                 ***
;**                     SERVO_10 ------------> RB4                                 ***
;**                        PUL_CENTRA ----------> RC0                                         ***
;**                     PUL_ANDA ------------> RB5                                 ***
;**                                                                        ***
;**************************************************************************************************
;**************************************************************************************************

                     LIST P=16F873               ; Pic que vamos a utilizar.
                     INCLUDE "P16F873.INC"         ; Definicion de registros internos.

;******************************************* V A R I A B L E S ***********************************************

                     Delay_Cont      equ      0x20
                     Bucle         equ      0x21

;*************************************************************************************************************
      
      #define      FIN_CENTRADO   PORTA,5
      #define      PUL_ANDA      PORTB,5
      #define      PUL_CENTRA      PORTC,0
      #define      SERVO_1         PORTA,0
      #define      SERVO_2         PORTA,1
      #define      SERVO_3         PORTA,2
      #define      SERVO_4         PORTA,3
      #define      SERVO_5         PORTA,4
      #define      SERVO_6         PORTB,0
      #define      SERVO_7         PORTB,1
      #define      SERVO_8         PORTB,2
      #define      SERVO_9         PORTB,3
      #define      SERVO_10      PORTB,4

;*************************************************************************************************************

;================================= AQUI EMPIEZA EL PROGRAMA ==================================================

               ORG            0x00            ; Inicio en el Vector de Reset.
               goto         INICIO            ; Vamos a la primera instruccion del programa.

 INICIO         
               bsf            STATUS,RP0
               bcf            STATUS,RP1         ; Cambiamos al banco 1.
               movlw         b'11100000'
               movwf         TRISB            ; Configuramos Puerta B.
               movlw         b'00000110'
               movwf         ADCON1            ; Puerta A E/S digitales.
               movlw         b'000000'
               movwf         TRISA            ; Configuramos Puerta A
               movlw         b'00000001'
               movwf         TRISC            ; Configuramos Puerta C.
               movlw         b'11000001'
               movwf         OPTION_REG         ; Preescaler de 4 asociado al TMR0.
               bcf            STATUS,RP0         ; Cambiamos al banco 0.
                   clrf         PORTA            ; Borramos bits Puerta A.
               clrf         PORTB            ; Borramos bits Puerta B.
               clrf         PORTC            ; Borramos bits Puerta C.

;+++++++++++++++++++++++++++++++++++++ CENTRAMOS LOS SERVOS ++++++++++++++++++++++++++++++++++++++++++++++++++

 Wait_0            clrwdt                        ; Refresca WDT.
               btfss         PUL_CENTRA         ; Pulsador para centrado ON??
               goto         Wait_0            ; Todavia no,espera.
               goto         Centra            ; Si,inicia centrado

;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

 Centra            
               movlw         .25
               movwf         Bucle            ; Repetimos 25 veces la secuencia.
 Movi1            movlw         0x03
               movwf         Delay_Cont         ; Cargamos 3 en Delay_Cont.
               bsf            SERVO_1            ; SERVO_1 high.
 Delay1.0         movlw         .131
               movwf         TMR0            ; Inicia TMR0.
 Delay1.1         clrwdt                        ; Refresca WDT.
               btfss         INTCON,2         ; Han pasado ....ms.
               goto         Delay1.1         ; Todavia no.
               bcf            INTCON,2         ; Si, reponer flag del TMR0.
               decfsz         Delay_Cont,1      ; Se ha repetido tantas veces como indica Delay_Cont??
               goto            Delay1.0         ; Todavia no.
               movlw         0x37
               movwf         Delay_Cont         ; Carganos 37 en Delay_Cont
               bcf            SERVO_1            ; SERVO_1 low.
 Delay1.0.0         movlw         .175
               movwf         TMR0            ; Inicia TMR0.
 Delay1.1.1         clrwdt                        ; Refresca WDT.
               btfss         INTCON,2         ; Han pasado ....ms.
               goto         Delay1.1.1         ; Todavia no.
               bcf            INTCON,2         ; Si, reponer el flag del TMR0.
               decfsz         Delay_Cont,1      ; Se ha repetido tantas veces como indica Delay_Cont??
               goto         Delay1.0.0         ; Todavia no.
               decfsz         Bucle,1            ; Se ha repetido tantas veces como indica Bucle??
               goto         Movi1            ; Todavia no.

;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

                 movlw         .25
               movwf         Bucle            ; Repetimos 25 veces la secuencia.
 Movi2            movlw         0x03
               movwf         Delay_Cont         ; Cargamos 3 en Delay_Cont.
               bsf            SERVO_2            ; SERVO_2 high.
 Delay2.0         movlw         .133
               movwf         TMR0            ; Inicia TMR0.
 Delay2.1         clrwdt                        ; Refresca WDT.
               btfss         INTCON,2         ; Han pasado ....ms.
               goto         Delay2.1         ; Todavia no.
               bcf            INTCON,2         ; Si, reponer flag del TMR0.
               decfsz         Delay_Cont,1      ; Se ha repetido tantas veces como indica Delay_Cont??
               goto            Delay2.0         ; Todavia no.
               movlw         0x37
               movwf         Delay_Cont         ; Carganos 37 en Delay_Cont
               bcf            SERVO_2            ; SERVO_2 low.
 Delay2.0.0         movlw         .175
               movwf         TMR0            ; Inicia TMR0.
 Delay2.1.1         clrwdt                        ; Refresca WDT.
               btfss         INTCON,2         ; Han pasado ....ms.
               goto         Delay2.1.1         ; Todavia no.
               bcf            INTCON,2         ; Si, reponer el flag del TMR0.
               decfsz         Delay_Cont,1      ; Se ha repetido tantas veces como indica Delay_Cont??
               goto         Delay2.0.0         ; Todavia no.
               decfsz         Bucle,1            ; Se ha repetido tantas veces como indica Bucle??
               goto         Movi2            ; Todavia no.

;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

               movlw         .25
               movwf         Bucle            ; Repetimos 25 veces la secuencia.
 Movi3            movlw         0x03
               movwf         Delay_Cont         ; Cargamos 3 en Delay_Cont.
               bsf            SERVO_3            ; SERVO_3 high.
 Delay3.0         movlw         .133
               movwf         TMR0            ; Inicia TMR0.
 Delay3.1         clrwdt                        ; Refresca WDT.
               btfss         INTCON,2         ; Han pasado ....ms.
               goto         Delay3.1         ; Todavia no.
               bcf            INTCON,2         ; Si, reponer flag del TMR0.
               decfsz         Delay_Cont,1      ; Se ha repetido tantas veces como indica Delay_Cont??
               goto            Delay3.0         ; Todavia no.
               movlw         0x37
               movwf         Delay_Cont         ; Carganos 37 en Delay_Cont
               bcf            SERVO_3            ; SERVO_3 low.
 Delay3.0.0         movlw         .175
               movwf         TMR0            ; Inicia TMR0.
 Delay3.1.1         clrwdt                        ; Refresca WDT.
               btfss         INTCON,2         ; Han pasado ....ms.
               goto         Delay3.1.1         ; Todavia no.
               bcf            INTCON,2         ; Si, reponer el flag del TMR0.
               decfsz         Delay_Cont,1      ; Se ha repetido tantas veces como indica Delay_Cont??
               goto         Delay3.0.0         ; Todavia no.
               decfsz         Bucle,1            ; Se ha repetido tantas veces como indica Bucle??
               goto         Movi3            ; Todavia no.

;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

               movlw         .25
               movwf         Bucle            ; Repetimos 25 veces la secuencia.
 Movi4            movlw         0x03
               movwf         Delay_Cont         ; Cargamos 3 en Delay_Cont.
               bsf            SERVO_4            ; SERVO_4 high.
 Delay4.0         movlw         .133
               movwf         TMR0            ; Inicia TMR0.
 Delay4.1         clrwdt                        ; Refresca WDT.
               btfss         INTCON,2         ; Han pasado ....ms.
               goto         Delay4.1         ; Todavia no.
               bcf            INTCON,2         ; Si, reponer flag del TMR0.
               decfsz         Delay_Cont,1      ; Se ha repetido tantas veces como indica Delay_Cont??
               goto            Delay4.0         ; Todavia no.
               movlw         0x37
               movwf         Delay_Cont         ; Carganos 37 en Delay_Cont
               bcf            SERVO_4            ; SERVO_4 low.
 Delay4.0.0         movlw         .175
               movwf         TMR0            ; Inicia TMR0.
 Delay4.1.1         clrwdt                        ; Refresca WDT.
               btfss         INTCON,2         ; Han pasado ....ms.
               goto         Delay4.1.1         ; Todavia no.
               bcf            INTCON,2         ; Si, reponer el flag del TMR0.
               decfsz         Delay_Cont,1      ; Se ha repetido tantas veces como indica Delay_Cont??
               goto         Delay4.0.0         ; Todavia no.
               decfsz         Bucle,1            ; Se ha repetido tantas veces como indica Bucle??
               goto         Movi4            ; Todavia no.

;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

               movlw         .25
               movwf         Bucle            ; Repetimos 25 veces la secuencia.
 Movi5            movlw         0x03
               movwf         Delay_Cont         ; Cargamos 3 en Delay_Cont.
               bsf            SERVO_5            ; SERVO_5 high.
 Delay5.0         movlw         .133
               movwf         TMR0            ; Inicia TMR0.
 Delay5.1         clrwdt                        ; Refresca WDT.
               btfss         INTCON,2         ; Han pasado ....ms.
               goto         Delay5.1         ; Todavia no.
               bcf            INTCON,2         ; Si, reponer flag del TMR0.
               decfsz         Delay_Cont,1      ; Se ha repetido tantas veces como indica Delay_Cont??
               goto            Delay5.0         ; Todavia no.
               movlw         0x37
               movwf         Delay_Cont         ; Carganos 37 en Delay_Cont
               bcf            SERVO_5            ; SERVO_5 low.
 Delay5.0.0         movlw         .175
               movwf         TMR0            ; Inicia TMR0.
 Delay5.1.1         clrwdt                        ; Refresca WDT.
               btfss         INTCON,2         ; Han pasado ....ms.
               goto         Delay5.1.1         ; Todavia no.
               bcf            INTCON,2         ; Si, reponer el flag del TMR0.
               decfsz         Delay_Cont,1      ; Se ha repetido tantas veces como indica Delay_Cont??
               goto         Delay5.0.0         ; Todavia no.
               decfsz         Bucle,1            ; Se ha repetido tantas veces como indica Bucle??
               goto         Movi5            ; Todavia no.

;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

               movlw         .25
               movwf         Bucle            ; Repetimos 25 veces la secuencia.
 Movi6            movlw         0x03
               movwf         Delay_Cont         ; Cargamos 3 en Delay_Cont.
               bsf            SERVO_6            ; SERVO_6 high.
 Delay6.0         movlw         .133
               movwf         TMR0            ; Inicia TMR0.
 Delay6.1         clrwdt                        ; Refresca WDT.
               btfss         INTCON,2         ; Han pasado ....ms.
               goto         Delay6.1         ; Todavia no.
               bcf            INTCON,2         ; Si, reponer flag del TMR0.
               decfsz         Delay_Cont,1      ; Se ha repetido tantas veces como indica Delay_Cont??
               goto            Delay6.0         ; Todavia no.
               movlw         0x37
               movwf         Delay_Cont         ; Carganos 37 en Delay_Cont
               bcf            SERVO_6            ; SERVO_6 low.
 Delay6.0.0         movlw         .175
               movwf         TMR0            ; Inicia TMR0.
 Delay6.1.1         clrwdt                        ; Refresca WDT.
               btfss         INTCON,2         ; Han pasado ....ms.
               goto         Delay6.1.1         ; Todavia no.
               bcf            INTCON,2         ; Si, reponer el flag del TMR0.
               decfsz         Delay_Cont,1      ; Se ha repetido tantas veces como indica Delay_Cont??
               goto         Delay6.0.0         ; Todavia no.
               decfsz         Bucle,1            ; Se ha repetido tantas veces como indica Bucle??
               goto         Movi6            ; Todavia no.

;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

               movlw         .25
               movwf         Bucle            ; Repetimos 25 veces la secuencia.
 Movi7            movlw         0x03
               movwf         Delay_Cont         ; Cargamos 3 en Delay_Cont.
               bsf            SERVO_7            ; SERVO_7 high.
 Delay7.0         movlw         .133
               movwf         TMR0            ; Inicia TMR0.
 Delay7.1         clrwdt                        ; Refresca WDT.
               btfss         INTCON,2         ; Han pasado ....ms.
               goto         Delay7.1         ; Todavia no.
               bcf            INTCON,2         ; Si, reponer flag del TMR0.
               decfsz         Delay_Cont,1      ; Se ha repetido tantas veces como indica Delay_Cont??
               goto            Delay7.0         ; Todavia no.
               movlw         0x37
               movwf         Delay_Cont         ; Carganos 37 en Delay_Cont
               bcf            SERVO_7            ; SERVO_7 low.
 Delay7.0.0         movlw         .175
               movwf         TMR0            ; Inicia TMR0.
 Delay7.1.1         clrwdt                        ; Refresca WDT.
               btfss         INTCON,2         ; Han pasado ....ms.
               goto         Delay7.1.1         ; Todavia no.
               bcf            INTCON,2         ; Si, reponer el flag del TMR0.
               decfsz         Delay_Cont,1      ; Se ha repetido tantas veces como indica Delay_Cont??
               goto         Delay7.0.0         ; Todavia no.
               decfsz         Bucle,1            ; Se ha repetido tantas veces como indica Bucle??
               goto         Movi7            ; Todavia no.

;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++                     
   
               movlw         .25
               movwf         Bucle            ; Repetimos 25 veces la secuencia.
 Movi8            movlw         0x03
               movwf         Delay_Cont         ; Cargamos 3 en Delay_Cont.
               bsf            SERVO_8            ; SERVO_8 high.
 Delay8.0         movlw         .133
               movwf         TMR0            ; Inicia TMR0.
 Delay8.1         clrwdt                        ; Refresca WDT.
               btfss         INTCON,2         ; Han pasado ....ms.
               goto         Delay8.1         ; Todavia no.
               bcf            INTCON,2         ; Si, reponer flag del TMR0.
               decfsz         Delay_Cont,1      ; Se ha repetido tantas veces como indica Delay_Cont??
               goto            Delay8.0         ; Todavia no.
               movlw         0x37
               movwf         Delay_Cont         ; Carganos 37 en Delay_Cont
               bcf            SERVO_8            ; SERVO_8 low.
 Delay8.0.0         movlw         .175
               movwf         TMR0            ; Inicia TMR0.
 Delay8.1.1         clrwdt                        ; Refresca WDT.
               btfss         INTCON,2         ; Han pasado ....ms.
               goto         Delay8.1.1         ; Todavia no.
               bcf            INTCON,2         ; Si, reponer el flag del TMR0.
               decfsz         Delay_Cont,1      ; Se ha repetido tantas veces como indica Delay_Cont??
               goto         Delay8.0.0         ; Todavia no.
               decfsz         Bucle,1            ; Se ha repetido tantas veces como indica Bucle??
               goto         Movi8            ; Todavia no.

;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

               movlw         .25
               movwf         Bucle            ; Repetimos 25 veces la secuencia.
 Movi9            movlw         0x03
               movwf         Delay_Cont         ; Cargamos 3 en Delay_Cont.
               bsf            SERVO_9            ; SERVO_9 high.
 Delay9.0         movlw         .133
               movwf         TMR0            ; Inicia TMR0.
 Delay9.1         clrwdt                        ; Refresca WDT.
               btfss         INTCON,2         ; Han pasado ....ms.
               goto         Delay9.1         ; Todavia no.
               bcf            INTCON,2         ; Si, reponer flag del TMR0.
               decfsz         Delay_Cont,1      ; Se ha repetido tantas veces como indica Delay_Cont??
               goto            Delay9.0         ; Todavia no.
               movlw         0x37
               movwf         Delay_Cont         ; Carganos 37 en Delay_Cont
               bcf            SERVO_9            ; SERVO_9 low.
 Delay9.0.0         movlw         .175
               movwf         TMR0            ; Inicia TMR0.
 Delay9.1.1         clrwdt                        ; Refresca WDT.
               btfss         INTCON,2         ; Han pasado ....ms.
               goto         Delay9.1.1         ; Todavia no.
               bcf            INTCON,2         ; Si, reponer el flag del TMR0.
               decfsz         Delay_Cont,1      ; Se ha repetido tantas veces como indica Delay_Cont??
               goto         Delay9.0.0         ; Todavia no.
               decfsz         Bucle,1            ; Se ha repetido tantas veces como indica Bucle??
               goto         Movi9            ; Todavia no.

;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

               movlw         .25
               movwf         Bucle            ; Repetimos 25 veces la secuencia.
 Movi10            movlw         0x03
               movwf         Delay_Cont         ; Cargamos 3 en Delay_Cont.
               bsf            SERVO_10         ; SERVO_10 high.
 Delay10.0         movlw         .133
               movwf         TMR0            ; Inicia TMR0.
 Delay10.1         clrwdt                        ; Refresca WDT.
               btfss         INTCON,2         ; Han pasado ....ms.
               goto         Delay10.1         ; Todavia no.
               bcf            INTCON,2         ; Si, reponer flag del TMR0.
               decfsz         Delay_Cont,1      ; Se ha repetido tantas veces como indica Delay_Cont??
               goto            Delay10.0         ; Todavia no.
               movlw         0x37
               movwf         Delay_Cont         ; Carganos 37 en Delay_Cont
               bcf            SERVO_10         ; SERVO_10 low.
 Delay10.0.0      movlw         .175
               movwf         TMR0            ; Inicia TMR0.
 Delay10.1.1      clrwdt                        ; Refresca WDT.
               btfss         INTCON,2         ; Han pasado ....ms.
               goto         Delay10.1.1         ; Todavia no.
               bcf            INTCON,2         ; Si, reponer el flag del TMR0.
               decfsz         Delay_Cont,1      ; Se ha repetido tantas veces como indica Delay_Cont??
               goto         Delay10.0.0         ; Todavia no.
               decfsz         Bucle,1            ; Se ha repetido tantas veces como indica Bucle??
               goto         Movi10            ; Todavia no.

               END

;+++++++++++++++++++++++++++++++++++++++ FIN DEL CENTRADO DE LOS SERVOS ++++++++++++++++++++++++++++++++++++++

 Espero que te sea de ayuda,si tienes dudas no dudes en preguntar.
 
Saludos.
Todos somos muy ignorantes. Lo que ocurre es que no todos ignoramos las mismas cosas.

Desconectado tapi8

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1506
Re: Controlar servo con pic16f84a
« Respuesta #3 en: 23 de Junio de 2009, 08:02:22 »
Miquel este programa lo has probado? te funciona?.
Es que tienes activada la interrupcion por TIMER0 pero no la tratas de ninguna manera, no haces nada en el vector de INTERRUPCION y no la tratas como tal, lo normal seria que se te quedara en el vector de interrupcion y no hiciera nada mas, o no?


tapi8

Desconectado Miquel_S

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1251
Re: Controlar servo con pic16f84a
« Respuesta #4 en: 23 de Junio de 2009, 11:02:32 »
Hola tapi8, lo simule con proteus y me funciono, al darle al pulsador se me centran uno detras del otro;fisicamente solo lo he probado con dos servos uno en RA0 y el otro en RA1 y funciono.
Pero gracias por el aviso lo revisare y ya dire cosas.

 Gracias de nuevo y saludos...
 
 Miquel
Todos somos muy ignorantes. Lo que ocurre es que no todos ignoramos las mismas cosas.

Desconectado tapi8

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1506
Re: Controlar servo con pic16f84a
« Respuesta #5 en: 23 de Junio de 2009, 12:24:52 »
Mira Miquel te pongo este ejemplo de Suki, para que veas como se hace la interrupcion, esta bien explicado y creo que lo entenderas facil, en este caso  temporiza 200ms, las de 20ms para los servos te sale directa con preescaler de 128, creo que sin hacer repeticiones y cargando el TIMER con 100 te da 19,968ms


; **** Encabezado ****
list p=16F84A
#include P16F84A.inc
__CONFIG   _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC
;**** Definicion de variables ****
Contador   equ   0x0C   ; Contador para detectar 4 desbordes de TMR0.-
W_Temp      equ   0x0D   ; Registro para guardar temporalmente W.-
STATUS_Temp   equ   0x0E   ; Registro para guardar temporalmete STATUS

Led         equ      0         ; Definimos Led como el bit cero de un registro, en este caso PORTB.-

;**** Inicio del Micro ****
Reset      
   org      0x00      ; Aquí comienza el micro.-
   goto   Inicio      ; Salto a inicio de mi programa.-
;**** Vector de Interrupcion ****
   org      0x04      ; Atiendo Interrupcion.-
   goto   Inicio_ISR

; **** Programa Principal ****
;**** Configuracion de puertos ***
   org      0x05      ; Origen del código de programa.-
Inicio      
   bsf      STATUS,RP0    ; Pasamos de Banco 0 a Banco 1.-
   movlw   b'11111110'   ; RB0 como salida.-
   movwf   TRISB
   movlw   b'00000111'   ; Se selecciona TMR0 y preescaler de 256.-
   movwf   OPTION_REG
   bcf      STATUS,RP0   ; Paso del Banco 1 al Banco 0
   bcf      PORTB,Led   ; El Led comienza apagado.-
   movlw   0x3D      ; Cargamos 61 en TMR0 para lograr aprox. 50ms.-
   movwf   TMR0
   clrf   Contador   ; Iniciamos contador.-
   movlw   b'10100000'   ; Habilitamos GIE y T0IE (interrupción del TMR0)
   movwf   INTCON
;**** Control de Led ****
Bucle      
   nop               ; Aqui el micro puede ejecutar cualquier otra tarea
   goto   Bucle      ; sin necesidad de utilizar tiempo en un bucle de demora.-   


;**** Rutina de servicio de Interrupcion ****

;---> Aqui haremos copia de respaldo para mostrar como se hace aunque no es
; necesario ya que el micro no hace otra tarea mientras tanto <---

;  Guardado de registro W y STATUS.-
Inicio_ISR
   movwf   W_Temp   ; Copiamos W a un registro Temporario.-
   swapf   STATUS, W   ;Invertimos los nibles del registro STATUS.-
   movwf   STATUS_Temp   ; Guardamos STATUS en un registro temporal.-
;**** Interrupcion por TMR0 ****
ISR
   btfss   INTCON,T0IF   ; Consultamos si es por TMR0.-
   goto   Fin_ISR      ; No, entonces restauramos valores.-
   incf   Contador   ; Si, Incrementamos contador
   movlw   0x04      ; Consultamos si se han producido 4 desbordes
   subwf   Contador,0   ; para obtener 200 ms.-
   btfss   STATUS,Z   ;
   goto   Actualizo_TMR0   ; No, cargo TMR0 si salgo.-
   clrf   Contador   ; Si, reseteo Contador y controlo Led.-
   btfss   PORTB,Led   ; Si esta apagado, prendo y viseversa.-
   goto   Prendo_led
   bcf      PORTB,Led   ; Apago Led.-
Actualizo_TMR0         ; Actualizo TMR0 para obtener una temporizacion de 50 ms.-
   movlw   0x3D      ; d'61'
   movwf   TMR0
   bcf      INTCON,T0IF   ; Borro bandera de control de Interrupcion.-
   goto   Fin_ISR      ; Restauro valores.-
Prendo_led
   bsf      PORTB,Led   ; prendo Led.-
   goto   Actualizo_TMR0
; Restauramos los valores de W y STATUS.-
Fin_ISR
   swapf   STATUS_Temp,W   ; Invertimos lo nibles de STATUS_Temp.-
   movwf   STATUS
   swapf   W_Temp, f   ; Invertimos los nibles y lo guardamos en el mismo registro.-
   swapf W_Temp,W   ; Invertimos los nibles nuevamente y lo guardamos en W.-
   retfie         ; Salimos de interrupción.-
;..........................................

   end

Desconectado Miquel_S

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1251
Re: Controlar servo con pic16f84a
« Respuesta #6 en: 23 de Junio de 2009, 12:56:32 »
Gracias tapi8, modificare el codigo y asi me ahorrare instrucciones y tiempo en la ejecucion del programa. Una ultima pregunta tengo los movimientos muy rapidos ¿como podria suavizarlos?
 Me comentaron el mover el servo de dos grados en dos grados hasta el punto deseado pero eso conlleva a mas codigo = mas tiempo de ejecucion ¿hay otra forma de resolver el problema?

Gracias de nuevo.
Todos somos muy ignorantes. Lo que ocurre es que no todos ignoramos las mismas cosas.

Desconectado tapi8

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1506
Re: Controlar servo con pic16f84a
« Respuesta #7 en: 23 de Junio de 2009, 14:27:24 »


http://picmania.garcia-cuervo.net/picc2.php#SERVO1

Echale un vistazo a esa pagina del gran Diego Redpic, aunque el programa esta en C creo que te va a aclarar bastante, en la misma pag. tiene ejemplos para 8 y 16 servos con una sola interrupcion.
Supongo que para que vaya mas suave tendras que ir variando el dutty poco a poco y no de golpe, yo de servos no se mucho, pero si te puedo ayudar en algo lo hare.

tapi8

Desconectado Miquel_S

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1251
Re: Controlar servo con pic16f84a
« Respuesta #8 en: 23 de Junio de 2009, 15:25:56 »
Hola de nuevo Tapi8 gracias por la ayuda,mirare la pagina del Gran Diego Redpic, de todas formas he estado pensando lo comentado anteriormente referente a la interrupcion del TMR0, y si no me equivoco que podria ser, porque no se tanto como vosotros como mi intencion era temporizar por desbordamiento del TMR0 por mi que esta bien escrito.
 :mrgreen:
Todos somos muy ignorantes. Lo que ocurre es que no todos ignoramos las mismas cosas.

Desconectado tapi8

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1506
Re: Controlar servo con pic16f84a
« Respuesta #9 en: 23 de Junio de 2009, 15:49:53 »
Fijate en el programa que te puse donde pone:
bucle
    nop
    goto  bucle
Aqui puedes poner el programa que tu quieras, por ejemplo el control del dutty de los servos, porque de la temp. de 20ms no te tienes que preocupar, cuando se desborde el TIMER el solo te ira al vector 0x04 y ahi haces el tratamiento de la interrupcion, si configuras el TIMER con div frec. en 128 y lo cargas con 100 cada vez que se desborda te hace temp. casi exactas de 20ms (19968us), tienes que guardar los reg. W y STATUS, aunque en el programa ese pone que no es necesario, en el tuyo si lo es porque vas a hacer mas cosas, y te podria dar errores en tu programa principal.
Las temp. del dutty se pueden hacer con el TIMER2 o tambien por bucle porque son pequeñas, si no tienes que atender a muchas mas cosas.

tapi8

Desconectado Fulguitron

  • PIC16
  • ***
  • Mensajes: 122
    • Disfruta de mi blog, hobbies y gadgets diferentes y poco comunes.
Re: Controlar servo con pic16f84a
« Respuesta #10 en: 25 de Junio de 2009, 03:04:08 »
Ufffffff hacía días que no me conectaba, es que ultimamente ... ya tengo casi todas las piezas del bipedo hechos y en cuanto lo tenga montado me lio con el programa, gracias por lo ejemplos, a ver si me ayudan, os mantendre informados.
Disfruta de mi blog, hobbies y gadgets diferentes y poco comunes.

http://hobbiesygadgets.blogspot.com.es/

Desconectado Fulguitron

  • PIC16
  • ***
  • Mensajes: 122
    • Disfruta de mi blog, hobbies y gadgets diferentes y poco comunes.
Re: Controlar servo con pic16f84a
« Respuesta #11 en: 25 de Junio de 2009, 04:32:52 »
 Os dejo un programa que he modificado para hacer pruebas con los sevos, funciona OK en el proteus pero tengo una duda. En cada movimiento del programa hay tres variables como d'xxx' que son para controlar el angulo y (creo que la velocidad) del servo. Aunque con reglas de tres puedo conseguir el angulo deseado a ver si alguien puede darme un explicacion lógica. Aquí teneis el programa, saludos y gracias

;****************************************************************************************************
;
;     PROGRAMA : PRUEBAS DE ANGULOS CON DOS SERVOS.ASM
;
;
;
; Velocidad del reloj : 4 MHz           Reloj instrucci¢n: 1 MHz = 1 us, T= 4 us
; Perro Guardian : Deshabilitado        Tipo de reloj : XT 
; Proteccion del codigo : OFF
;
;
;****************************************************************************************************       
 
 LIST     P=16F84A     ;EL PIC A UTILIZAR.

;****************************** IGUALIDADES *********************************************************

w          EQU        0X00     ;DESTINO w (REGISTRO DE TRABAJO)
f          EQU      0X01     ;DESTINO f (REGISTRO A USADO)     
ESTADO      EQU      0X03     ;ESTADO,  ESTA EN LA DIRECCION 3
RP0         EQU      0X05     ;RP0 EQUIVALE A 5. 
PCL          EQU      0x02     ;DIRECCION DEL PCL (CONTADOR DEL PC)
PUERTAA     EQU      0X05     ;PUERTAA SE ENCUENTRA EN LA DIRECCION 5.
PUERTAB     EQU      0X06     ;PUERTAB SE ENCUENTRA EN LA DIRECCION 6.
ALTO_1      EQU        0x0c     ;DIRECCION DEL REGISTRO DEL PULSO ALTO
ALTO_2      EQU        0x0d     ;DIRECCION DEL REGISTRO DEL PULSO ALTO
BAJO_1      EQU      0X0e     ;DIRECCION DEL REGISTRO DEL PULSO BAJO
BAJO_2      EQU        0x0f     ;DIRECCION DEL REGISTRO DEL PULSO ALTO
HZ          EQU      0x1c     ;DIRECCION DEL REGISTRO HZ (50 VECES, PARA FORMAR 50HZ)

;***************** AQUI EMPIEZA EL PROGRAMA. ********************************************************

            ORG      0            ;ORIGEN DEL PROGRAMA, AQUI EMPIEZA.
               
            goto     INICIO       ;VA A INICIO PARA SOBREPASAR
                        ;EL VECTOR DE INTERRUPCION.
            ORG      5     

INICIO      bsf      ESTADO,RP0   ;Cambio al banco 1
            movlw    b'00000111'  ;2 bit de puerto A como entrada
            movwf    PUERTAA
          clrf     PUERTAB      ;Puerta B como salida
          bcf        ESTADO,RP0   ;Cambio al banco 0
          clrf     PUERTAA      ;Borro puerta A
           clrf     PUERTAB      ;Borro puerta B

;******************** Leer las entrada para desplazar servo *****************************************

LEE_ENTRADA movf     PUERTAA,0    ;Mueve el valor de la entrada al registro w (Lee entradas)
           
           
            goto     AVANZA     

AVANZA      call     SV_0_90
            call     SV_1_90
           call     SV_0_180
            call     SV_1_180
            goto     LEE_ENTRADA


      
;************ Rutina para posicionar el servo en los 90° ********************************************

SV_0_90     movlw    d'13'
            movwf    HZ
ALTO_90_0   bsf        PUERTAB,0     ;Pone a 1 el bit 0 de la puerta A
          call     AL90
BAJO_90_0   bcf      PUERTAB,0     ;Pone a 0 el bit 0 de la puerta A
            call     BA90
            decfsz   HZ,1
            goto     ALTO_90_0
            return
           
                                 
SV_1_90     movlw    d'13'
            movwf    HZ
ALTO_90_1   bsf      PUERTAB,1     ;Pone a 1 el bit 0 de la puerta A
            call     AL90
BAJO_90_1   bcf      PUERTAB,1     ;Pone a 0 el bit 0 de la puerta A
            call     BA90
            decfsz   HZ,1
            goto     ALTO_90_1
            return
           
;************ Rutina para posicionar el servo en los 180° ********************************************

SV_0_180    movlw    d'13'
            movwf    HZ
ALTO_0_180  bsf        PUERTAB,0     ;Pone a 1 el bit 0 de la puerta A
          call     AL0
BAJO_0_180  bcf      PUERTAB,0     ;Pone a 0 el bit 0 de la puerta A
            call     BA0
            decfsz   HZ,1
            goto     ALTO_0_180
            return
           
                                 
SV_1_180    movlw    d'13'
            movwf    HZ
ALTO_1_180  bsf      PUERTAB,1     ;Pone a 1 el bit 0 de la puerta A
            call     AL0
BAJO_1_180  bcf      PUERTAB,1     ;Pone a 0 el bit 0 de la puerta A
            call     BA0
            decfsz   HZ,1
            goto     ALTO_1_180
            return

;*********** Pulso Alto a 90° ********************************************************

AL90    movlw    d'44'
       movwf    ALTO_1
A90       movlw    d'8'
       movwf    ALTO_2           
DC1       decfsz   ALTO_2,1
       goto     DC1
        decfsz   ALTO_1,1
       goto     A90
        return     

     
      
;*********** Pulso Bajo a 90° *********************************************************
      
BA90    movlw    d'45'
       movwf    BAJO_1
B90       movlw    d'92'
       movwf    BAJO_2           
DC2       decfsz   BAJO_2,1
       goto     DC2
        decfsz   BAJO_1,1
       goto     B90
        return 
       
   
 
  ;*********** Pulso Alto a 180º *****************************************************


AL0     movlw    d'52'
       movwf    ALTO_1
A0      movlw    d'92'
       movwf    ALTO_2           
DC11    decfsz   ALTO_2,1
       goto     DC11
        decfsz   ALTO_1,1
       goto     A0
        return     
      
;*********** Pulso Bajo a 180°  *****************************************************
      
BA0    movlw    d'49'
       movwf    BAJO_1
B0      movlw    d'8'
       movwf    BAJO_2           
DC12   decfsz   BAJO_2,1
       goto     DC12
        decfsz   BAJO_1,1
       goto     B0
        return   
       END
Disfruta de mi blog, hobbies y gadgets diferentes y poco comunes.

http://hobbiesygadgets.blogspot.com.es/

Desconectado tapi8

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1506
Re: Controlar servo con pic16f84a
« Respuesta #12 en: 25 de Junio de 2009, 13:17:18 »
Fulgitron esos numeros que van en decimal D'XX son todos para las temporizaciones excepto el D'13 que es el numero de veces que haces la repeticion alto-bajo sobre el servo, osea te controlaria la velocidad.
Este programa no tiene buena pinta:
Haces al principio una lectura de PORTA pero no la tienes en cuenta para nada.
Los tiempos, no se que servo vas a usar pero son:
90º>alto 1.237ms; total>13.844
180º>alto14.5ms; total>15.95*
Te funciona ese tipo de servo con estos tiempos?
Hacer todas las temporizaciones por bucle es poco aconsejable, ya que no vas a poder hacer nada mas. Yo te aconsejaria hacer la de 20ms (es lo que dura el ciclo total en la mayoria de los servos) por TIMER0 y despues controlar los tiempos en alto por bucle, que son tiempos pequeños.
*Los tiempos los saque de la simulacion del MPLAB que los da exactos.

tapi8

Desconectado Fulguitron

  • PIC16
  • ***
  • Mensajes: 122
    • Disfruta de mi blog, hobbies y gadgets diferentes y poco comunes.
Re: Controlar servo con pic16f84a
« Respuesta #13 en: 26 de Junio de 2009, 02:40:24 »
    Gracias Tapi8, la verdad es que solo lo he probado en el proteus y funciona y lo del PORTA es que es parte del programa que usaré para un robot y solo puse esta parte para probar lo de los ángulos de los servos porque no sabía como iba. Entonces sino he entendido mal para poner por ejemplo 90º tengo que poner en el d'xx' 13.84 más o menos???
    Como ves estoy empezando y voy un poco perdido.
    Por cierto usaré unos servos futaba s3003
Disfruta de mi blog, hobbies y gadgets diferentes y poco comunes.

http://hobbiesygadgets.blogspot.com.es/

Desconectado tapi8

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1506
Re: Controlar servo con pic16f84a
« Respuesta #14 en: 26 de Junio de 2009, 13:26:48 »
Aqui tienes las demoras necesarias para 90º y 180º, para 90º tienes que tener en alto bsf 1.5ms y en bajo bcf 18.5ms entre las dos hacen los 20ms, y y con la de 2.5 y 17.5 para los 180º.
Para que cambie de una posicion a otra, de 90º a 180º y viceversa, haces el cambio cada cierto tiempo, ese tiempo es el que controlas con ese 13, que es el numero de veces que repites el tren de pulsos que envias, cada alto-bajo son siempre 20ms, entonces 20*13=260ms es el tiempo que lo cambias, cada 1/4 de segundo, si lo quisieras cada segundo en vez de 13 pondrias 50, y cada 1/2 seg 25, si o no?
El problema es que ese programa esta haciendo continuamente bucles de temporizacion, no vas a poder hacer mucho mas con ese microcontrolador.
Las demoras estan hechas con el picdel que lo teneis al principio de este foro, da los tiempos exactos, no falla ni una millonesima, cosa parece que importante en este tema de los servos

demora de 1.5ms

DEMORA  movlw     .249      ; 1 set numero de repeticion
        movwf     PDel0     ; 1 |
PLoop0  clrwdt              ; 1 clear watchdog
PDelL1  goto PDelL2         ; 2 ciclos delay
PDelL2 
        decfsz    PDel0, 1  ; 1 + (1) es el tiempo 0  ?
        goto      PLoop0    ; 2 no, loop
        clrwdt              ; 1 ciclo delay
        return              ; 2+2 Fin.

demora de 18.5ms

DEMORA  movlw     .23       ; 1 set numero de repeticion  (B)
        movwf     PDel0     ; 1 |
PLoop1  movlw     .200      ; 1 set numero de repeticion  (A)
        movwf     PDel1     ; 1 |
PLoop2  clrwdt              ; 1 clear watchdog
        decfsz    PDel1, 1  ; 1 + (1) es el tiempo 0  ? (A)
        goto      PLoop2    ; 2 no, loop
        decfsz    PDel0,  1 ; 1 + (1) es el tiempo 0  ? (B)
        goto      PLoop1    ; 2 no, loop
PDelL1  goto PDelL2         ; 2 ciclos delay
PDelL2  clrwdt              ; 1 ciclo delay
        return              ; 2+2 Fin.

demora de 2.5ms

DEMORA  movlw     .7        ; 1 set numero de repeticion  (B)
        movwf     PDel0     ; 1 |
PLoop1  movlw     .88       ; 1 set numero de repeticion  (A)
        movwf     PDel1     ; 1 |
PLoop2  clrwdt              ; 1 clear watchdog
        decfsz    PDel1, 1  ; 1 + (1) es el tiempo 0  ? (A)
        goto      PLoop2    ; 2 no, loop
        decfsz    PDel0,  1 ; 1 + (1) es el tiempo 0  ? (B)
        goto      PLoop1    ; 2 no, loop
PDelL1  goto PDelL2         ; 2 ciclos delay
PDelL2  clrwdt              ; 1 ciclo delay
        return              ; 2+2 Fin.

demora de 17.5ms

DEMORA  movlw     .17       ; 1 set numero de repeticion  (B)
        movwf     PDel0     ; 1 |
PLoop1  movlw     .205      ; 1 set numero de repeticion  (A)
        movwf     PDel1     ; 1 |
PLoop2  clrwdt              ; 1 clear watchdog
        clrwdt              ; 1 ciclo delay
        decfsz    PDel1, 1  ; 1 + (1) es el tiempo 0  ? (A)
        goto      PLoop2    ; 2 no, loop
        decfsz    PDel0,  1 ; 1 + (1) es el tiempo 0  ? (B)
        goto      PLoop1    ; 2 no, loop
PDelL1  goto PDelL2         ; 2 ciclos delay
PDelL2 
        return              ; 2+2 Fin.