Autor Tema: Lectura de un encoder incremental por interrupción en un PIC  (Leído 10431 veces)

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

Desconectado acerdgr82

  • PIC10
  • *
  • Mensajes: 14
Lectura de un encoder incremental por interrupción en un PIC
« en: 27 de Diciembre de 2008, 20:28:00 »
Hola a todos,

Necesito hacer la lectura de un encoder incremental por interrupción en un PIC16f87X. El problema es que la interrupción por cambio de patillas en RB4...RB7 ya la tengo ocupada por un teclado, por lo que me queda la interrupción externa por RB0, pero necesitaría generar una interrupción por cualquier cambio de  estado en cualquiera de las dos patillas del encoder ¿Alguna idea de cómo activar la interrupción por cambio de estado de alguna de las dos patillas del encoder?¿Alguna otra alternativa que no sea ir explorando cada cierto tiempo el encoder?

Gracias,

Desconectado Cryn

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4169
Re: Lectura de un encoder incremental por interrupción en un PIC
« Respuesta #1 en: 27 de Diciembre de 2008, 20:51:55 »
que pic estas usando?? pienso que un 16fxxxx

si quieres tener más interrupciones externas puedes utilizar un pic de la familia 18fxxxx los cuales la mayoría tienen hasta 3 interrupciones externas, RB0, RB1 y RB2

o puedes usar el pin RA4 que es la entrada de reloj externa para el timer0 y hacer que esté esperando un pulso y desborde, entonces puedes generar la interrupción que necesitas y contar pulsos tb
.

Desconectado acerdgr82

  • PIC10
  • *
  • Mensajes: 14
Re: Lectura de un encoder incremental por interrupción en un PIC
« Respuesta #2 en: 28 de Diciembre de 2008, 16:15:05 »
Gracias Cryn,

Estoy usando el 16f877, pero de momento no he pasado del simulador. Me parece que me decantaré a utilizar un PIC con tres interrupciones externas. Lo de conectar el encoder a los contadores es muy buena idea, pero prefiero dejar de momento los temporizadores libres.


Desconectado Cryn

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4169
Re: Lectura de un encoder incremental por interrupción en un PIC
« Respuesta #3 en: 28 de Diciembre de 2008, 16:22:42 »
bien que te hayas decidido por un 18f porque estos también son de mayor espacio de memoria de programa o flash, ram y algunos otros periféricos mejorados.

Si programas en Ensamblador tienes muchas más instrucciones, si programas en C no tendrás que preocuparte mucho por llenar la memoria, son de aguante en ese lado :mrgreen:
.

Desconectado sztongo

  • PIC10
  • *
  • Mensajes: 11
Re: Lectura de un encoder incremental por interrupción en un PIC
« Respuesta #4 en: 02 de Enero de 2009, 17:53:25 »
Hola, si estas disupuesto a trabajar en i2c podes utilizar el pcf8574 que es un espansor de 8 i/0 con salida de interrupcion con el cambio de cualquiera de sus entradas. Saludos

Desconectado Oceano

  • PIC10
  • *
  • Mensajes: 22
    • Proyectos Roboticos.
Re: Lectura de un encoder incremental por interrupción en un PIC
« Respuesta #5 en: 04 de Julio de 2010, 19:21:40 »
Un ejemplo de encoder incremental usando la interrupción externa RB0/INT con Proton IDE o en CCS
y usando un PIC 16F876A, pero puede ser cualquiera de los 16F, sólo has de cambiar el nombre del PIC. Es muy importante acondicionar las señales de los encoders ópticos porque si no, no funcionaría. Se usa para acondicionar la señal del encoder un 7414 ó 74LS14 (siempre de tecnología TTL), nunca uses CMOS (por ejemplo el 74HC14) porque te fallaría, comprobado.

Esquema, código y web con completa información sobre este tema:



Código Proton IDE:

Código: [Seleccionar]

Device=16F876A

REMINDERS = FALSE
     Config XT_OSC, PWRTE_ON, CPD_OFF, WDT_OFF, BODEN_OFF, LVP_OFF
REMINDERS = TRUE

Symbol INTF   = INTCON.1         ' RB0 External Interrupt Flag
Symbol INTE   = INTCON.4         ' RB0 External Interrupt Enable
Symbol GIE    = INTCON.7         ' Global Interrupt Enable
Symbol INTEDG = OPTION_REG.6     ' Flag = 0 Flanco bajada. Flag = 1 Flanco subida.

On_INTERRUPT GoTo Interrupcion   ' Interrupción por Hardware (es la más rápida).

GIE    = 1                       ' Activa interrupciones generales.
INTE   = 1                       ' Activa la interrupción externa RB0/INT.
INTEDG = 1                       ' Hace que inicialmente la interrupción se habilite
                                 ' para flanco de subida.

ALL_DIGITAL = TRUE               ' Todas las entradas y salidas son digitales.
                                                                              
TRISA  = %111111
TRISB  = %11111111               ' Puerto A y B todo entradas.
TRISC  = %00000000               ' Puerto C como salida para visualizar a través de los LED.
          
Dim x As  Byte                   ' Variable X ---> contador de posición actual.


x=0                              
 
While 1=1                        ' |------ Programa Principal ------|
    
     PORTC = x                   ' El contenido de X se visualiza en el Puerto C a través de los LED.

Wend                             ' |--------------------------------|
            
End                              

    
Interrupcion:                 '-------- Decodificador de Encoder --------------
      
    Context SAVE              ' Salva en contexto de los registros antes de operar con la interrupción.
    
    If PORTB.0 = 1    Then    ' Si RB0 se ha puesto a 1 (flanco de subida),
       INTEDG  = 0            ' entonces activar la siguiente interrupción para flanco de bajada.
       If PORTB.1 = 1 Then    ' Si RB1 está a 1
          Inc x               ' entonces incrementar el contador X.
       EndIf
    EndIf
    
    If PORTB.0 = 0    Then    ' Si RB0 se ha puesto a 0 (flanco de bajada),
       INTEDG  = 1            ' entonces activar la siguiente interrupción para flanco de subida.
       If PORTB.1 = 1 Then    ' Si RB1 está 1
          Dec x               ' entonces decrementar el contador X.
       EndIf
    EndIf
    
    INTF = 0                  ' Borra el "flag" de la interrupción RB0/INT para poder permitir la  
                              ' siguiente interrupción, cuando ocurra.
    Context Restore           ' Restablece el contexto de los registros tal como estaban antes de la
                              ' interrupción.




Código en CCS:

Código: [Seleccionar]
#Include <16F876A.h>            // Usamos el PIC 16F876A.

#Fuses NOWDT, XT, NOPROTECT, NODEBUG, NOBROWNOUT, NOLVP, NOCPD, NOWRT

#Use Delay( Clock = 4000000 )   // Usamos un cristal de 4MHz, por ejemplo.

#Byte PortA = 0x05              // Dirección del puerto A
#Byte PortB = 0x06              // Dirección del puerto B
#Byte PortC = 0x07              // Dirección del puerto C

// ------ Variable Global ------
Int8   x = 0;                   // Declaramos el valor de X como Byte, es decir, 8 bits. Esta variable
                                // ha de ser global porque su valor lo usaremos en la interrupción y
                                // en el programa principal. Por tanto declaramos esta variable antes
                                // de la interrupción y de "Void Main".

// --------- Interrupción ---------
#Int_Ext                        // Interrupción Externa por RB0: Decodificación de Encoder.
Void IntRB0()
{
   // CCS se encarga de desactiva automáticamente cualquier interrupción.
   // No hace falta guardar contextos de registros por que CCS se encarga de hacerlo por ti.

   If (Bit_Test(PortB, 0))      // Si RB0 se ha puesto a 1 (flanco de subida),
   {  
       Ext_Int_Edge(H_TO_L);    // entonces activar la siguiente interrupción por flanco de bajada.
       If (Bit_Test(PortB, 1))  // Si RB1 está a 1,
       {
           x++;                 // entonces incrementar una unidad el valor de X.
       }
   }
   Else                         // Si RB0 se ha puesto a 0 (flanco de bajada),
   {  
       Ext_Int_Edge(L_TO_H);    // entonces activar la siguiente interrupción por flanco de subida.
       If (Bit_Test(PortB, 1))  // Si RB1 está 1,
       {
           x--;                 // entonces decrementar una unidad el valor de X.
       }
   }
   // Al finalizar la interrupción CCS se encarga de volver a poner automáticamente
   // la badera INTF = 0 ---> borra la interrupción para poder permitir la siguiente.
   // No hemos de hacer nada por nuestra parte.
}

Void Main()                     // Inicio y configuración.
{
   Port_b_pullups(FALSE);       // Configuración para el PIC 16F876A.
   Setup_adc_ports(NO_ANALOGS); // Sin comparadores ni ADCs, todo digital, etc...
   Setup_adc(ADC_CLOCK_DIV_2);
   Setup_spi(SPI_SS_DISABLED);
   Setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   Setup_timer_1(T1_DISABLED);
   Setup_timer_2(T2_DISABLED,0,1);
   Setup_comparator(NC_NC_NC_NC);
   Setup_vref(FALSE);
  
   Ext_Int_Edge(L_TO_H);        // Inicialmente detectar interrupción por flanco de subida.
   Enable_Interrupts(Int_Ext);  // Activar Interrupción Externa.
   Enable_Interrupts(GLOBAL);   // Interrupciones Generales Activadas.

   Set_Tris_A(0b111111);        // Puerto A todo entradas (en este caso no usamos el Puerto A).
   Set_Tris_B(0b11111111);      // Puerto B todo entradas (sólo usamos las entradas RB0 y RB1).
   Set_Tris_C(0b00000000);      // Puerto C todo salidas  (8 bits que irán a los LEDs).

   // ---------- Programa Principial ----------

   While (True)
   {
          PortC = x;            // El valor de X sale por el Puerto C a los 8 LED de salida.
   }      
  
}

Más info aquí: http://sites.google.com/site/proyectosroboticos/encoder/encoder-por-software
« Última modificación: 22 de Agosto de 2010, 00:24:01 por Oceano »


 

anything