Leyendo el registro who_am_IBueno, en este punto necesitaremos la hoja de datos para ver un poco las características de nuestro giro y su configuracion.
En mi caso uso el L3G4200D de ST.
Lo primero que hay que analizar es la tabla 4 (mecánical characteristics)

Como primer parámetro tenemos el Rango del gyro, podemos elegir entre +-250, +-500 y +-2000. A mayor rango, vamos a poder medir velocidades angulares mayores y además será menos sensible a velocidades más pequeñas. En mi caso elegiré 2000dps.
Una vez elegido el rango, la sensivilidad queda determinada. En mi caso 0.07 dps por cada bit en el dato de salida.
Luego tenemos el ODR, podemos elegir 100, 200, 400 u 800Hz. O sea, 1 muestra cada 10mseg hasta 1 muestra cada 1,25mseg. Aquí hay algo para investigar que aún no he hecho. Tengo entendido que a mayor ODR mas "ruidosa" será la señal de salida. En principio elegiría 100 o 200Hz.
El resto de los parámetros los podemos ver un poco más adelante.
Bien, en la Tabla18 tenemos un listado de todos los registros del gyro, los cuales debemos/podemos leer/escribir para hacerlo funcionar.
El primer registro que podemos utilizar para testeo es el Who_am_I en la direccion 0x0F cuyo valor por defecto es 211 decimal.
Luego tenemos 5 registros de control, los cuales debemos configurar para obtener la respuesta deseada del gyro
Luego tenemos los 6 registros con los datos crudos de cada eje.
Bueno, veamos un pequeño ejemplo para leer el registro Who_am_I y verificar el funcionamiento de la comunicacion:
Lamentablemente para muchos, mi placa de desarrollo es la LPCXpresso, por lo que el código que propongo es para ella. Es C, por lo que se podrá modificar facilmente a cualquier otro uC.
Bueno, este es mi archivo L3G4200D.h
#ifndef L3G4200D_H_
#define L3G4200D_H_
#include "i2c.h"
extern volatile uint8_t I2CMasterBuffer[I2C_PORT_NUM][BUFSIZE];
extern volatile uint8_t I2CSlaveBuffer[I2C_PORT_NUM][BUFSIZE];
extern volatile uint32_t I2CReadLength[I2C_PORT_NUM];
extern volatile uint32_t I2CWriteLength[I2C_PORT_NUM];
#define L3G4200D_READ_ADDR 0xD3
#define L3G4200D_WRITE_ADDR 0xD2
#define L3G4200D_DATA_ADDR 0x28
#define L3G4200D_WHO_AM_I 0x0F
#define L3G4200D_CTRL_REG1 0x20
#define L3G4200D_CTRL_REG2 0x21
#define L3G4200D_CTRL_REG3 0x22
#define L3G4200D_CTRL_REG4 0x23
#define L3G4200D_CTRL_REG5 0x24
#define L3G4200D_REFERENCE 0x25
#define L3G4200D_OUT_TEMP 0x26
#define L3G4200D_STATUS_REG 0x27
#define L3G4200D_OUT_X_L 0x28
#define L3G4200D_OUT_X_H 0x29
#define L3G4200D_OUT_Y_L 0x2A
#define L3G4200D_OUT_Y_H 0x2B
#define L3G4200D_OUT_Z_L 0x2C
#define L3G4200D_OUT_Z_H 0x2D
#define L3G4200D_FIFO_CTRL_REG 0x2E
#define L3G4200D_FIFO_SRC_REG 0x2F
#define L3G4200D_INT1_CFG 0x30
#define L3G4200D_INT1_SRC 0x31
#define L3G4200D_INT1_THS_XH 0x32
#define L3G4200D_INT1_THS_XL 0x33
#define L3G4200D_INT1_THS_YH 0x34
#define L3G4200D_INT1_THS_YL 0x35
#define L3G4200D_INT1_THS_ZH 0x36
#define L3G4200D_INT1_THS_ZL 0x37
#define L3G4200D_INT1_DURATION 0x38
#define PORT_USED 1
void L3G4200D_init();
unsigned char L3G4200D_read(unsigned char reg);
unsigned char L3G4200D_write(unsigned char reg_address, unsigned char value);
void L3G4200D_init(){
L3G4200D_write(L3G4200D_CTRL_REG1, 0b00001111); // 100Hz, 12.5 CO, all axis enable
L3G4200D_write(L3G4200D_CTRL_REG4, 0x20); // 0x00 250 dps, 0x10 500 dps, 0x20 2000dps
}
unsigned char L3G4200D_read(unsigned char reg){
I2CWriteLength[PORT_USED] = 2;
I2CReadLength[PORT_USED] = 1;
I2CMasterBuffer[PORT_USED][0] = L3G4200D_WRITE_ADDR;
I2CMasterBuffer[PORT_USED][1] = reg;
I2CMasterBuffer[PORT_USED][2] = L3G4200D_READ_ADDR;
I2CEngine( PORT_USED );
return(I2CSlaveBuffer[PORT_USED][0]);
}
unsigned char L3G4200D_write(unsigned char reg_address, unsigned char value){
I2CWriteLength[PORT_USED] = 3;
I2CReadLength[PORT_USED] = 0;
I2CMasterBuffer[PORT_USED][0] = L3G4200D_WRITE_ADDR;
I2CMasterBuffer[PORT_USED][1] = reg_address;
I2CMasterBuffer[PORT_USED][2] = value;
return(I2CEngine( PORT_USED ));
}
#endif /* L3G4200D_H_ */
Sé que en los .h van las definiciones y tendria que tener un L3G4200D.c, pero todavia me falta aprender algunas cosas sobre programar con varios .c, en especial con el alcance de las variables, etc.
Bueno, como ven al principio estan todos los define con las direcciones de cada registro. Luego tengo las funciones típicas necesarias para usar el gyro en esta aplicacion.
Mi main.c es este:
#ifdef __USE_CMSIS
#include "LPC17xx.h"
#endif
#include <cr_section_macros.h>
#include <NXP/crp.h>
#include "uart2.h"
#include <stdio.h>
#include "i2c.h"
#include "L3G4200D.h"
/*******************************************************************************
** Main Function main()
*******************************************************************************/
int main (void){
unsigned char who_am_I;
I2C1Init(); /* initialize I2c1 */
L3G4200D_init();
UART2_Init(56700); // Inicializo el UART a 56700
UART2_PrintString ("\r\nGiroscopo L3G4200D\r\n");
UART2_PrintString ("======== elgarbe ==========\r\n");
who_am_I=L3G4200D_read(L3G4200D_WHO_AM_I);
UART2_PrintString("\r\nEl registro who am I contiene: ");
uart2_printUint32(who_am_I, 10);
while ( 1 ){
}
}
Simplemente se inicializa el I2C, luego se inicializa el gyro. Para ello solo hace falta escribir 2 registros. el REG1 configuramos 100Hz de ODR, 12.5 Hz de BW, habilitamos los tres ejes y ponemos el modo de energia en Normal. En el REG4 elegimos 2000dps
Finalmente inicializamos la UART, escribimos un mensaje para luego leer el registro who_am_I y mostrar su valor.
El terminal obtengo la siguiente salida
