Autor Tema: LIS331DLH y 16F887 problemas con lecturas [mikroC]  (Leído 3123 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado juliozv

  • PIC10
  • *
  • Mensajes: 37
LIS331DLH y 16F887 problemas con lecturas [mikroC]
« en: 10 de Noviembre de 2012, 16:46:51 »
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:

Código: [Seleccionar]
/*
  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.  :)
« Última modificación: 10 de Noviembre de 2012, 16:49:53 por juliozv »
Firma en Construcción!

Desconectado miquel

  • PIC12
  • **
  • Mensajes: 69
Re: LIS331DLH y 16F887 problemas con lecturas [mikroC]
« Respuesta #1 en: 11 de Noviembre de 2012, 19:46:05 »
¡Hola juliozv !

No conozco el lenguaje mikroC PRO . Pero creo que las variables sx, sy, sz de la función void Accel_Average(void)  deberían ser del tipo long (32bits), quizás sea ese el problema.

Saludos,

Miquel

Desconectado juliozv

  • PIC10
  • *
  • Mensajes: 37
Re: LIS331DLH y 16F887 problemas con lecturas [mikroC]
« Respuesta #2 en: 12 de Noviembre de 2012, 00:37:09 »
¡Hola juliozv !

No conozco el lenguaje mikroC PRO . Pero creo que las variables sx, sy, sz de la función void Accel_Average(void)  deberían ser del tipo long (32bits), quizás sea ese el problema.

Saludos,

Miquel


He analizado tu sugerencia y de momento no se como hacer que la variable int pase ha ser de 16bits, se que CCS posee esa función pero mikroC tendría que investigar como hacer algo parecido, la otra es que me he dado cuenta que tengo un error en el corrimiento de mis datos, la idea de ese corrimiento de 4 bits hacia la derecha era para eliminar los bits menos significativos de la lectura de 16bits, sin embargo esto fue un error de copy/paste de un código anterior que hice para controlar un ADXL345 pero olvide que este es de 13bits por eso el corrimiento de 4, en dado caso este debería de ser de 8, pero entra en duda si es bueno perder precisamente la mitad de los datos, es como pedirle al sensor que solo me entregue en este caso el valor almacenado en el registro alto del eje po ejemplo el  _OUT_X_H.

Alguna forma de poder obtener el mayor dato posible, creo que me he enredado en esto o hay algo que estoy considerando mal.

saludos y de nuevo gracias por la ayuda.
Firma en Construcción!

Desconectado juliozv

  • PIC10
  • *
  • Mensajes: 37
Re: LIS331DLH y 16F887 problemas con lecturas [mikroC]
« Respuesta #3 en: 12 de Noviembre de 2012, 00:45:36 »
Bueno me acabo de dar cuenta que he vivido engañado, resulta que creía que una variable tipo Int era de 8bits y no es de 16bits, pero ahora me surge una duda por que deberia ser de 32bits, o como resuelvo el envío de datos por Serial sin peder bits o por lo menos sin modificar los datos.

 :z)
Firma en Construcción!

Desconectado miquel

  • PIC12
  • **
  • Mensajes: 69
Re: LIS331DLH y 16F887 problemas con lecturas [mikroC]
« Respuesta #4 en: 12 de Noviembre de 2012, 20:24:59 »
¡Hola juliozv !

Creo que en mikroC tienes variables del tipo:

short  >   8bits
int      >   16bits
long   >   32bits

Solo tienes que declarar  las variables sx, sy, sz de la función void Accel_Average(void) como long.
Creo que el desplazamiento a la derecha de 4bits es para dividir por 16 las variables sx,sy y sz, lo que da por resultado la media de 16 lecturas del acelerometro. Supongo que en microC hay una función equivalente a printf ó sprintf de CCS y no tendrás ningún problema para transmitri los datos por la UART.

Saludos,

Miquel