Un saludo,
Recientemente he adquirido un Acelerometro digital de la marca STMicroelectronics modelo
LIS331DLH en la placa de pruebas STEVAL-MK1089 Version 1.0. He tenido problemas al interpretar los datos y estabilizar el sensor

, de momento ya logre la comunicacion I2C y enviarlo por medio de la comunicacion serial. Pero no logro aun resolver lo siguiente:
* El buffer de la comunicacion serial se sobrecarga al grado de que cuando desconecto el dispositivo desde el Serial Monitor aun recivo datos
* No encuentro la forma de estabilizar el sensor aun cuando esta sin moviemineto recibo datos muy variados y hasta negativos.
* Tengo una rutina dentro de la programacion donde los datos al ser de 16 bits y el micro de 8 bits los recorro y promedio para obtener un resultado promedio, sin
embargo no se si estoy en lo correcto.
El codigo es el siguiente:
/*
Pruebas Acelerometro LIS331DLH
Comunicacion I2C
*/
// Renombramiento del puerto
sbit I2C_SCL at RB6_bit;
sbit I2C_SDA at RB7_bit;
// end
// Definiciones
#define LIS331_ADD_W 0x30
#define LIS331_ADD_R 0x31
#define _ACCEL_ERROR 0x10
// LIS331DLH Declaracion de Registros
#define _WHO_I_AM 0x0F
#define _CTRL_REG1 0x20
#define _CTRL_REG2 0x21
#define _CTRL_REG3 0x22
#define _CTRL_REG4 0x23
#define _CTRL_REG5 0x24
#define _HP_FILTER_RESET 0x25
#define _REFERENCE 0x26
#define _STATUS_REG 0x27
#define _OUT_X_L 0x28
#define _OUT_X_H 0x29
#define _OUT_Y_L 0x2A
#define _OUT_Y_H 0x2B
#define _OUT_Z_L 0x2C
#define _OUT_Z_H 0x2D
#define _INT1_CFG 0x30
#define _INT1_SRC 0x31
#define _INT1_THS 0x32
#define _INT1_DURATION 0x33
#define _INT2_CFG 0x34
#define _INT2_SRC 0x35
#define _INT2_THS 0x36
#define _INT2_DURATION 0x37
// fin de Declaraciones
unsigned short temp;
char out[16];
int readings[3] = {0, 0, 0}; // X, Y y Z
short Reg_ADD, buffer;
void LIS331_Write(unsigned short Reg_ADD, unsigned short data1) {
I2C1_Start(); // Señal I2C de Inicio
I2C1_Wr(LIS331_ADD_W); // Escribe la Direccion de Esclavo SAD+R/W = 0x30
I2C1_Wr(Reg_ADD); // Escribe la direccion del Registro
I2C1_Wr(data1); // Escribe el dato en el Registro
I2C1_Stop(); // Paro de la Comunicacion
}
unsigned short LIS331_Read(unsigned short Reg_ADD) {
unsigned short tmp = 0;
I2C1_Start(); // Señal I2C de Inicio
I2C1_Wr(LIS331_ADD_W); // Escribe la Direccion de Esclavo SAD+R/W = 0x30
I2C1_Wr(Reg_ADD); // Escribe la direccion del Registro
I2C1_Repeated_Start(); // Señal I2C repetir señal Inicio
I2C1_Wr(LIS331_ADD_R); // Escribe la Direccion de Esclavo SAD+R/W = 0x31
tmp = I2C1_Rd(0); // Obtiene el Dato (not acknowledge)
I2C1_Stop(); // Paro de la Comunicacion
return tmp;
}
// ---------------------- LIS331DLH Inicio ----------------------
char LIS331_Init(void) {
char id = 0x00;
// Rutina que verifica si realmente me
id = LIS331_Read(_WHO_I_AM); // conectare al Acelerometro.
if (id != 0x32){
return _ACCEL_ERROR;
}
else {
LIS331_Write(_CTRL_REG1, 0x2F); // Configuraciones de los registros a usar
LIS331_Write(_CTRL_REG2, 0x21);
LIS331_Write(_CTRL_REG3, 0x04);
LIS331_Write(_CTRL_REG4, 0x80);
LIS331_Write(_STATUS_REG, 0xF0);
LIS331_Read(_HP_FILTER_RESET);
return 0x00;
}
}
// Lectura Eje X ----------------------------------------
int Accel_ReadX(void) {
char low_byte;
int Out_x;
Out_x = LIS331_Read(_OUT_X_H);
low_byte = LIS331_Read(_OUT_X_L);
Out_x = (Out_x << 8);
Out_x = (Out_x | low_byte);
return Out_x;
}
// Lectura Eje Y ----------------------------------------
int Accel_ReadY(void) {
char low_byte;
int Out_y;
Out_y = LIS331_Read(_OUT_Y_H);
low_byte = LIS331_Read(_OUT_Y_L);
Out_y = (Out_y << 8);
Out_y = (Out_y | low_byte);
return Out_y;
}
// Lectura Eje Z ----------------------------------------
int Accel_ReadZ(void) {
char low_byte;
int Out_z;
Out_z = LIS331_Read(_OUT_Z_H);
low_byte = LIS331_Read(_OUT_Z_L);
Out_z = (Out_z << 8);
Out_z = (Out_z | low_byte);
return Out_z;
}
// Calcular los valores promedio de los ejes leidos X, Y y Z.
void Accel_Average(void) {
int i, sx, sy, sz;
// suma
sx = sy = sz = 0;
// Lecturas promedio del acelerometro de las ultimas 16 muestras
for (i=0; i<16; i++) {
sx += Accel_ReadX();
sy += Accel_ReadY();
sz += Accel_ReadZ();
}
// promedio
readings[0] = sx >> 4;
readings[1] = sy >> 4;
readings[2] = sz >> 4;
}
// Dostrar promedio del Eje-X leer valor en la UART ----------------------
void Display_X_Value(void) {
UART1_Write_Text("X:");
IntToStr(readings[0], out);
UART1_Write_Text(out);
UART1_Write(0x09);
Delay_ms(50);
}
// Dostrar promedio del Eje-Y leer valor en la UART ----------------------
void Display_Y_Value(void) {
UART1_Write_Text("Y:");
IntToStr(readings[1], out);
UART1_Write_Text(out);
UART1_Write(0x09);
Delay_ms(50);
}
// Dostrar promedio del Eje-Z leer valor en la UART ----------------------
void Display_Z_Value(void) {
UART1_Write_Text("Z:");
IntToStr(readings[2], out);
UART1_Write_Text(out);
UART1_Write(0x0D);
UART1_Write(0x0A);
Delay_ms(50);
}
// ------------------------------------------------------------------
void AccelInit(){
// Inicializacion del LIS331 accelerometer
if (LIS331_Init() == 0) {
UART1_Write_Text("Accel module inicializado.\r\n" );
Delay_ms(100);
}
else {
// UART_Write_Text("Error durante la inicializacion del Accel module.", 70, 100);
UART1_Write_Text("Error durante la inicializacion.");
Delay_ms(100);
}
}
// ---------------------- Main() ----------------------
void main() {
ANSEL = 0; // Configure AN pins as digital I/O
ANSELH = 0;
TRISC = 0x10;
C1ON_bit = 0; // Disable comparators
C2ON_bit = 0;
UART1_Init(19200);
Delay_ms(100); // Espera para que el modulo se inicialize
UART1_Write_Text("Prueba Acelerometro...\r\n");
Delay_ms(100);
I2C1_Init(100000);
AccelInit();
Delay_ms(100);
UART1_Write_Text("Leyendo los valores de los ejes...\r\n\r\n");
Delay_ms(100);
while(1) {
Accel_Average(); // Calcular el promedio de las lecturas X, Y y Z
Display_X_Value();
Display_Y_Value();
Display_Z_Value();
}
}Si alguien ha trabajado con este sensor o similar me gustaria que me orientara en su control, el codigo esta en mikroC PRO 5.61, aunque no domino la programacion en CCS si la puedo interprestar o cualquier lenguaje C.
Las Conecciones entre el sensor y el PIC16F887 es por medio de los canales I2C y estoy usando un cristal de 8MHz. Para la comunicacion serial estoy tomando la linea RX del PIC y la envio a un modulo FT232RL para convertirla en USB.
El sensor es de 3v, asi que estoy usando un regulador de Texas Instruments TPS7330P y para la comunicacion I2C un conversor de nivel logico de
Sparkfun.
No tengo un archivo de simulacion o esquematico en algun software, sin embargo si desean alguna imagen o diagrama puedo realizarlo.
Adjuntado va el proyecto completo en mikroC.
Gracias por el tiempo y agradesco su ayuda.
