# Problemas con el GIRÓSCOPO



## Zuri (May 19, 2010)

Hola!

Dispongo del giróscopo digital de tres ejes ITG-3200 de invensense. El caso es que estoy trabajando con el, pero no funciona como yo esperaba. Según su datasheet la salida de los ejes, es la velocidad angular, es decir los grados por segundo que gira en cada eje. En mi caso, las salidas que obtengo cuando está quieto (que deberían ser 0) son:

VELOCIDADES ANGULARES X         Y            Z       

                       x= 42    y= -110    z= -17    
                       x= 44    y= -116    z= -16    
                       x= 46    y= -108    z= -18    
                       x= 47    y= -111    z= -18    
                       x= 45    y= -111    z= -15    
                       x= 48    y= -110    z= -15    
                       x= 41    y= -112    z= -17    
                       x= 44    y= -106    z= -19    
                       x= 46    y= -112    z= -15    
                       x= 45    y= -108    z= -17    
                       x= 46    y= -110    z= -17    
                       x= 47    y= -114    z= -16    
                       x= 48    y= -111    z= -18    
                       x= 45    y= -112    z= -12    
                       x= 46    y= -113    z= -16    
                       x= 43    y= -110    z= -14    
                       x= 46    y= -112    z= -17    
                       x= 46    y= -117    z= -20    
                       x= 45    y= -117    z= -18    
                       x= 47    y= -113    z= -14    
                       x= 45    y= -111    z= -15    
                       x= 45    y= -112    z= -20    
                       x= 43    y= -115    z= -20    
                       x= 48    y= -114    z= -16    
                       x= 47    y= -108    z= -16    
                       x= 46    y= -108    z= -16    
                       x= 45    y= -111    z= -16    
                       x= 46    y= -113    z= -15    
                       x= 50    y= -111    z= -16    
                       x= 46    y= -113    z= -16    
                       x= 44    y= -113    z= -17    
                       x= 44    y= -111    z= -17    
                       x= 50    y= -113    z= -18    
                       x= 41    y= -116    z= -16    
                       x= 44    y= -111    z= -17    
                       x= 47    y= -115    z= -16    
                       x= 49    y= -113    z= -17    
                       x= 48    y= -113    z= -14    
                       x= 46    y= -110    z= -17    
                       x= 45    y= -111    z= -16    
                       x= 39    y= -107    z= -13    
                       x= 44    y= -110    z= -14    
                       x= 47    y= -112    z= -15    
                       x= 47    y= -111    z= -15    
                       x= 47    y= -110    z= -14    
                       x= 58    y= -112    z= -17    
                       x= 43    y= -115    z= -16    
                       x= 44    y= -113    z= -16    
                       x= 47    y= -114    z= -18    
                       x= 44    y= -112    z= -15    
                       x= 47    y= -110    z= -17    
                       x= 53    y= -113    z= -16    
                       x= 46    y= -115    z= -14    
                       x= 45    y= -113    z= -11    
                       x= 47    y= -108    z= -16    
                       x= 45    y= -112    z= -16    
                       x= 45    y= -109    z= -12    
                       x= 42    y= -109    z= -17    
                       x= 44    y= -111    z= -12 


He buscado a ver si es poblema de calibración, pero en el datasheet no viene ninguna indicación de como hacerla.

Os dejo un link por si quereis echar un vistazo:

http://invensense.com/mems/gyro/documents/PS-ITG-3200-00-01.4.pdf


----------



## tecnogirl (May 20, 2010)

Zuri:
1. No estará dañado el sensor ?. Prueba otro.
2. No estará mal conectado ?. Revisa y comprueba las indicaciones del fabricante.

Saludos


----------



## Zuri (May 21, 2010)

Por que crees que puede estra dañado o mal conectado? 

Qué valores tendrían que dar en cada eje mas o menos, según tu? según el datasheet zero rate output es +-40. Pero, como no está calibrado ni nada...no sé. Dame tu opinión, yo soy nueva en esto y no controlo mucho.


----------



## Beamspot (May 21, 2010)

Enhorabuena por haber conseguido el sensor, después de tanto buscar.

¿Puedes poner cómo lo tienes montado? ¿PCB, layout? ¿Esquema del sistema de test que tienes puesto/montado?

¿El software puede leer correctamente los registros internos del sensor?¿El registro WhoAmI?¿La Temperatura? ¿Cómo lo haces para leer los valores de giro/temperatura?


----------



## Zuri (May 24, 2010)

Sí!

A la hora de leer los registros y escribir en ellos no hay ningún problema. Para ello, lo hago así:

void mostrarGyroscope(uint16*x,uint16*y,uint16*z, uint16 offset_x,uint16 offset_y,uint16 offset_z)
{

uint16*data;	

uint8 readVector[6];

uint8 writeVector_1[1] = {0x1A}; 
uint8 writeVector_2[1] = {0x1D};


I2cTransfer(I2C_GIR_T1_WRITE , writeVector_1, 1, NULL, 0); 
I2cTransfer(I2C_GIR_T1_READ , NULL, 0, readVector, 1);

    if(readVector[0]&0x01) /* Se mira el registro InterruptStatus (0x1A), todos los bits son 0 menos el ultimo que estará a 1 cuando hay datos para leer*/
    {

                I2cTransfer(I2C_GIR_T1_WRITE , writeVector_2, 1, NULL, 0); 
	    I2cTransfer(I2C_GIR_T1_WRITE , NULL, 0, readVector, 6);




		data = (uint16*)malloc(sizeof(uint16)*3);


		data[0]=readVector[0];
		data[0]=(data[0]<<8)+readVector[1];

		data[1]=readVector[2];
		data[1]=(data[1]<<8)+readVector[3];

		data[2]=readVector[4];
		data[2]=(data[2]<<8)+readVector[5];


		*x=data[0];
		*y=data[1];
		*z=data[2];


        if((data[0]>>15)&0x01)
        {

			*x = !((data[0]>>14)&0x01);
			*x = (*x<<1) + !((data[0]>>13)&0x01);
			*x = (*x<<1) + !((data[0]>>12)&0x01);
			*x = (*x<<1) + !((data[0]>>11)&0x01);
			*x = (*x<<1) + !((data[0]>>10)&0x01);
			*x = (*x<<1) + !((data[0]>>9)&0x01);
			*x = (*x<<1) + !((data[0]>>8)&0x01);
			*x = (*x<<1) + !((data[0]>>7)&0x01);
			*x = (*x<<1) + !((data[0]>>6)&0x01);
		    *x = (*x<<1) + !((data[0]>>5)&0x01);
            *x = (*x<<1) + !((data[0]>>4)&0x01);
            *x = (*x<<1) + !((data[0]>>3)&0x01);
            *x = (*x<<1) + !((data[0]>>2)&0x01);
            *x = (*x<<1) + !((data[0]>>1)&0x01);
            *x = (*x<<1) + !(data[0]&0x01);

            *x = *x + 0x01;
            *x = *x&0x7FFF;
            *x = -*x;
        }
        else
        {
            *x = data[0];
        }

        if((data[1]>>15)&0x01)
        {


			*y = !((data[1]>>14)&0x01);
			*y = (*y<<1) + !((data[1]>>13)&0x01);
			*y = (*y<<1) + !((data[1]>>12)&0x01);
			*y = (*y<<1) + !((data[1]>>11)&0x01);
			*y = (*y<<1) + !((data[1]>>10)&0x01);
			*y = (*y<<1) + !((data[1]>>9)&0x01);
			*y = (*y<<1) + !((data[1]>>8)&0x01);
			*y = (*y<<1) + !((data[1]>>7)&0x01);
			*y = (*y<<1) + !((data[1]>>6)&0x01);
			*y = (*y<<1) + !((data[1]>>5)&0x01);
            *y = (*y<<1) + !((data[1]>>4)&0x01);
            *y = (*y<<1) + !((data[1]>>3)&0x01);
            *y = (*y<<1) + !((data[1]>>2)&0x01);
            *y = (*y<<1) + !((data[1]>>1)&0x01);
            *y = (*y<<1) + !(data[1]&0x01);

            *y = *y + 0x01;
            *y = *y&0x7FFF;
            *y = -*y;
        }
        else
        {
            *y = data[1];
        }

        if((data[2]>>15)&0x01)
        {

			*z = !((data[2]>>14)&0x01);
			*z = (*z<<1) + !((data[2]>>13)&0x01);
			*z = (*z<<1) + !((data[2]>>12)&0x01);
			*z = (*z<<1) + !((data[2]>>11)&0x01);
			*z = (*z<<1) + !((data[2]>>10)&0x01);
		    *z = (*z<<1) + !((data[2]>>9)&0x01);
			*z = (*z<<1) + !((data[2]>>8)&0x01);
			*z = (*z<<1) + !((data[2]>>7)&0x01);
		    *z = (*z<<1) + !((data[2]>>6)&0x01);
            *z = (*z<<1) + !((data[2]>>5)&0x01);
            *z = (*z<<1) + !((data[2]>>4)&0x01);
            *z = (*z<<1) + !((data[2]>>3)&0x01);
            *z = (*z<<1) + !((data[2]>>2)&0x01);
			*z = (*z<<1) + !((data[2]>>1)&0x01);
            *z = (*z<<1) + !(data[2]&0x01);

            *z = *z + 0x01;
            *z = *z&0x7FFF;
            *z = -*z;
        }
        else
        {
            *z = data[2];
        }


		*x=*x-offset_x;
		*y=*y+offset_y;
		*z=*z+offset_z;

		free(data);

}


El gyroscope está montado en una PCB, voy a pasaros el esquema


----------



## Beamspot (May 24, 2010)

¿Has probado a mostrar directamente los datos leídos, sin todo ese trasiego de bits? No entiendo para nada esa historia que montas con tanto *x = (*x <<1) +|... ¿me la puedes explicar?

Si la lectura directa de los registros más o menos concuerda, quedan dos caminos muy diferentes a recorrer: uno es que tengas problemas con el diseño HW (PCB, condensadores, etc) y otra es un problema con el procesado de los datos adquiridos (precisamente esa parte que no entiendo).

¿Puedes poner una traza de los datos leidos directamente del sensor, a ser posible de todos los registros, sin procesarlos de ninguna manera? Es interesante ver los datos leídos 'a palo seco', y comparar si se corresponden con lo previsto/esperado.


----------



## Zuri (May 25, 2010)

Lo que hago, si lo que se ha leido es negativo, pasarlo de complemento a dos a normal, ya que si no se hace, lo que se mostraría no sería el valor correcto.


----------



## Beamspot (May 25, 2010)

No hace falta complicarse tanto la vida. Con un union (siendo 'legal') o jugando con la definición de los punteros (haciendo typecast o 'trampas') se puede conseguir leer directamente signed ints de 16 bits. Maravillas del C.

Con semejante formato, ya no hay problema de mostrar nada ni de convertir nada. Simplemente, le dices al programa que data=&Readvector y ya está, lees directamente los valores x=data[0]; y=data[1]; z=data[2]; Luego, depende de como los presentes (printf?).


----------



## Zuri (May 28, 2010)

Hola Beamspot!

Además del tema de la calibración, tengo otra duda. Según entiendo yo del datasheet, sus salidas solo pueden estar entre -2000 y 2000 (º/s), ya que el Full Scale Range es ese.

La cosa, es que cuando yo giro en alguno de sus ejes, sobrepasa ese valor.

                       x= 44    y= -81    z= -8       
                       x= 40    y= -78    z= -14       
                       x= 42    y= -79    z= -12       
                       x= 1691    y= -146    z= 68       
                       x= 3100    y= -111    z= 107       
                       x= 743    y= -25    z= 22       
                       x= 41    y= -97    z= -13       
                       x= 41    y= -107    z= -13       
                       x= 41    y= -75    z= -16      

En este caso, he girado en dirección positiva sobre el eje x.

Además, como puedes comprobar, además de a ver una velocidad en el eje x, también influye en los otros dos ejes, aunque realmente no se haya girado sobre ellos.


----------



## Beamspot (May 28, 2010)

1º ¿Cómo lo giras? Si lo haces a mano es fácil añadir valores de un eje a otro. Y si lo hago yo, ni te cuento, con el tembleque que tengo.
2º Si no me falla la memoria, en algún sitio de pondrá la correspondencia entre los pasos y la medida. Creo que era un ADC interno de 16 bits, con lo que a fondo de escala presumiblemente te de una lectura de alrededor de 32000 pasos, que equivaldrían a 2000º/S es decir, que un º/s equivaldría a 16 pasos. Esto lo tienes que confirmar con el datasheet, ojo, que mi memoria me juega muy malas pasadas, pero espero al menos que entiendas el concepto. Segú esto, habrías girado a unos 200º/S en el pico de velocidad angular.
3º- Espera una alinealidad, un offset y un desajuste para cada eje, y probablemente algo de interrelación. De usar mates, rectas de regresión y similares no te escapas ni por asomo. Lo más difícil sería ajustar finamente la calibración del sistema, aunque es factible.


----------



## Zuri (May 28, 2010)

1.- Lo mantengo en la mesa y apoyandome en la mesa.

2.- La verdad es que no he entendido el concepto. Si, no te importa, explicámelo con otras palabras por favor.


----------



## Beamspot (May 28, 2010)

En la página 6 del PDF que tengo yo, pone que tiene una sensibilidad de 14.375 LSB's por º/s. Es decir, que cuando detecta un giro de alrededor de 1º/s, el registro de devolverá 14 o 15. Si el giro de de 2º/s, leerás 28-29, etc. Si lees 1437, es que tienes un giro de 100º/s, por tanto estabas girando a mano cerca de unos 200º/s.

Hay una interrelación entre ejes del 2% como máximo, es decir, que fácilmente puedes leer en los otros ejes hasta 60 cuando en el eje que sí se mueve lees 3000. Aún así, es difícil de conseguir que gires sólo en un eje si lo haces a mano. Además, la precisión y variación respecto de la temperatura de este sensor, digamos que deja algo que desear...

Por cierto, parece ser que no estaba muy desencaminado.


----------



## Zuri (May 28, 2010)

Muchas gracias por explicármelo!

La teoría es simple...pero en la práctica no se cumple tal y como dice la teoría. Digamos que intento mover 1 grado en 1 segundo, y según la teoría, la salida debería de ser 14-15. La realidad es que a veces devulve 20, otras 40, otras 60...

¿Que puedo hacer?


----------



## Beamspot (May 28, 2010)

La única manera que yo tendría de fiarme, es ponerlo todo montado en un sistema inalámbrico, en un plato giratorio, accionado por un motor, y controlado de tal manera que se supervisa en todo momento la velocidad real de giro.

Aún así, si te miras el apartado de tolerancias, variaciones, linealidades, etc, verás que la lectura es relativamente poco fiable, ya que es posible tener errores de más del 10% (eso en electrónica es una auténtica barbaridad). Por eso, todos los sistemas de instrumentación con los que he trabajado siempre han tenido alguna manera de calibrarse y ajustarse.

En el caso que me comentas, hacer un ajuste que te permita la precisión de 1º/s o mejor es factible, pero el montaje mecánico para realizarlo es complejo, caro, laborioso, y requiere tiempo. Los sistemas de calibración son auténticos proyectos que llegan a ser realmente complejos.

Por cierto, se me acaba de ocurrir que una manera relativamente simple de conseguir esto: es montarlo sobre un motor paso a paso que vaya haciendo giros de manera alternativa: una vuelta a un lado, otra vuelta en sentido contrario. Todo esto, bien controlado, te puede funcionar sin mucho esfuerzo.


----------



## rachid (May 29, 2011)

Buenas tardes, tambien adquiri este sensor, yo lo configuro y obtengo unos valores del sensor, cuando esta el sensor en estado de reposo (que no lo muevo) obtengo un vector de 16 bits, por lo general entre valores por encima de 65440 cuando convierto esos bits a decimal, al mover el sensor obtengo valores menores, por el orden de los 40, o 100, no entiendo por que en estado de reposo me da estos valores tan altos? Alguien sabe cual podria ser el problema? estoy usando un microcontrolador 16F877 y unas resistencias pull-up de 10K entre SDA y SCL del micro y el sensor.


----------



## KIKETSH (Abr 21, 2012)

Buenas a los dos que planteais la misma duda.

Hay que multiplicar el valor leido por el giro por alguna constante que sea lo que vale un sólo LSB!


----------

