Autor Tema: Lectura de encoder.  (Leído 5892 veces)

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

Desconectado micro_pepe

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 3216
Lectura de encoder.
« en: 12 de Diciembre de 2008, 18:44:26 »
Buenas, estoy tratando de leer un encoder, y aumentar una variable en un sentido de giro y disminuirla en otro. Con el codigo que muestro, en el display aparece sienpre un 0, si elimino el 'else' de la interrupción, el que está entre comentario, puedo incrementar hasta 40.

El encoder es uno como este: http://www.piher-nacesa.com/pdf/04-CI-11v04.pdf

Un saludo.

PD: El ejemplo es un derivado de esto: http://www.bolivar.udo.edu.ve/microinternet/articulos/Usando%20Quadrature%20Encoder.pdf

Código: [Seleccionar]
/******************************************************************************/
#include <16f876A.h>
#fuses XT,NOWDT,PUT, NOPROTECT, NOBROWNOUT,NOLVP,NOCPD
#use delay (clock=4000000)
#use fast_io(A)
#use fast_io(B)
#use fast_io(C)
/******************************************************************************/
/******************************************************************************/
int8 encoder;
/******************************************************************************/
/* Definiciones para la interfaz PIC-LCD */
/******************************************************************************/
# define PORTA 0x05// Puerto A
# define PORTB 0x06// Puerto B
# define PORTC 0x07// Puerto C
# define TRISA 0x85// Registro de direccionamiento Puerto A
# define TRISB 0x86// Registro de direccionamiento Puerto B
# define TRISC 0x87// Registro de direccionamiento Puerto C
//Se definen los terminales de conexion del display
#bit lcd_db4 = PORTA.2
#bit tris_lcd_db4 = TRISA.2
#bit lcd_db5 = PORTA.3
#bit tris_lcd_db5 = TRISA.3
#bit lcd_db6 = PORTA.4
#bit tris_lcd_db6 = TRISA.4
#bit lcd_db7 = PORTA.5
#bit tris_lcd_db7 = TRISA.5

#bit lcd_en = PORTC.0
#bit tris_lcd_en = TRISC.0
#bit lcd_rs = PORTC.1
#bit tris_lcd_rs = TRISC.1
# include <lcd_flex.c>
/******************************************************************************/
/* Interrupción por cambio en RB4-RB7                                         */
/******************************************************************************/
#int_rb
void detect_rb_change() {
int current;
static int last=0;
current=*PORTB;
// Canal A = PORTB.5
// Canal B = PORTB.4
if ((bit_test(current,4)) && (bit_test(current,5))){
   if ((bit_test(last,4)) ^ (bit_test(current,5))){
      encoder++; //sentido agujas del reloj
      if(encoder > 40)
         encoder = 40;
   }
   else {
        encoder--; //sentido contrario agujas del reloj
        if(encoder == 0xFF)
           encoder = 0;
   }
}
last=current;
}
/******************************************************************************/
/* Programa Principal                                                         */
/******************************************************************************/
void main(void)
{
disable_interrupts(GLOBAL);
encoder = 0;
set_tris_a(0b11000011);
set_tris_b(0b00110000);
set_tris_c(0b11111100);
port_b_pullups(FALSE);
enable_interrupts(INT_RB);
enable_interrupts(GLOBAL);
lcd_init();
while(1) {
delay_ms(1000);
lcd_gotoxy(1,1);//fila 1, col 1
printf(lcd_putc,"  %u",encoder);
}
}
/******************************************************************************/

« Última modificación: 13 de Diciembre de 2008, 16:41:44 por micro_pepe »
Se obtiene más en dos meses interesandose por los demás, que en dos años tratando de que los demás se interesen por ti.

新年快乐     的好奇心的猫死亡

Desconectado micro_pepe

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 3216
Re: Lectura de encoder.
« Respuesta #1 en: 13 de Diciembre de 2008, 16:40:41 »
Problema solucionado, creo que era un problema de ruido, tenia configurado RB6 y RB7 como entrada y las tenia al aire, por lo que quizas saltaba la interrupción del puerto b cuando no tenia que saltar, el codigo lo he corregido.

Un saludo.
Se obtiene más en dos meses interesandose por los demás, que en dos años tratando de que los demás se interesen por ti.

新年快乐     的好奇心的猫死亡

Desconectado Marttyn

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1836
    • IDEAA
Re: Lectura de encoder.
« Respuesta #2 en: 17 de Enero de 2009, 01:35:09 »
Mico_pepe, me echas una mano?
Estoy queriendo hacer un analizador de servos, y voy a utilizar un encoder para seleccionar la posicion del servo. Esto de los encoders la verdad me marea un poco, y a pesar de haber leido un poco de informacion de todos lados todavia no lo tengo claro del todo.
Por lo que dices tu codigo funciona, yo tenia pensado hacer algo muy parecido a lo que tu haces aqui:

Código: C
  1. if ((bit_test(last,4)) ^ (bit_test(current,5))){
  2.       encoder++; //sentido agujas del reloj
  3.       if(encoder > 40)
  4.          encoder = 40;
  5.    }
  6.    else {
  7.         encoder--; //sentido contrario agujas del reloj
  8.         if(encoder == 0xFF)
  9.            encoder = 0;
  10.    }

Pero pensaba activar un flag en vez de incrementar la variable directamente, ademas queria implementarlo en el INT_EXT para el pin A del encoder. Creo que esto me reduciria la precision a la mitad con respecto a usar INT_RB comprobando los pines A y B, aunque al ser solo para incrementear y decrementar variables no creo que influya mucho...

Algo que no entiendo de tu codigo es esto:

Código: C
  1. if ((bit_test(current,4)) && (bit_test(current,5)))

Para que esperas a que los dos pines sean 1?

Por cieto, crees que es necesario el filtro RC que pone en el datasheet? Dara mucho error si no lo uso?
Salu2!
La gente ve las cosas que existen y se pregunta por qué.
Yo prefiero imaginar lo que no existe y preguntarme por qué no.

Desconectado micro_pepe

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 3216
Re: Lectura de encoder.
« Respuesta #3 en: 06 de Febrero de 2009, 13:28:05 »
Hola Marttyn, no habia visto tu pregunta.

Puedes hacer algo así:

Código: [Seleccionar]
#int_rb
void detect_rb_change() {
int current;
static int last=0;

#asm movf PORTB,0 //Sin estas instrucciones no funciona bien.
     movwf current
#endasm
//current=*PORTB;
// Canal A = PORTB.5
// Canal B = PORTB.4
if ((bit_test(current,4)) && (bit_test(current,5))){
   if ((bit_test(last,4)) ^ (bit_test(current,5))){
      //sentido agujas del reloj, incrementar.
      IncDec=INCREMENTAR;
   }
   else{
        //sentido contrario agujas del reloj, decrementar.
        IncDec=DECREMENTAR;
   }
}
last=current;
}

Por otro lado, la explicacion del codigo está en el enlace que puse ( http://www.bolivar.udo.edu.ve/microinternet/articulos/Usando%20Quadrature%20Encoder.pdf )

El filtro RC, creo conveniente ponerlo, en mi aplicación funciona mejor poniendolo. Sin el se saltaba algunos pulsos de giro del encoder.

Si lo quieres hacer por INT_EXT, mira la respuesta de Nocturno de este hilo, no se me habia ocurrido pero es otra forma de hacerlo ( http://www.todopic.com.ar/foros/index.php?topic=24722.0 ).

Un saludo.
« Última modificación: 06 de Febrero de 2009, 13:36:56 por micro_pepe »
Se obtiene más en dos meses interesandose por los demás, que en dos años tratando de que los demás se interesen por ti.

新年快乐     的好奇心的猫死亡

Desconectado Marttyn

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1836
    • IDEAA
Re: Lectura de encoder.
« Respuesta #4 en: 07 de Febrero de 2009, 08:12:22 »
gracias micro_pepe!
la verdad que te pregunte sin haber investigado demasiado, y como no recibi respuesta me puse a experimentar con mi encoder y un par de leds para ver como funcionaba.
llegue a la misma conclusion que nocturno con respecto a la int_ext.
y llegue a la misma conclusion que tu con respecto al filtro RC.  :mrgreen:
Salu2
La gente ve las cosas que existen y se pregunta por qué.
Yo prefiero imaginar lo que no existe y preguntarme por qué no.

Desconectado jhon364

  • PIC10
  • *
  • Mensajes: 6
Re: Lectura de encoder.
« Respuesta #5 en: 16 de Febrero de 2009, 12:25:36 »
Hola Marttyn la verdad yo no la haría por interrupcion externa yo utilizaría el contador del micro para contar los pulsos del encoder y solo tendria una relacion contador del timmer con la lectura y el micro no estaría ocupado todo el tiempo contando te parece.... creo que el micro que trabajas tiene timmers/counter yo lo harñia así el unico detalle es que cuando este se desborda tendass que hacer un arreglo de una variable pero lo bueno de esta idea es que puedes hacer otras cosas sin que se te pierda ningun pulso. Si quieres te puedo mostrar como utilizar este arreglo para pulsos mayores pero en PIC18F452 ya que tengo un proyecto hecho con esto.

Desconectado Marttyn

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1836
    • IDEAA
Re: Lectura de encoder.
« Respuesta #6 en: 16 de Febrero de 2009, 12:45:37 »
Hola amigo! Bienvenido al foro!
Gracias por tu aporte, pero el codigo ya lo tengo implementado y funcionando de 10. Realmente de todas las soluciones, la de la INT_EXT es la que mas me gusta y mas reducida me queda. Ademas, el micro no esta pendiente del encoder todo el tiempo. Cuando se gira el encoder salta la int, y alli activo un flag avisando que se giro el encoder y para que lado. realmente es muy sencillo!
Este es todo el codigo que necesito:

Código: C
  1. #int_EXT
  2. void EXT_isr(void){
  3.         flagGiro = TRUE;
  4.         Sentido = ENC_B;
  5. }

El pin A del encoder se conecta a la int ext, y el pin B puede ser cualquiera, y lo defino en el programa como ENC_B. Si Sentido es 1, giro a la izquierda, si es 0 giro a la derecha.

Igualmente expon como lo harias con el contador... tal vez si es mejor como dices tu y me convences  :mrgreen:
Salu2
La gente ve las cosas que existen y se pregunta por qué.
Yo prefiero imaginar lo que no existe y preguntarme por qué no.

Desconectado pacho2012

  • PIC10
  • *
  • Mensajes: 1
Re: Lectura de encoder.
« Respuesta #7 en: 13 de Mayo de 2010, 12:01:43 »
hola pepe  mira  lo que pasa es que  trate  de hacer el montaje en picc y en proteus
en picc me bota  muchos errores  y  el montaje  de  proteus no me funciona me podria  decir  porque


Desconectado raito

  • PIC10
  • *
  • Mensajes: 2
Re: Lectura de encoder.
« Respuesta #8 en: 10 de Septiembre de 2013, 13:40:50 »
Hola soy nuevo en el foro y


Solo quiero que en un lcd me visualice la direccion de giro del encoder (derecha o izquierda) y pues la verdad solo me detecta un sentido de giro y no se cambia de uno a otro
utilice una interrupcion externa y puse instrucciones del LCD para que me mostrara la direccion de giro. La rutina de interrupcion que utilice en CCS fue la siguiente

#INT_EXT                      //Interrupcion externa por RB0

Void IntRB0()
{
 
  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 interrupcion por
                              //flanco de bajada
      If (Bit_Test(PortB, 1))       //si RB1 esta a 1
     
      //Aca quiere decir que va en sentido de las agujas del reloj
{       
         printf(lcd_putc,"\fDerecha");
         } 
}
Else                          //si RB0 se ha puesto a 0 (Flanco de bajada)

      //en este caso indica que el sentido es en contra de las agujas
      Ext_Int_Edge(L_TO_H);     //entonces activar la siguiente interrupcion por
                              //flanco de subida
      If (Bit_Test(PortB, 1))   //si RB1 esta a 1
     
    {
           printf(lcd_putc,"\fizquierda");     
           }
   
Mi duda es si estuvo mal haber puesto dentro de la interrupcion la instruccion de que se visualizara en el LCD, porque ademas me manda warnings del tipo 216 y dice que me desactivan las interrupciones.

De antemano gracias por sus aportes

Desconectado RALF2

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 2062
Re: Lectura de encoder.
« Respuesta #9 en: 10 de Septiembre de 2013, 14:43:28 »
Hola raito!
Amigo no colocas que tipo de encoder estas utilizando, modelo...
Para asi ayudarte mejor, pero te adelanto. Si tienes el modelo que pienso... podrias hacer lo siguiente:
Colocas el canal B como señal de reloj y el A como sentido de giro; de esta forma, cuando la señal de reloj cambie de 0 -->1, ves el nivel logico de A si es un uno gira para un lado y si es cero gira para el otro   :mrgreen:

Alli te dejo eso  :D

Desconectado raito

  • PIC10
  • *
  • Mensajes: 2
Re: Lectura de encoder.
« Respuesta #10 en: 11 de Septiembre de 2013, 10:50:26 »

Desconectado RALF2

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 2062
Re: Lectura de encoder.
« Respuesta #11 en: 11 de Septiembre de 2013, 20:48:55 »
raito
Tu encoder es optico, de tipo incremental, con salidas tipo NPN; lo que quiere decir, que debes colocar una resistencia desde cada salida a Vcc, luego como te indique arriba toma por ejemplo la señal del canal A como señal de reloj (Clk) de forma tal que cada vez que el canal A cambie de 0 a 1, lees el canal B y si es un "1" gira en un sentido y si es "0", gira en sentido contrario. Para ello podrias porgrama el pic para que cada vez que se detecte un flanco de subida generado por el canal A, leas el canal B y asi sepas para donde gira el encoder.
Otra forma, sin un pic, seria valerte de un flip flop tipo D, colocas el canal A como señal de reloj y el canal B como datos; de esta forma al girar el motor tendras un "1" o "0" a la salida del flip flop de acuerdo para donde gire el encoder  :mrgreen:

Saludos


 

anything