lunes, 17 de junio de 2013

Control de un acelerómetro LIS3LV02DL con arduino







STMicroelectronics, uno de los mayores fabricantes de Sistemas Micro-Electro-Mecánicos (MEMS), este tipo de sensores tienen una capacidad de  procesamiento que  permiten reducir el consumo de energía a nivel sistema ideal para sistemas portátiles.

Acelerómetro LIS3LV02DL
Es un sistema micro electro- mecánico capacitivo, tiene como principio primordial censar las fuerzas G en un solo encapsulado, su configuración interna contiene dos estructuras mecánicas semiconductoras una fija y la otra movible, al hacer un movimiento genera un cambio capacitivo proporcional a la fuerza.
Tiene 3 salidas digitales x y z enviando información lineal correspondiente a la aceleración, puede medir de 2 a 6G configurado por software.
Aplicaciones:
üDetectar caída libre
ürobótica
üActivación por movimiento
üInclinómetro
üJuegos
üMonitoreo de compensación y vibración
Caracteristicas
voltaje de alimentación 2,16 V a 3,6 V
Interfaces de salida digital I2C/SPI
Tiempos de representación de datos 12 o 16 bits
Interrumpir activado por movimiento
Umbral programable de interrupciones de Autocomprobación
Soporta Alto choque
Puede generar interrupciones de 2 tipos: Free Fall(caída libre) o Direction Detection Change(cambio de dirección)
El acelerómetro tiene una resolución de 12 bits(4096 posibles valores) y comprende 2 rangos de medición ±2gy ±6g.
En caso de utilizar el primer rango ±2g, la precisión de la lectura sería de 4096/4g = 1024 LSb/g
En el caso de usar el rango mayor de los ±6g la precisión del sistema sería de 4096/12g 
340LSb/gPor defecto el acelerómetro se actualiza 40 veces por segundo (40Hz), pero se puede
configurar para aumentar esta tasa a 160,
640o incluso2560veces por segundo (2560Hz). En este último caso estaríamos obteniendo un valor
cada 0,39ms.
Este acelerómetro dispone de un auto-test para la integridad de las medidas tomadas, pudiendo
descartar las medidas en los
momentos en que no son válidas. Su rango de temperatura de funcionamiento está comprendido entre
los -40ºC y los +85ºC.

Modo de conexión
Se lo conecta usando I2c (Inter-Integrated Circuit (Inter-Circuitos Integrados) o llamado  TWI y TWSI usando tres líneas digitales (tierra, reloj y datos) logrando conectar hasta 128 sensores. Los datos del sensor son de 8 bits, Es una comunicación de tipo half duplex. Comunicación bidireccional por la misma línea pero no simultáneamente

También se puede usar Protocolo  SPI( Serial Peripherical Interface), es un bus de 4 líneas, Cada
dispositivo conectado al bus puede actuar como transmisor y receptor al mismo tiempo, por lo que este
tipo de comunicación serial es full duplex. Dos de estas líneas trasfieren los datos (una en cada
dirección) y la tercer línea es la del reloj
Pines de acelerómetro

Conexión  SPI
CS es el puerto de habilitación serie i2c y en modo SPI es un pin de control como maestro , donde se pasa a nivel bajo en el inicio de la transmisión y se remonta
 a uno al final de la misma.
Conexión  I2C
Para modo  I2C el CS =1SPI el CS  =0
Diagrama de bloques usado en arduino


Programa creado para el incliometro en arduino

/* ////////////////////////////////////////////////////////////////////////
//programa para comunicar un acelerometro LIS3LV02DL por I2C con arduino
SDA (línea de datos) es la suminittrada por el arduino o en algunos casos
entrada analógica es el pin 4  y se conecta al pin 3 sensor  
SCL (línea de reloj) es la suminittrada por el arduino o en algunos casos
es la entrada analógica del pin 5 al pin 5 sensor 
verifique bien el montaje antes de usar este archivo, ya que solo hay un montaje funcional
ing edison viveros para www.Microelectronicos.com 2013
*///////////////////////////////////////////////////////////////////////////
#include <Wire.h>//libreria de comunicacion i2c
//se definen los registros de lectura de las coordenadas
#define i2cID 0x1D          //direccion de I2C//definicion de variables de nivel alto
#define REG_OUTX_H 0x29     //valor alto de coordenada x
#define REG_OUTY_H 0x2B     //valor alto de coordenada y
#define REG_OUTZ_H 0x2D     //valor alto de coordenada z
//definicion de variables de nivel bajo
#define REG_OUTX_L 0x28    
//valor bajo de coordenada x
#define REG_OUTY_L 0x2A
#define REG_OUTZ_L 0x2C
////////////DEFINE EL REGISTRO QUE CONTROLA G 
#define REG_CTRL_REG2  0x21

////////////////////////////////////////////////////////////////////////////////7
/* estos son todos los registros que se usan con el acelerometro para quien
// los dese usar en otra aplicacion
#define REG_WHO_AM_I  0x0f; //3A
#define REG_OFFSET_X  0x16;
#define REG_OFFSET_Y  0x17;
#define REG_OFFSET_Z  0x18;
#define REG_GAIN_X  0x19;
#define REG_GAIN_Y  0x1A;
#define REG_GAIN_Z  0x1B;
#define REG_CTRL_REG1  0x20;
#define REG_CTRL_REG2  0x21;
#define REG_CTRL_REG3  0x22;
#define REG_HP_FILTER_RESET  0x23;
#define REG_STATUS_REG  0x27;
#define REG_OUTX_L  0x28;
#define REG_OUTX_H  0x29;
#define REG_OUTY_L  0x2a;
#define REG_OUTY_H  0x2b;
#define REG_OUTZ_L  0x2c;
#define REG_OUTZ_H  0x2d;
#define REG_FF_WU_CFG  0x30;
#define REG_FF_WU_SRC  0x31;
#define REG_FF_WU_ACK  0x32;
#define REG_FF_WU_THS_L  0x34;
#define REG_FF_WU_THS_H  0x35;
#define REG_FF_WU_DURATION  0x36;
#define REG_DD_CFG  0x38;
#define REG_DD_SRC  0x39;
#define REG_DD_ACK  0x3a;
#define REG_DD_THSI_L  0x3c;
#define REG_DD_THSI_H  0x3d;
#define REG_DD_THSE_L  0x3e;
#define REG_DD_THSE_H  0x3f;
 
*/
//const int CTRL_REG2_FS = 7;//se redefine la posicion de memoria para FS el cual estipula fs =0 entonces es 2g, si FS =1 es 6g

byte z_val_l, z_val_h, y_val_l, y_val_h, x_val_l, x_val_h;
byte escala;
int led_x_alto = 7;
int led_x_bajo = 6;
int led_y_alto = 5;
int led_y_bajo = 4;
int led_z_alto = 3;
int led_z_bajo = 2;
//----------variable que sacara los datos-----------------------
  int x_inclinacion;
  int y_inclinacion;
  int z_inclinacion;
//------------------------------- 
void setup()

{ 
 pinMode(led_x_alto,OUTPUT);
 pinMode(led_x_bajo,OUTPUT);
 pinMode(led_y_alto,OUTPUT);
 pinMode(led_y_bajo,OUTPUT);
 pinMode(led_z_alto,OUTPUT);
 pinMode(led_z_bajo,OUTPUT);
 
}
void loop()
{
  configuracion();
  valores_x();
  valores_y();
  valores_z();
  imprimir_inclinacion_x_y_z();
  activar_led();
}
  
  //////////////////////////7
  void configuracion()
{
          //Wire.beginTransmission(address)Comienza una transmisión a un dispositivo I2C esclavo con la dirección dada (address).
         // Posteriormente, prepara los bytes a transmitir con la función send() y los transmite llamando a la función endTransmission().
        
          Wire.begin(); // Inicie la librería Wire y unirse a la I2C 
                        //bus como maestro o esclavo. Normalmente, esto debería ser llamado una sola vez.
          Serial.begin(9600);//configura la velocidad
          
          Serial.println("Wire.begin");//Serial.println(val, format)
                                     //val: el valor a imprimir - de cualquier tipo
                                     //format: especifica el número de la base (para números enteros) 
                                     //o el número de posiciones decimales 
                                     //(para números de coma flotante o tipo "float")
        
        //////el acelerómetro establece el ID del dispositivo para comunicacion I2C
          Wire.beginTransmission(0x1D);//direccion del acelerometro que se asignara
          Wire.write(0x20); //Envía al dispositivo el siguiente mensaje para configurar el modo regular o testing CTRL_REG1 (20h)
                            //Escribe los datos de un dispositivo esclavo en respuesta a una petición de un maestro
        Wire.write(0x87);   // Encienda el dispositivo, que todos los ejes, no se auto-test, REG_CTRL_REG1, 0x87
        Wire.endTransmission(); // todo ok
        //CARGA ESCALA
          Wire.beginTransmission(i2cID);//Comience una transmisión al I2C dispositivo 
                                       //esclavo con la dirección indicada. Posteriormente,
                                      // los bytes de cola se transmiten con la funcion write()
          Wire.write(REG_CTRL_REG2);
          Wire.endTransmission();  //fin de transmision 
           
        Wire.requestFrom(i2cID, 1);//Wire.requestFrom(address, quantity)
                            //Solicita bytes de otro dispositivo. Los bytes pueden ser recibidos 
                            //con las funciones available() y read().
                   //Parámetros: address: la dirección de 7 bits del dispositivo al que pedir los bytes
                   //quantity: el número de bytes a pedir
         while(Wire.available())
         {
           escala= Wire.read();
         }

}

  ////////////////////////////////////////////////////////////////////
void valores_x()
{
////los valores obtenidos del acelerometro son tan bajos que se tomara dos señales
// la baja y alta y al final se las suma
  Wire.beginTransmission(i2cID);//Comience una transmisión al I2C dispositivo 
                               //esclavo con la dirección indicada. Posteriormente,
                              // los bytes de cola se transmiten con la funcion write()
  Wire.write(REG_OUTX_L);
  Wire.endTransmission();  //fin de transmision 
   
Wire.requestFrom(i2cID, 1);//Wire.requestFrom(address, quantity)
                    //Solicita bytes de otro dispositivo. Los bytes pueden ser recibidos 
                    //con las funciones available() y read().
           //Parámetros: address: la dirección de 7 bits del dispositivo al que pedir los bytes
           //quantity: el número de bytes a pedir
 while(Wire.available())
 {
   x_val_l = Wire.read();
 }
 //-------------------------------  
  Wire.beginTransmission(i2cID);//Comience una transmisión al I2C dispositivo 
                               //esclavo con la dirección indicada. Posteriormente,
                              // los bytes de cola para la transmisión con la funcion write()
  Wire.write(REG_OUTX_H); //Escribe los datos de un dispositivo esclavo 
                          //en respuesta a una petición de un maestro se envia un solo byte
  Wire.endTransmission();   //se transmite y finaliza
    
Wire.requestFrom(i2cID, 1);
if(Wire.available())//puede enviar lo solicitado
 {
   x_val_h = Wire.read();//Lee un byte que se transmite de un dispositivo
                          // esclavo de un maestro después de llamar a requestFrom ()
                         // o se transmite de maestro a un esclavo. read ()
 }
//-------------------------------  
 x_inclinacion = x_val_h;//almaceno el valor alto en x_val
 x_inclinacion  <<= 8;//se desplaza a la izquierda 8 bit
 x_inclinacion  += x_val_l;//se suma el valor alto(x_val_h)con el valor bajo (x_val_l)

//------------------------------- 
}
////////////valores y
void valores_y()
{
  Wire.beginTransmission(i2cID);//Comience una transmisión al I2C dispositivo 
                               //esclavo con la dirección indicada. Posteriormente,
                              // los bytes de cola para la transmisión con la funcion write()
  Wire.write(REG_OUTY_L);
  Wire.endTransmission();
   
Wire.requestFrom(i2cID, 1);
 while(Wire.available())
 {
   y_val_l = Wire.read();
 }
}
 //-------------------------------valores z
void valores_z()
{
  Wire.beginTransmission(i2cID);
  Wire.write(REG_OUTY_H); //nivel alto de Y
  Wire.endTransmission();
    
  Wire.requestFrom(i2cID, 1);
  if(Wire.available())
 {
   y_val_h = Wire.read();
 }
//-------------------------------  
 
 
 y_inclinacion  = y_val_h;
 y_inclinacion  <<= 8;
 y_inclinacion  += y_val_l;
 

//------------------------------- 
  Wire.beginTransmission(i2cID);
  Wire.write(REG_OUTZ_L);
  Wire.endTransmission();
   
Wire.requestFrom(i2cID, 1);
 while(Wire.available())
 {
   z_val_l = Wire.read();
 }
 //-------------------------------  
  Wire.beginTransmission(i2cID);
  Wire.write(REG_OUTZ_H);
  Wire.endTransmission();
    
Wire.requestFrom(i2cID, 1);
if(Wire.available())
 {
   z_val_h = Wire.read();
 }
//-------------------------------  
 z_inclinacion  = z_val_h;
 z_inclinacion  <<= 8;//se corre 8 bit
 z_inclinacion  += z_val_l;
}
 /////////////////////////
 //imprimir valores
 void imprimir_inclinacion_x_y_z()
 {
///despues de tenre todos los valores se imprimen en pantalla los valores obtenidos
Serial.print("Escala= "); Serial.println(escala, DEC);
Serial.print("X_inclinacion = "); Serial.println(x_inclinacion , DEC);
Serial.print("Y_inclinacion = "); Serial.println(y_inclinacion , DEC);
Serial.print("Z_inclinacion = "); Serial.println(z_inclinacion , DEC);

delay(200);//se hace un tiempo de 300ms y se repite el ciclo
 }
 /////////////activar led
 void activar_led()
 {
if(x_inclinacion <=100)
{
  digitalWrite(led_x_alto,LOW);
  digitalWrite(led_x_bajo,LOW);
  digitalWrite(led_y_alto,LOW);
  digitalWrite(led_y_bajo,LOW);
}

if(x_inclinacion >=100)
{
  digitalWrite(led_x_alto,LOW);
  digitalWrite(led_x_bajo,HIGH);
  digitalWrite(led_y_alto,LOW);
  digitalWrite(led_y_bajo,HIGH);
}
if(x_inclinacion <=-100)
{
  
   digitalWrite(led_x_alto,HIGH);
  digitalWrite(led_x_bajo,LOW);
  digitalWrite(led_y_alto,HIGH);
  digitalWrite(led_y_bajo,LOW);
}
/////INCLINACION Y CONTROL EJE Y
if(y_inclinacion >=100)
{
  digitalWrite(led_x_alto,HIGH);
  digitalWrite(led_x_bajo,LOW);
  digitalWrite(led_y_alto,LOW);
  digitalWrite(led_y_bajo,HIGH);
}
if(y_inclinacion <=-100)
{
 
  digitalWrite(led_x_alto,LOW);
  digitalWrite(led_x_bajo,HIGH);
  digitalWrite(led_y_alto,HIGH);
  digitalWrite(led_y_bajo,LOW);
}
}

El acelerometro lo puede conseguir en microelectronicos.com
agradezco la publicación de este tutorial en la web de opiron españa

No hay comentarios: