Autor Tema: I2C y Giroscopio L3G4200D  (Leído 6135 veces)

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

Desconectado kaki

  • PIC18
  • ****
  • Mensajes: 260
I2C y Giroscopio L3G4200D
« en: 21 de Febrero de 2013, 19:56:13 »
Hola... Llevo varios dias tratando de obtener algun resultado sobre la conxion y uso de dicho giroscopio con un pic mediant I2C.

La verdad no se como arrancar.. eh ejecudo un programa que detecta el hadware si esta bien conectado y me da la direccion. y todo parase estar bien.

La direccion del giro es 0xD2.

Ahora bien a la hora de leer uno de los eje x o configurar su frecuencioa de muestreo todo se complica. no tengo ni idea como hacerlo. eh leido el datasheet y algo entendi pero me gustaria si alguien alguna ves uso este giro que me de una mano a configurarlo.

yo intente esto:

Código: [Seleccionar]
i2c_start();
i2c_read(0xD2);         
result = i2c_read();
printf("I2C read:\n\r",result);
delay_ms(1500);

el resultado de eso es 255

Saludos

Desconectado RALF2

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 2060
Re: I2C y Giroscopio L3G4200D
« Respuesta #1 en: 21 de Febrero de 2013, 20:18:36 »
Hola kaki!
Aqui puedes encontrar un ejemplo en arduino, si estas programando con el ccs debe ser facil migrarlo  :mrgreen:

Saludos

Desconectado kaki

  • PIC18
  • ****
  • Mensajes: 260
Re: I2C y Giroscopio L3G4200D
« Respuesta #2 en: 21 de Febrero de 2013, 20:37:39 »
Alguien que sepa arduino que me tradusca un par de cosas!!

Código: [Seleccionar]
#include <SPI.h>
#include "L3G4200D.h"

// pin definitions
const int int2pin = 6;
const int int1pin = 7;
const int chipSelect = 10;

// gyro readings
int x, y, z;

void setup()
{
  Serial.begin(9600);
 
  // Start the SPI library:
  SPI.begin();
  SPI.setDataMode(SPI_MODE3);
  SPI.setClockDivider(SPI_CLOCK_DIV8);
 
  pinMode(int1pin, INPUT);
  pinMode(int2pin, INPUT);
  pinMode(chipSelect, OUTPUT);
  digitalWrite(chipSelect, HIGH);
  delay(100);
 
  setupL3G4200D(2);  // Configure L3G4200 with selectabe full scale range
  // 0: 250 dps
  // 1: 500 dps
  // 2: 2000 dps
}

void loop()
{
  // Don't read gyro values until the gyro says it's ready
  while(!digitalRead(int2pin))
    ; 
  getGyroValues();  // This will update x, y, and z with new values
 
  Serial.print(x, DEC);
  Serial.print("\t");
  Serial.print(y, DEC);
  Serial.print("\t");
  Serial.print(z, DEC);
  Serial.print("\t");
  Serial.println();
 
  //delay(100); // may want to stick this in for readability
}

int readRegister(byte address)
{
  int toRead;
 
  address |= 0x80;  // This tells the L3G4200D we're reading;
 
  digitalWrite(chipSelect, LOW);
  SPI.transfer(address);
  toRead = SPI.transfer(0x00);
  digitalWrite(chipSelect, HIGH);
 
  return toRead;
}

void writeRegister(byte address, byte data)
{
  address &= 0x7F;  // This to tell the L3G4200D we're writing
 
  digitalWrite(chipSelect, LOW);
  SPI.transfer(address);
  SPI.transfer(data);
  digitalWrite(chipSelect, HIGH);
}

int setupL3G4200D(byte fullScale)
{
  // Let's first check that we're communicating properly
  // The WHO_AM_I register should read 0xD3
  if(readRegister(WHO_AM_I)!=0xD3)
    return -1;
   
  // Enable x, y, z and turn off power down:
  writeRegister(CTRL_REG1, 0b00001111);
 
  // If you'd like to adjust/use the HPF, you can edit the line below to configure CTRL_REG2:
  writeRegister(CTRL_REG2, 0b00000000);
 
  // Configure CTRL_REG3 to generate data ready interrupt on INT2
  // No interrupts used on INT1, if you'd like to configure INT1
  // or INT2 otherwise, consult the datasheet:
  writeRegister(CTRL_REG3, 0b00001000);
 
  // CTRL_REG4 controls the full-scale range, among other things:
  fullScale &= 0x03;
  writeRegister(CTRL_REG4, fullScale<<4);
 
  // CTRL_REG5 controls high-pass filtering of outputs, use it
  // if you'd like:
  writeRegister(CTRL_REG5, 0b00000000);
}

void getGyroValues()
{
  x = (readRegister(0x29)&0xFF)<<8;
  x |= (readRegister(0x28)&0xFF);
 
  y = (readRegister(0x2B)&0xFF)<<8;
  y |= (readRegister(0x2A)&0xFF);
 
  z = (readRegister(0x2D)&0xFF)<<8;
  z |= (readRegister(0x2C)&0xFF);
}

La funcion getGyroValues, setupL3G4200D es C puro no tendria problemas en correr en CCS.

Las demas funciones hay cosas q no se que son como:

Código: [Seleccionar]
SPI.begin();
  SPI.setDataMode(SPI_MODE3);
  SPI.setClockDivider(SPI_CLOCK_DIV8);

Código: [Seleccionar]
Serial.begin(9600);

Desconectado RALF2

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 2060
Re: I2C y Giroscopio L3G4200D
« Respuesta #3 en: 21 de Febrero de 2013, 22:41:03 »
Citar
SPI.begin();
  SPI.setDataMode(SPI_MODE3);
  SPI.setClockDivider(SPI_CLOCK_DIV8);

Sencillo   :shock:

spi.begin invoca o llama a la fucion que configura el spi, spi_setdatamode con ella seleccionas el modo de operacion (modo 3: estado de reposo del reloj es uno, la transmicion de datos ocurre en el flanco de subida del reloj y la lectura en el flanco de bajada).
spi.setclockdivider con ello defines la frecuencia del reloj del SPI.
Serial.begin(9600) con ella configuras la velocidad del rs232 a 9600 bps  ;-)

Te recomiendo que le heches una ojeada a este documento  :mrgreen:

Saludos
« Última modificación: 21 de Febrero de 2013, 22:46:29 por RALF2 »

Desconectado miquel

  • PIC12
  • **
  • Mensajes: 69
Re: I2C y Giroscopio L3G4200D
« Respuesta #4 en: 25 de Febrero de 2013, 19:54:19 »
Hola Kaki!  he utilizado este giroscopio con un 18F2620 y me ha funcionado muy bien. Aqui esta el codigo:
Código: [Seleccionar]


/*******   GIROSCOPI L3G4200   ***********************************************/

#define GIR_ADR              0xD2
#define GIR_WHO              0x0F
#define GIR_REG1             0x20
#define GIR_REG2             0x21
#define GIR_REG3             0x22
#define GIR_REG4             0x23       
#define GIR_REG5             0x24
#define GIR_ESC              0.0175     //250dps > 0.00875  500dps >> 0.0175  2000dps >> 0.07 






void Giro_Inici(int8 Tem);
void Giro_LlegirAngle(void);










struct DataGir
   {
   signed int16 X;
   signed int16 Y;
   signed int16 Z;
   signed int16 X_0;
   signed int16 Y_0;
   signed int16 Z_0;
   float32 Ang_X;
   float32 Ang_Y;
   float32 Escala;
   } DadesGir;










void Giro_Inici(int8 Tem)
{
DadesGir.Escala=Tem;
DadesGir.Escala/=1000;
DadesGir.Escala*=GIR_ESC;
WriteReg (GIR_ADR,GIR_REG1,0x0F);
WriteReg (GIR_ADR,GIR_REG2,0x00);
WriteReg (GIR_ADR,GIR_REG3,0x08);
WriteReg (GIR_ADR,GIR_REG4,0x10);    // 0x00 > 250dps  0x10 > 500dps  0x30 > 2000dps
WriteReg (GIR_ADR,GIR_REG5,0x00);
}

void Giro_Llegir(void)
{
Byte L,H;
H=ReadReg(GIR_ADR,0x29);
L=ReadReg(GIR_ADR,0x28);
DadesGir.X=make16(H,L);
H=ReadReg(GIR_ADR,0x2B);
L=ReadReg(GIR_ADR,0x2A);
DadesGir.Y=make16(H,L);
H=ReadReg(GIR_ADR,0x2D);
L=ReadReg(GIR_ADR,0x2C);
DadesGir.Z=make16(H,L);
}

void Giro_Zero(void)
{
signed int8 J;
signed int32 Xa=0,Ya=0,Za=0;
for (J=0; J<100; J++)
   {
   Giro_Llegir();
   delay_us(500);
   }
for (J=0; J<20; J++)
   {
   Giro_Llegir();
   Xa+=DadesGir.X;
   Ya+=DadesGir.Y;
   Za+=DadesGir.Z;
   delay_ms(1);
   }
DadesGir.X_0=Xa / 20;
DadesGir.Y_0=Ya / 20;
DadesGir.Z_0=Za / 20;
}

void Giro_LlegirAngle(void)
{
Giro_Llegir();
DadesGir.Ang_X=DadesGir.X - DadesGir.X_0;
DadesGir.Ang_Y=DadesGir.Y - DadesGir.Y_0;
DadesGir.Ang_X*=DadesGir.Escala;
DadesGir.Ang_Y*=DadesGir.Escala;
}


void WriteReg(Byte Adr, Byte Reg, Byte Val)
{
i2c_start();
i2c_write(Adr);
i2c_write(Reg);
i2c_write(Val);
i2c_stop();
}

Byte ReadReg(Byte Adr, Byte Reg)
{
Byte R;
i2c_start();
i2c_write(Adr);
i2c_write(Reg);
i2c_start();
i2c_write(Adr + 1);
R=i2c_read(0);
i2c_stop();
return(R);
}

/******************************************************************************/



Solo tienes que iniciar el giro con la funcion:   void Giro_Inici(int8 Tem);      donde Tem es el tiempo de muestreo en milisegundos.
Con la funcion:  void Giro_LlegirAngle(void); tienes los valores de  los angulos X e Y.

Espero que te funcione!!!

Desconectado kaki

  • PIC18
  • ****
  • Mensajes: 260
Re: I2C y Giroscopio L3G4200D
« Respuesta #5 en: 27 de Febrero de 2013, 20:00:50 »
Genial lo voy a probar y luego estudiar tu codigo!! culaquier cosa te pego un chiflido!!

Gracias totales!! Debo decier que anda una maravilla!!                                             Y
                                                                                                                            ^
                                                                                                                            |
Bueno ahora se bienen las preguntas... teninedo el giroscopio de esta manera    x<---O z

estos son los valores que me da por defecto:

Citar
X: 122 - Y: 121 - X: 122 - Y: 121 - X: 122 - Y: 121 - X: 122 - Y: 121 - X: 122 - Y: 121 - X: 122 - Y: 121 - X: 122 - Y: 121 - X: 122 - Y: 121 - X: 122 - Y: 121 - X: 122 - Y: 121 - X: 122 - Y: 121 - X: 122 - Y: 121 - X: 122 - Y: 121 - X: 122 - Y: 121 - X: 122 - Y: 121 - X: 122 - Y: 121 - X: 122 - Y: 121 - X: 122 - Y: 121 - X: 123 - Y: 121 - X: 121 - Y: 123 - X: 123 - Y: 124 - X: 126 - Y: 126 - X: 126 - Y: 123 - X: 126 - Y: 123 - X: 124 - Y: 121 - X: 123 - Y: 121 - X: 124 - Y: 121 - X: 124 - Y: 123 - X: 122 - Y: 121 - X: 123 - Y: 122 - X: 122 - Y: 122 - X: 121 - Y: 120 - X: 126 - Y: 125 - X: 125 - Y: 124 - X: 124 - Y: 125 - X: 118 - Y: 123 - X: 122 - Y: 121 - X: 121 - Y: 121 - X: 125 - Y: 126 - X: 123 - Y: 122 - X: 125 - Y: 125 - X: 122 - Y: 121 - X: 122 - Y: 121 - X: 122 - Y: 121 - X: 122 - Y: 121


para hacer el muestreo uso el siguiente codigo:

Código: [Seleccionar]
Giro_LlegirAngle();
printf("X: %U - ",DadesGir.Ang_X);
printf("Y: %U - ",DadesGir.Ang_Y);

No se si es correcto... y si lo que me muestra ya es el angulo final de X y Y... saludos..
« Última modificación: 27 de Febrero de 2013, 20:57:24 por kaki »

Desconectado miquel

  • PIC12
  • **
  • Mensajes: 69
Re: I2C y Giroscopio L3G4200D
« Respuesta #6 en: 27 de Febrero de 2013, 21:49:01 »
Hola Kaki!  Las variables DadesGir.Ang_X y DadesGir.Ang_Y son del tipo float, tienes que darles el formato %f en la funcion printf()
Tambien tienes que tener en cuenta que la lectura que te dan estas variables es el valor en grados desde el ultimo muestreo. Para tener el valor absoluto del angulo respecto al origen, tiene que ir sumando los valores. Tienes que hacer algo asi:
Código: [Seleccionar]

float32 Gir_X=0.0;
float32 Gir_Y=0.0;
Gir_X+=DadesGir.Ang_X;
Gir_Y+=DadesGir.Ang_Y;


De esta manera tienes el valor absoluto del angulo. Pero hay un problema que se llama "drift", que  es que al cabo de unos segundos el valor en la posicion inicial ya no es cero. Por eso se utiliza junto con un acelerometro para evitar este problema. Prueba a poner un pulsador para resetear las variables Gir_X y Gir_Y, cada vez que las reseteas tienes unos segundos para probar, hasta que el jodi... drift se desmadre!

Saludos
 

Desconectado miquel

  • PIC12
  • **
  • Mensajes: 69
Re: I2C y Giroscopio L3G4200D
« Respuesta #7 en: 27 de Febrero de 2013, 21:53:04 »
Mira esta pagina tiene una informacion muy buena sobre giros y acelerometros: http://www.starlino.com/imu_guide.html

Desconectado kaki

  • PIC18
  • ****
  • Mensajes: 260
Re: I2C y Giroscopio L3G4200D
« Respuesta #8 en: 28 de Febrero de 2013, 10:32:07 »
Gracias Miquel por el link... muy buena explicación... ahora comprendo muchas cosas que antes no entendía...

Desconectado kaki

  • PIC18
  • ****
  • Mensajes: 260
Re: I2C y Giroscopio L3G4200D
« Respuesta #9 en: 25 de Marzo de 2013, 18:04:33 »
Hola miguel despues de un tiempo ocupado volvi a la carga con el IMU... el acelerometro ya lo tengo funcionando pero el giro estoy complicado..

Código: [Seleccionar]
float32 Gir_X=0.0;
float32 Gir_Y=0.0;
Gir_X+=DadesGir.Ang_X;
Gir_Y+=DadesGir.Ang_Y;

Gir_X y Gir_Y que serian el angulo?? teniendo en cuenta como tu dices q eso se da por unos pocos segundos...

otra cosa.. cual es el tiempo utilizado en la funcion Giro_Inici(10); yo puse 10 por poner.

Saludos..

Desconectado miquel

  • PIC12
  • **
  • Mensajes: 69
Re: I2C y Giroscopio L3G4200D
« Respuesta #10 en: 26 de Marzo de 2013, 08:14:17 »
¡ Hola Kaki !

Efectivamente Gir_X y Gir_Y son los angulos. En la funcion Giro_Inici() tienes que poner como parametro el tiempo de muestreo en ms, yo utilizaba 5ms con un pic 18F2620.

Si vas a unir los datos del acelerometro con los del giro ten en cuenta que el "Complementary Filter" o el "Kalman" necesitan los datos del giro en dps.

Saludos

Miquel

Desconectado kaki

  • PIC18
  • ****
  • Mensajes: 260
Re: I2C y Giroscopio L3G4200D
« Respuesta #11 en: 26 de Marzo de 2013, 10:44:48 »
y DadesGir.Ang_X, DadesGir.Ang_Y que me dan esas funciones?? en angulo instante a instante a medida que muevo el giro??

Desconectado kaki

  • PIC18
  • ****
  • Mensajes: 260
Re: I2C y Giroscopio L3G4200D
« Respuesta #12 en: 26 de Marzo de 2013, 15:06:01 »
noto algo que no se si es normal en el giro...

DadesGir.Ang_X = 0
DadesGir.Ang_Y = -0.07

sin moverlo dejandolo quieto no tendrian que ser 0???
« Última modificación: 26 de Marzo de 2013, 15:17:35 por kaki »

Desconectado miquel

  • PIC12
  • **
  • Mensajes: 69
Re: I2C y Giroscopio L3G4200D
« Respuesta #13 en: 28 de Marzo de 2013, 06:28:58 »
¡ Hola Kaki !

Efectivamente en las variables DadesGir.Ang_X, DadesGir.Ang_Y, tienes los grados que ha habido de variacion desde el ultimo muestreo.

La funcion Giro_Zero() sirve para ajustar a cero las lecturas en reposo. debes mantener en absoluto reposo el giro mientras se inicia el pic.
 
Saludos,

Miquel

Desconectado kaki

  • PIC18
  • ****
  • Mensajes: 260
Re: I2C y Giroscopio L3G4200D
« Respuesta #14 en: 03 de Abril de 2013, 15:21:28 »
Bien repacemos.. jeje

Código: [Seleccionar]
void main()
{

Giro_Inici(5);
delay_ms(5);
Giro_Zero();

while(true){
Giro_LlegirAngle();

delay_ms(100);
printf("x:%f",DadesGir.Ang_X);
delay_ms(50);
printf("y:%f",DadesGir.Ang_Y);
delay_ms(50);
}
}

Bien yo mando a la PC la componente en X y Y de lo q rota el Giro sobre el eje.
Hasta aca todo genia.
Ahora cuando yo recivo en la pc los datos y quiero ver el angulo en el que se giro desde el reposo hasta la pocion en la q se encuentra ahora tengo q sumar todos los datos q me envia DadesGir.Ang_X y ,DadesGir.Ang_Y en un sierto tiempo antes de que esos valores sufran el drift.

¿es correcto lo que digo?


 

anything