TODOPIC
Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: kaki 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:
i2c_start();
i2c_read(0xD2);
result = i2c_read();
printf("I2C read:\n\r",result);
delay_ms(1500);
el resultado de eso es 255
Saludos
-
Hola kaki!
Aqui (https://www.sparkfun.com/products/10612) puedes encontrar un ejemplo en arduino, si estas programando con el ccs debe ser facil migrarlo :mrgreen:
Saludos
-
Alguien que sepa arduino que me tradusca un par de cosas!!
#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:
SPI.begin();
SPI.setDataMode(SPI_MODE3);
SPI.setClockDivider(SPI_CLOCK_DIV8);
Serial.begin(9600);
-
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 (http://www.google.co.ve/url?sa=t&rct=j&q=spi+en+ccs+oviedo&source=web&cd=1&ved=0CCwQFjAA&url=http%3A%2F%2Fwww2.ate.uniovi.es%2Ffernando%2FDoc2007%2FPresentaciones%2FSerie_sincrona_en_C.pdf&ei=ZcwmUbLhBIbS9QTG-IH4Bg&usg=AFQjCNGKjEBJ4oadsV7mgboSPqhbOi2lRA&bvm=bv.42768644,d.eWU&cad=rja) documento :mrgreen:
Saludos
-
Hola Kaki! he utilizado este giroscopio con un 18F2620 y me ha funcionado muy bien. Aqui esta el codigo:
/******* 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!!!
-
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:
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:
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..
-
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:
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
-
Mira esta pagina tiene una informacion muy buena sobre giros y acelerometros: http://www.starlino.com/imu_guide.html
-
Gracias Miquel por el link... muy buena explicación... ahora comprendo muchas cosas que antes no entendía...
-
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..
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..
-
¡ 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
-
y DadesGir.Ang_X, DadesGir.Ang_Y que me dan esas funciones?? en angulo instante a instante a medida que muevo el giro??
-
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???
-
¡ 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
-
Bien repacemos.. jeje
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?
-
Hola Kaki!
Con este codigo no te funcionara ya que tienes que leer el giro a intervalos exactos, en tu caso son 5ms de acuerdo al parametro de la funcion Giro_Inici(). En el bucle de la funcion main tienes retardos por mas de 200ms!!!
Tienes que utilizar un timer programado a 5ms y en la interrupcion hacer la lectura del giro.
Saludos
-
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:
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:
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..
Buenos dias, soy de argentina y estoy intentando programar el giroscopo l3g4200D, queria consultar si que alguien puede, respecto de la programacion de dicfho giroscopo, me encuentro con un inconveniente al quere realizar la comunicacion por i2c ya que habiendo leido las hojas de datos correspondientes no logro entender bien el funcionamiento del mismo, mi duda es la siguiente para poder leer los registros de salida o sea los datos de salida del giro, como tengo que realizar la lectura de los registros, es decir si alguien podria indicarme alguna rutina en c o como deberia realizarla, ya que hace varios dias que estoy luchando con dicho dispositivo y no logro dar con la solucion.
saludos cordiales, y espero que alguien pueda darme una mano
-
pasaste por aquí?
http://www.todopic.com.ar/foros/index.php?topic=41979.0
sds