¿Cómo saber si está dañado el giroscopio L3G4200D?

Hola :)
Bueno, les cuento que tengo un giroscopio L3G4200D, lo estoy comunicando con un ATmega328p vía i2c
Al momento de leer los registros, si los puedo leer pero para escribirlos no puedo.
Sí estoy siguiendo bien la trama i2c que dice la hoja de datos, bueno al menos eso creo.
Según vi en la hoja de datos, es sensible a la estática y no fui muy cuidadoso en ese sentido.
Quisiera saber si no los escribe, por qué está dañado o por qué no funciona.

Ya descargué un par de códigos de arduino para comprobar que funciona pero ninguno me funcionó, y lo que yo programé de lectura de registros si funciona.

Esta función la uso para leer el registro que almacena la dirección del giroscopio y si funciona, solo que debo escribir dos veces la trama i2c, cuando debería ser solo una pero si lo escribo solo una vez, no funciona.

Código:
unsigned char get_gy_address(void)
{   
    unsigned char address_of_gyroscope;   
    
    i2c_start(); 
    i2c_write(L3G4200D_WRITE);
    i2c_write(WHO_AM_I);
    i2c_start();
    i2c_write(L3G4200D_READ);
    address_of_gyroscope = i2c_read(0);
    i2c_stop(); 
    
   //Aqui empieza de nuevo, solo asi funciona deberia ser solo lo de arriba
    i2c_start(); 
    i2c_write(L3G4200D_WRITE);
    i2c_write(WHO_AM_I);
    i2c_start();
    i2c_write(L3G4200D_READ);
    address_of_gyroscope = i2c_read(0);
    i2c_stop();   
                                 
    return address_of_gyroscope;  
}
Esta es para inicializar el giroscopio habilitando los 3 ejes y el modo normal esta es la que no funciona, no escribe los registros :\'(

Código:
void gy_init_cfg(void)
{

    i2c_start();
    i2c_write(L3G4200D_WRITE);
    i2c_write(CTRL_REG1);
    i2c_write(0x0F);
    i2c_stop();
    
    i2c_start();
    i2c_write(L3G4200D_WRITE);
    i2c_write(CTRL_REG1);
    i2c_write(0x0F);
    i2c_stop();
    
}
Uso codevision avr.

De antemano, gracias por su ayuda.
 
Última edición:
Esta función la uso para leer el registro que almacena la dirección del giroscopio y si funciona, solo que debo escribir dos veces la trama i2c, cuando debería ser solo una pero si lo escribo solo una vez, no funciona.
Intenta verificar que el bus i2c está en stop antes de operar con el, quiero decir, agregar un i2c_stop() antes de i2c_start(); a ver si con eso no hace falta hacer lo mismo 2 veces:

Código:
unsigned char get_gy_address(void)
{   
    unsigned char address_of_gyroscope;   
    
    i2c_stop(); 
    i2c_start(); 
    i2c_write(L3G4200D_WRITE);
    i2c_write(WHO_AM_I);
    i2c_start();
    i2c_write(L3G4200D_READ);
    address_of_gyroscope = i2c_read(0);
    i2c_stop();            
    return address_of_gyroscope;  
}
Esta es para inicializar el giroscopio habilitando los 3 ejes y el modo normal esta es la que no funciona, no escribe los registros :\'(

Código:
void gy_init_cfg(void)
{

    i2c_start();
    i2c_write(L3G4200D_WRITE);
    i2c_write(CTRL_REG1);
    i2c_write(0x0F);
    i2c_stop();
    
    i2c_start();
    i2c_write(L3G4200D_WRITE);
    i2c_write(CTRL_REG1);
    i2c_write(0x0F);
    i2c_stop();
    
}

¿Y como determinaste que no funciona?, ¿probaste leer los registros que recien escritos para ver si son los mismos valores?.
Recomendaría hacer funciones separadas para leer/escribir registros, así una vez que eso funciona te olvidas del bus i2c y podes concentrarte en los registros a escribir y leer para operar el giroscopio (no lo probe):

Código:
void gy_writeRegister(uint8_t registerAddress, uint8_t registerValue)
{
     i2c_stop(); //por las dudas, probar si funciona sin esto
    i2c_start();
    i2c_write(L3G4200D_WRITE);
    i2c_write(registerAddress);
    i2c_write(registerValue);
    i2c_stop();    
}
uint8_t gy_readRegister(uint8_t registerAddress)
{
    uint8_t registerValue;

     i2c_stop(); //por las dudas, probar si funciona sin esto
    i2c_start();
    i2c_write(L3G4200D_WRITE);
    i2c_write(registerAddress);
    i2c_start();
    i2c_write(L3G4200D_READ);
    registerValue= i2c_read(0);
    i2c_stop();    
    return registerValue;
}
Luego para verificar si funciona escribir cualquier registro con un valor conocido, y luego leerlo para ver si el registro contiene el valor que queremos:

Código:
gy_writeRegister(CTRL_REG1, 0x0F);
if (0x0F != gy_readRegister(CTRL_REG1) )
{
  //error
}
else
{
  //funciona
}

No estoy seguro de si las funciones i2c_start, i2c_write, i2c_read, i2c_stop hacen lo que creo que hacen. ¿Hay alguna referencia con esa información?
 
Veo en su hoja de datos que ese sensor opera en un rango bajo de voltaje, cuidado con eso. No creo que se haya dañado pues "medio funciona", intenta lo que te comenta Ardogan o bien, mi sugerencia es que intentes establecer la comunicación por el bus SPI en lugar del I2C.
Saludos
 
Hola gracias por sus respuestas

¿Y como determinaste que no funciona?, ¿probaste leer los registros que recien escritos para ver si son los mismos valores?.
Recomendaría hacer funciones separadas para leer/escribir registros, así una vez que eso funciona te olvidas del bus i2c y podes concentrarte en los registros a escribir y leer para operar el giroscopio (no lo probe)

Si eso hice, los escribi y despues los lei y no leia el valor que habia escrito, gracias por el consejo hice una funcion para leer y otra para escribir y mi codigo quedo mejor :LOL:

Veo en su hoja de datos que ese sensor opera en un rango bajo de voltaje, cuidado con eso. No creo que se haya dañado pues "medio funciona", intenta lo que te comenta Ardogan o bien, mi sugerencia es que intentes establecer la comunicación por el bus SPI en lugar del I2C.

Es una de esas tarjetas para arduino, ya lista para 5v y no trae los pines para usar el spi :/ solo sda y scl.


Bien, estos dias me canse de probar y mejor cambie mi codigo de codevision a ccs jeje pero sigue sin funcionar u.u, la diferencia es que ahora con ccs si escribe los registros y no hace falta escribir la trama dos veces en la funcion de lectura o escritura con una sola vez funciona.


Mi único problema ahora es que al leer mas de una vez un registro, solo lo lee correctamente la primera vez, y las siguientes veces solo me retorna 0xFF

Por si no me explique bien si leo los registros antes del "while(true)" si funciona pero si los leo continuamente dentro del "while(true)" solo leo 0xFF

ahh y en la tarjeta tambien viene acelerometro, barometro y magnetometro, no se si se pudiesen "interfeerir"
Mis codigo es


Código:
#include <18F2550.h>
#fuses INTRC,NOMCLR,NOLVP,CPUDIV1,NOWDT
#use delay(clock=8000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)

#use I2C(master, scl=PIN_B1, sda=PIN_B0,FAST=400000)
#include "IMU.h"

void main()
{
      //esto funciona
      int8 GYROSCOPE_ID,ACCELEROMETER_ID,COMPASS_ID;
      write_reg(L3G4200D,CTRL_REG1,0x0F);
      write_reg(ADXL345,POWER_CTL,0x08);
      write_reg(HMC5883,CFG_REG_A ,0x70);
      write_reg(HMC5883,CFG_REG_B,0xA0);
      write_reg(HMC5883,MODE_REG,0x00);
      

       
      GYROSCOPE_ID= read_reg(L3G4200D,WHO_AM_I);
      ACCELEROMETER_ID= read_reg(ADXL345,DEVID);
      COMPASS_ID = read_reg(HMC5883,CFG_REG_B);
      delay_ms(100);

        while(TRUE)
       {
       
      //GYROSCOPE_ID= read_reg(L3G4200D,WHO_AM_I);//aqui solo leo 0xff pero si comento esto y dejo la de arriba si es correcta
         printf("\rGyroscope     id = 0X%02X\n", GYROSCOPE_ID);
         printf("\rAccelerometer id = 0X%02X\n",ACCELEROMETER_ID);
         printf("\rCompass       id = 0X%02x\n\n",COMPASS_ID);
         delay_ms(1000);
         
       }
}
este es IMU.h
Código:
//I2C
#define NACK 0
#define ACK  1

//GIROSCOPIO L3G4200D
#define L3G4200D      0xD2
#define WHO_AM_I      0x0F
#define CTRL_REG1     0x20
#define OUT_X_L       0x28
#define OUT_X_H       0x29
#define FIFO_CTRL_REG 0x2E

//ACELEROMETRO ADXL345
#define ADXL345       0xA6
#define POWER_CTL     0x2D
#define DEVID         0x00
#define DATA_Z0       0x36
#define DATA_Z1       0x37

//BAROMETRO BMP085
#define BMP085        0xEE

//MAGNETOMETRO HMC5883
#define HMC5883       0x3C
#define CFG_REG_A     0x00
#define CFG_REG_B     0x01
#define MODE_REG      0x02
#define DATA_XH       0x03




typedef int1 BOOL;
typedef unsigned int UINT;
typedef unsigned int8 UINT8;
typedef unsigned int16 UINT16;
typedef unsigned int32 UINT32; 



void write_reg(BYTE slave_address,BYTE sub_address,BYTE value)
{
   i2c_start();
   i2c_write(slave_address);
   i2c_write(sub_address);
   i2c_write(value);
   i2c_stop();
}


UINT8 read_reg(BYTE slave_address,BYTE sub_address)
{
   UINT8 value;

    i2c_start();
    i2c_write(slave_address);
    i2c_write(sub_address);
    i2c_start();
    i2c_write(slave_address|0x01);
    value = i2c_read(NACK);
    i2c_stop();
    
    return value;
}

UINT16 read_reg16(signed int8 slave_address,signed int8 sub_address)
{
   UINT8 value_h,value_l;
   
    i2c_start(); 
    i2c_write(slave_address);
    i2c_write(sub_address);
    i2c_start();
    i2c_write(slave_address|0x01);
    value_h = i2c_read(ACK);
    value_l = i2c_read(NACK);
    i2c_stop(); 
    
    return MAKE16(value_h,value_l);
}

mmmm ahora veo que no puse scl como salida habia pensado eso antes :LOL: pero sda deberia ser salida o entrada ? ahh y tambien lei que para i2c los pines deben estar en open drain pero no se como hacer eso :LOL:
 
Última edición:
Ambos pines SDL. y SDA deben de ser configurados como salidas con sus respectivos bits en TRISX a 0's. Después de esto, al configurar los registros del puerto serie internamente se desactivan los buffers de salida de esos pines para hacerlos de colector abierto
 
Ya agregue la siguiente linea

set_tris_b(0b11111100);

Pero sigo leyendo 0xFF :/

Ya no se que mas hacer :LOL:



Ya agregue la siguiente linea

set_tris_b(0b11111100);

Pero sigo leyendo 0xFF :/

Ya no se que mas hacer :LOL:
 
Última edición:
Bien, bajare la velocidad a 100Khz,aunque ya la habia bajado antes y no funciono :p pero una vez mas jaja, ahora lo tengo funcionando sin pullups le habia puesto de 10Kohm pero igual no funcionaba, ademas ya las tiene incluidas en la tarjeta las pullups

Este es el schematic

GY-80_Schematic.jpg
 
No pero si esta vien sdo, es para la direccion estandoa 1 o 0 y permite el uso de dos giroscopios

bien creo que no lo lograre ha cer funcionar igual gracias por la ayuda
 
Atrás
Arriba