TODOPIC

Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: Algec en 10 de Julio de 2012, 15:54:52

Título: INterrupcion de MPG, no detecta el sentido de giro
Publicado por: Algec en 10 de Julio de 2012, 15:54:52
USo una interrupcion para contar puloso de un MPG y no funciona bien,
No detecta el sentido de giro correctamente. Esta escrito en Hitec y el original, que no funciona bien es esta rutina

// GESTION DEL MPG POR INTERRUCION SE USA INT0
// LA INTERRUPCION DETECTA EL SENTIDO DE GIRO Y MANTIENE UN CONTADOR
//************************************************************************
void interrupt Isr(void) 
{
 if (SSPIF)   
    {
     SSPIF = 0;   
     isrEnd = 1;
    }
 if (INTF) // interrupcion mpg2 pines rb0(a) y rb1(b) la resolucion es X1
     {
      (RB1) ? MPG++: MPG--; // esto es un if un poco raro jejeje
      INTF=0; // fin de la int para MPG a X1
     }
}


YO la he modificado asi, pero tampoco detecta el sentido , si los pulsos, es decir como la anterior.


//************************************************************************
// Funcion que verifica el valor de un bit de una variable
//  Devuelve el valor del bit que se chequea
//************************************************************************

int bittest(var,bitno){
int var_int=0;
if(bitno==0)
   var_int = var & 0x00000001;
if(bitno==1)
   var_int= var &0x00000010;   
return var_int;
}


//************************************************************************
// SERVICIOS DE INTERRUPCION
//
//
//
// GESTION DEL MPG POR INTERRUCION SE USA INT0
// LA INTERRUPCION DETECTA EL SENTIDO DE GIRO Y MANTIENE UN CONTADOR
//************************************************************************
//como hacer un test de un bit
// variable_aux = variable & 0b00000010;
// si el bit 1 de variable estaba en 1, el resultado de la and es 2.
// if (variable_aux == 2) ....   
// evaluo el valor, para saber si el bit estaba en 1


void interrupt Isr(void) 
{
 if (SSPIF)   
    {
     SSPIF = 0;   
     isrEnd = 1;
    }
 if (INTF) // interrupcion mpg2 pines rb0(a) y rb1(b) la resolucion es X1
     {
      lec_mpg=(RB1*2)+RB0; // carga en mpg el valor en gray de las entradas RB0 y RB1
   

     if(bittest(lec_mpg,1)==1)        // si el bit 1 de valor es 1
         {
         if(bittest(lec_mpg,0)==0)     // invierte el bit 0 de valor
            bitset(lec_mpg,0);         // hace 1 el bit 0 de valor
         else
            bitclr(lec_mpg,0);      // hace cero el bit 0 de valor
         }
       
   if(lec_mpg!=lec_mpg_old){
      diferencia =lec_mpg-lec_mpg_old;
      if(bittest(diferencia,0) == 0)   // si se ha producido un error se habra puesto a cero el bit 0
            {
           
         } 
         else
            {   
            if(bittest(diferencia,1) == 1) // chequea el bit de sentido de giro que sera 1 girando a derecha
               MPG++;                // si es hacia un lado incrementa el contador
            else
               MPG--;            // hacia el otro lo decrementa
            }
           // memoriza en anterior_Z el estado actual
            lec_mpg_old  = lec_mpg;

         
   }      
      

Podeis echarme una mano, no se casi nada de hitec, por no decir nada. Siempre he trabajado en CCS.


Gracias
Título: Re: INterrupcion de MPG, no detecta el sentido de giro
Publicado por: Algec en 15 de Julio de 2012, 12:42:23
Sigo liado con esto, me he dado cuenta de que Hitec no gestiona las interrupciones como lo hace CCS.
Creia que la interrupcion que se activaba en Hitec era la INT_RB del CCS pero no es asi, ya que los pines que detecta son RB0 Y RB1 y eso no es en CCS.
En CCS INT_RB vigila RB3 al RB7.
A ver quien me traduce esto, porque no se quien genera la interrupcion y eso puede ser parte del problema.

EN Hitec esta asi

// GESTION DEL MPG POR INTERRUCION SE USA INT0
// LA INTERRUPCION DETECTA EL SENTIDO DE GIRO Y MANTIENE UN CONTADOR
//************************************************************************
void interrupt Isr(void) 
{
 if (SSPIF)   
    {
     SSPIF = 0;   
     isrEnd = 1;
    }
 if (INTF) // interrupcion mpg2 pines rb0(a) y rb1(b) la resolucion es X1
     {
      (RB1) ? MPG++: MPG--; // esto es un if un poco raro jejeje
      INTF=0; // fin de la int para MPG a X1
     }
}
 

Esta interrupcion es cierto que vigila cambios de estado de RB0 Y RB1?
Si es asi como se haria en CCS? ya que no me sirve INT_RB y no se que haya nada que haga eso.



Sigo teniendo elmismo problema , en HiTEC no consigo que se discrimine el sentido de giro del MPG porque esta rutina de interrupcion no va bien. Asi que trato de enmendarla en CCS que es lo que conozco pero me encuentro problemas porque no se que hace Hitec.
Quien me puede echar una manita que sepa de Hitec?

Mil gracias
Título: Re: INterrupcion de MPG, no detecta el sentido de giro
Publicado por: Algec en 15 de Julio de 2012, 19:16:49
Rehice la rutina y compila bien. Aun no pude probarla en hardware, pero a ver quien puede decirme si me equivoco en algo y quien demonios activa la rutina de interrupcion....No me entero de como va el HITEC

Código: C
  1. //************************************************************************
  2. // SERVICIOS DE INTERRUPCION
  3. //
  4. //
  5. //
  6. // GESTION DEL MPG POR INTERRUCION SE USA INT0
  7. // LA INTERRUPCION DETECTA EL SENTIDO DE GIRO Y MANTIENE UN CONTADOR
  8. //************************************************************************
  9.  
  10. void interrupt Isr(void)  
  11. {
  12.  if (SSPIF)    
  13.          {
  14.           SSPIF = 0;  
  15.           isrEnd = 1;
  16.          }
  17.  
  18.  
  19.  if (INTF) // interrupcion mpg2 pines rb0(a) y rb1(b) la resolucion es X1
  20.           {
  21.            lec_mpg=(PORTB && 0x00000011); // carga en mpg el valor leido del encoders MPG, que estara en codigo gray, de las entradas RB0 y RB1
  22.                 // codigo gray
  23.                 //  00    0
  24.                 //  01    1
  25.                 //  11    3
  26.                 //  10    2
  27.                 //  00    0
  28.                 //  ....
  29.    
  30. // convierte de gray a decimal
  31.  
  32.                 // codigo gray      decimal
  33.                 //  00    0                       00    0      
  34.                 //  01    1                       01    1      
  35.                 //  11    3           10        2
  36.                 //  10    2           11        3
  37.                 //  00    0           00    0
  38.                 //  ....                          ........
  39.  
  40. // para pasar de gray a decimal se vigila el bit de mayor peso, si es uno, se invierte el bit de menor peso, si no queda como estaba
  41.  
  42.  
  43.  
  44.                 if(((lec_mpg && 0x00000010))==2)  // si el bit 1 de lec_mpg es ==1       
  45.                 {
  46.                 if(((lec_mpg && 0x00000001)==0))        // si el bit 0 de lec_mpg  es cero
  47.                                 bitset(lec_mpg,0);         // hace 1 el bit 0 de valor
  48.                 else
  49.                 bitclr(lec_mpg,0);      // hace cero el bit 0 de valor
  50.                
  51.                         // aqui lec_mpg es decimal
  52.                         // calcula la diferencia entre el anterior y el actual
  53.                        
  54.                         diferencia = lec_mpg - lec_mpg_old;    
  55.                        
  56.                         // si el bit 1 de diferencia es == 1 es que esta girando a derecha
  57.  
  58.                         if(((diferencia && 0x00000010)==2)) // chequea el bit de sentido de giro que sera 1 girando a derecha
  59.                MPG++;                // si es hacia un lado incrementa el contador
  60.             else
  61.                MPG--;            // hacia el otro lo decrementa
  62.             }
  63.          
  64.                         // memoriza el valor  actual
  65.             lec_mpg_old  = lec_mpg;
  66.  
  67.         }              
  68.         INTF=0; // fin de la int para MPG a X1
  69. }
  70.  
  71.  
  72. // *****************************
  73. // ACTIVAR INTERRUPCIONES
  74. // *****************************
  75.  
  76. void setISR(void) /*Sets ISR bits */
  77. {
  78. GIE = 0;
  79. PEIE = 0;
  80. RCIE = 0;
  81. SSPIE = 0;
  82. EEIE = 0;
  83. INTE=  1; // Activar interrupcion INT0
  84. RBIE = 0; // DESActivar interrupciones on pin change del puerto B
  85. MPG = 0;  // Inicializa contador MPG
  86. GIE = 1;  // permite las ints (todas las activadas)
  87. }


Cualquier cambio de RB0 o RB1 activaria esta interrupcion?
Eso es lo que debe hacer, ya que el encoder esta en esos pines.
Título: Re: INterrupcion de MPG, no detecta el sentido de giro
Publicado por: Nocturno en 16 de Julio de 2012, 01:56:41
Me he permitido modificar tu post para meterle format GeSHi al código y que se entienda mejor.

Tampoco conozco Hitech pero deduzco que para que se active la interrupción se hace escribiendo directamente los registros del micro.

Código: C
  1. void setISR(void) /*Sets ISR bits */
  2. {
  3. GIE = 0;
  4. PEIE = 0;
  5. RCIE = 0;
  6. SSPIE = 0;
  7. EEIE = 0;
  8. INTE=  1; // Activar interrupcion INT0
  9. RBIE = 0; // DESActivar interrupciones on pin change del puerto B
  10. MPG = 0;  // Inicializa contador MPG
  11. GIE = 1;  // permite las ints (todas las activadas)
  12. }

En esta función has desactivado las interrupciones pin change del puerto B. ¿No tendrías que poner RBIE=1?
Título: Re: INterrupcion de MPG, no detecta el sentido de giro
Publicado por: Algec en 16 de Julio de 2012, 08:31:44
A ver eso es copiado del original, y el original funciona pero no determina el sentido de giro.
Ya he probado la nueva compilacion y esa no funciona, no entra en la interrupcion o al menos no aumenta ni disminuye MPG
Yo creo que el problema esta en que no se esta detectando los cambios de RB0 Y RB1 y que la interrupcion no se ejecuta.
EN el original (esta el codigo en el post) detecta algo y arranca la interrupcion, pero no detecta sentido de giro, es mas detecta el que le parece.
En la modificacion ultima mia, deberia funcionar si no me equivoque en algo pero no se ejecuta la interrupcion o al menos no aumenta ni disminuye MPG.
No puedo testearlo en Proteus porque no se como, asi que solo puedo modificar compilar y probar en hardware.
Una cuestion para mi es, esa interrupcioon arranca al cambiar el estado de RB0 y RB1?
Si en CCS INT_RB solo vigila rb4 al 7 como hace esto Hitec?

Una cosa mas,,,,,,Nocturno...ya no se que decirte, siempre sales en mi ayuda.
Mil gracias de nuevo, con gente como tu el mundo iria mejor seguro.

Título: Re: INterrupcion de MPG, no detecta el sentido de giro
Publicado por: Nocturno en 16 de Julio de 2012, 08:56:19
Pero en el código original la interrupción que se levanta es la de INT0, que suele estar en RB0.
Si es así, sólo habría que comprobar si RB1 es alto o bajo para saber el sentido de giro.
No se están usando las interrupciones por cambio de estado, así que retiro lo dicho en el post anterior.

¿Cómo lo tienes conectado?
Título: Re: INterrupcion de MPG, no detecta el sentido de giro
Publicado por: Algec en 16 de Julio de 2012, 09:00:43
A ver no estoy muy de acuerdo en que si se ejecuta la rutina cuando cambia de estado RB0 solamente, sin tener en cuenta el cambio de RB1 , depende del estado de RB1 si es alto o bajo, esta girando a derecha o izda.
Eso es lo que dice Siliconio cuando hizo la rutina, pero lo cierto es que no funciona asi.
El problema es claro, no sabe para que lado va en la rutina original.
Ejecuta la interrupcion pero dtecta el sentido que le parece
Título: Re: INterrupcion de MPG, no detecta el sentido de giro
Publicado por: Algec en 16 de Julio de 2012, 11:12:48
Vale ya he visto como es. tuve que tirar de libros etc, y tratar de recordar algo de ensamblador y demas.
La interrupcion con el programa original se genera con el flanco de subida de RB0 solamente. EN ese caso he estado mirando y tienes razon (como siempre jajaja) . Si el estado de RB1 es positivo cuando llega ese flanco esta girando hacia un lado, si es negativo gira hacia  el otro.
Bien parece que el programa deberia estar bien, pero lo cierto es que no detecta el sentido de giro. He probado con dos encoders, uno puramente mecanico y el otro es uno comercial industrial electronico optico y que con el osciloscopio va perfecto, (el mecanico tambien)
Quizas cambiando el pic por uno de mayor velocidad la rutina de interrupcion se ejecute mejor? mas rapido? y esa pueda ser la causa?
Usa uno de 4 Mhhz, Pruebo con 12 Mhz?
Tambien he pensado en poner algo a la salida del encoder y que adapte mejor la señal, incluso hacer un divisor que divida por 4 los pulsos para que lleguen menos. Es posible que sea eso? o quizas algo que mejore mas la señal? Ya tiene resistencias de pullup y no se que mas hacer.
La verdad me tiene aburrido.
Alguien tiene  el siliconio Modbus para mach3 funcionando con MPG y le va bien?
Lo demas del modbus va perfecto, pero necesitaria eso....es casi imprescindible.


Título: Re: INterrupcion de MPG, no detecta el sentido de giro
Publicado por: Nocturno en 16 de Julio de 2012, 13:05:02
Insisto, cuelga el esquema, sospecho que debe ser algo sencillo y no lo vemos por no tenerlo delante.
Título: Re: INterrupcion de MPG, no detecta el sentido de giro
Publicado por: Algec en 16 de Julio de 2012, 14:40:51
vale luego lo cuelgo
Título: Re: INterrupcion de MPG, no detecta el sentido de giro
Publicado por: Algec en 17 de Julio de 2012, 16:16:52
Ahi va a ver que me decis
Título: Re: INterrupcion de MPG, no detecta el sentido de giro
Publicado por: Nocturno en 18 de Julio de 2012, 01:31:14
Lo he intentado abrir y no puedo con Altium, supongo que será Eagle. ¿Te importa convertirlo a PDF o JPG?
Título: Re: INterrupcion de MPG, no detecta el sentido de giro
Publicado por: Algec en 18 de Julio de 2012, 08:54:18
Ahi lo llevas en JPG. El encoder esta conectado entre RB0, RB1, 5 V y cero.
Título: Re: INterrupcion de MPG, no detecta el sentido de giro
Publicado por: Algec en 18 de Julio de 2012, 08:54:52
Se me paso subirlo
Título: Re: INterrupcion de MPG, no detecta el sentido de giro
Publicado por: Nocturno en 18 de Julio de 2012, 09:30:58
No veo nada raro en el esquema.
Pero revisando el código sí que he encontrado algo. Este trozo de código está dentro de la interrupción:

Código: C
  1. if(((lec_mpg && 0x00000010))==2)  // si el bit 1 de lec_mpg es ==1       
  2.                 {
  3.                 if(((lec_mpg && 0x00000001)==0))        // si el bit 0 de lec_mpg  es cero
  4.                                 bitset(lec_mpg,0);         // hace 1 el bit 0 de valor
  5.                 else
  6.                 bitclr(lec_mpg,0);      // hace cero el bit 0 de valor
  7.                
  8.                         // aqui lec_mpg es decimal
  9.                         // calcula la diferencia entre el anterior y el actual
  10.                        
  11.                         diferencia = lec_mpg - lec_mpg_old;

Habíamos quedado en que la interrupción se produce en el flanco ascendente de INT0, o lo que es igual, cuando entres en la interrupción el pin RB0 siempre estará a 1.
Si esto es cierto, esta condición nunca se cumplirá:
if(((lec_mpg && 0x00000001)==0))   // si el bit 0 de lec_mpg  es cero

¿Estoy en lo cierto o lo he interpretado mal?
Título: Re: INterrupcion de MPG, no detecta el sentido de giro
Publicado por: Algec en 19 de Julio de 2012, 08:26:20
Esa fue mi modificacion que no funciono, mejor mira el codigo que subi ultimo que es el original. Ese si deberia funcionar segun todo lo que hemos hablado. Y lo cierto es que tampoco detecta el sentido
Título: Re: INterrupcion de MPG, no detecta el sentido de giro
Publicado por: Nocturno en 19 de Julio de 2012, 08:37:49
El último código que subiste tiene ese mismo error. ¿O es que estamos hablando de posts diferentes?
Línkamelo o pega el código de nuevo, please.
Título: Re: INterrupcion de MPG, no detecta el sentido de giro
Publicado por: Algec en 19 de Julio de 2012, 08:55:21
Este es el codigo original
Título: Re: INterrupcion de MPG, no detecta el sentido de giro
Publicado por: Nocturno en 19 de Julio de 2012, 09:08:58
Pues ahí no veo nada raro, ¿tienes la posibilidad de hacer debug paso a paso?
Yo pondría un breackpoint dentro de la interrupción mientras pruebo el giro a un lado y luego a otro.
Título: Re: INterrupcion de MPG, no detecta el sentido de giro
Publicado por: Algec en 19 de Julio de 2012, 09:11:00
A ver no se si podria pero esque suelo probar estas cosas con proteus y poner un LCD porque no se usar bien el debuguer, ademas como es un encoder es dificil de ver ya que hay que poner un motor con generador y lo mas facil es usar un lcd que este funcionando a la vez que el programa y asi ver que falla poco a poco.
No se como hacerlo
Título: Re: INterrupcion de MPG, no detecta el sentido de giro
Publicado por: Nocturno en 19 de Julio de 2012, 09:35:48
Si lo vas a hacer en proteus, ponle un par de interruptores, uno conectado a RB0 y el otro a RB1.
Cierras el de RB0 para que entre en la interrupción y vas siguiendo el resultado en función del valor de RB1.
De todas formas, son muchas las ocasiones en que el parecido entre Proteus y la vida real es pura coincidencia.
Título: Re: INterrupcion de MPG, no detecta el sentido de giro
Publicado por: Algec en 20 de Julio de 2012, 08:11:07
Lo he probado con proteus y si que funciona bien. He estado pensando (novedad....) y quizas no sea el problema del programa o del hardware, sino del MAch3, de la forma en que se transmite el dato del MPG con el brain. Quizas necesite algun experto en Mach3.
Lo mejor seria que el fenomeno de Siliconio apareciese y me echase una mano.
De todas formas tengo que seguir trabajando para solucionarlo.
Mil gracias