Friday, October 1, 2010

Accelerometer LIS3LV02DL controlled by a dsPIC, I2C communication

This post describe the basic data acquisition of an accelerometer LIS3LV02DL over I2C bus using a dsPIC30F3012.
This tri-axial accelerometer has a 12 or 16 bit digital output and can be interfaced using SPI or I2C communication.
The circuit employed is a very simple one, The dsPIC is connected to the accelerometer LIS3LV02 via I2C using the B7 and B6 pines. The dsPIC reads the data and send the results in ascii format to the PC using the bluetooth module KC21.

Sampling rate of the sensor: 640Hz
Program sampling rate: 100Hz
Communication: I2C and Bluetooth


image
The program was made using the CCS compiler.
/////////////////////////////////////////////////////////////////////////////
// 01/OCT/2010, Chiba, Japan.
//Coder: Rigo
//Compiler: CCS
//Description: Program to read data from an accelerometer sensor using the I2C bus
//
//////////////////////////////////////////////////////
#include  "30f3012.h"                                //DEVICE
#FUSES HS2_PLL8//The xtal freq is divided by 2 and multiplied by 8 (maximum using 20MHz xtal)
#FUSES NOWDT // NO Watch Dog Timer
#FUSES PR_PLL //Primary Oscillator
#FUSES NOCKSFSM //Clock Switching is disabled, fail Safe clock monitor is disabled
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOWRT //Program memory not write protected
#use delay(clock=80000000)// 20MHz/2*8=80MHz=80000000
#use rs232(baud=115200, xmit=PIN_B6, rcv=PIN_B7)            //To transmite result over Bluetooth
#use i2c(MASTER,SDA=PIN_C14,SCL=PIN_C13, fast=400)            // i2c define(For ACC)
//********************************
#define LED    PIN_D0
//LIS3LV02DL_register_define-----------------------
#define WRITE        0x3A   
#define READ         0x3B   
#define REG1         0x20
#define REG2         0x21
#define OUTX_L       0x28
#define OUTX_H       0x29
#define OUTY_L       0x2A
#define OUTY_H       0x2B
#define OUTZ_L       0x2C
#define OUTZ_H       0x2D
//=========================================================
int read_acc(int address_out);                //reading
long acc_change(int data_H,int data_L);       //change
float32 convert_into_g(int16 data);           //Converts into gravity values
//=========================================================
/*********** main **************/
////////////////////////////////////
void main()
{   
setup_adc_ports(NO_ANALOGS);                   //all digital I/O
int16 x_acc,  y_acc,  z_acc;                   //x,y,z-data_16bit
//Enabling the accelerometer 
i2c_start();                            //Sends a start command to the device
i2c_write(WRITE);                       //Sends a single byte preparing the device to receive data
i2c_write(REG1);                        //Indicate the device's addres to be modified   
i2c_write(0xE7);                        //11100111 = C7-->Turn on device activating all the axis, 640Hz sampling rate
i2c_stop();                             //Stop  I2C transmission
i2c_start();               //Start I2C communication
i2c_write(WRITE);          //Sends command to write data
i2c_write(REG2);           //Address the control register 2
i2c_write(0x40);           //01000001 --> 2g, no update between readings,12bits right justified
i2c_stop();                //Close trasmmision
/********* MAIN PROGRAM*************/
while(1)
{
output_high(LED);           
x_acc = read_acc(OUTX_L);    //Read data for the x axis
y_acc = read_acc(OUTY_L);    //Read data for the y axis
z_acc = read_acc(OUTZ_L);    //Read data for the z axis
//********************************
float X_out;             //Define floating variables for results in G units
float Y_out;
float Z_out;
X_out=convert_into_g(x_acc);            //Converts binary value into g
Y_out=convert_into_g(y_acc);
Z_out=convert_into_g(z_acc);
printf("  X  %g ", X_out); //display    //send results over RS232
printf("  Y  %g ", Y_out); //display
printf("  Z  %g \n \r", Z_out); //display
delay_ms(10);                           //delay for sampling 100Hz
output_low(LED);   
}
}   
//**************************************************************************************************
int16 read_acc(int address_out)
{
int DL=0x00, DH=0x00;    
int16 out = 0;
i2c_start();                //Start communication
i2c_write(WRITE);           //prepare the device to receive data
i2c_write(address_out|0x80);  //address register, autoincrement of address
i2c_start();                //
i2c_write(READ);            //Prepares the device to be read
DL=i2c_read();              //Read data LSB
DH=i2c_read(0);             //Read data MSB
i2c_stop();                //Stop  condition
//concatenating result    
out=DL|((DH&0x0F)<<8);     //Join the LSB and the MSB 
return(out);              //Returns the result
}
//**************************************************************************************************
float32 convert_into_g(int16 data)
{
float output;
output=(float)data;       //Converts integer data into float
if (data>=2048)         //check if the result is indicating a negative value
{
output=(output/1024)-4;  //Converts into g
}
if (data<2048)          //if the result indicates a positive value
{
output=output/1024;   //converts into g
}
return(output);               //Returns the result
}
//*****************************************************************
Output displayed in the computer using a simple and free serial terminal.
image My very very ugly implementation using breadboard
image

24 comments:

Unknown said...

hello

can you contact me?

i have some questions about this

nice greets kevin

Rigo said...

@Kevin:
Hello Kevin.
Sure, I can contact you but, give me some e-mail or something to do it. :-)

Regards

Rigo

Unknown said...

Hello Rigo

here my email:

seekingcenter@gmail.com

greets kevin

Unknown said...

hello .. I can make it with a pic 18f4550?

Unknown said...

is incomplete this proyect??.. you don't send the data through Uart .. please help me

Rigo said...

Hi Rosemberth.
You can´t use the PIC18F4550 using this program as it is. If you want to use that uC you must change the program for that specific uC.

I send the data through UART to a Bluetooth module and the Bluetooth module send the data to the PC.
If you have the same components as in the circuit or compatibles, then you can use the firmware without changes.
Also, you can send the data using a DB9 connector directly with youc computer instead the bluetooth module but, for that you must use a RS232 circuit to increase the 3.3 volts from the dspic to the voltage leves of the PC.

Unknown said...

I sent you a greeting from Colombia
thank you for responding, Rigo ... I'm using an RN42 Bluetooth and an accelerometer LIS3LV02DL but I want to read the acceleration of the axes and also I want to detect changes inthe direction X axis and Y axis to then send the data to a PC THROUGH bluetooth ... all this with the aim of controlling a car in a simple video game designed in visual basic. I am using MikroC but I failed to properly do the readings ... I will appreciate if I collaborate please.

my code is as follows:

https://www.dropbox.com/sh/acqdru5qnj63rvk/Bsox_QxBtG

Unknown said...

Rigo ... hablas español??

Rigo said...

Rosemberth:
Que tal.
Sí, hablo español. Soy de México. :-)

La verdad no estoy muy familiarizado con el mikroC.
Sugerencias:
1.- Comprueba que no haya errores en tu circuito.
2.- Prueba primero el módulo de bluetooth y asegurate que esté enviando datos correctamente a tu aplicación.
3.- El programa que me enviaste sí compila? Porque en la función LIS3LV02DL_Write declaras la variable unsigned short REG_DIR y usas Reg_DIR. así, con minúsculas "eg". Quizás eso te está dando problemas.
No tengo mikroC así que no lo puedo revisar a fondo, además de que ando algo presionado en tiempo.

Te recomiendo que vayas probando tu código parte por parte. Sólo así me han funcionado las cosas.

Suerte en tu proyecto.

Rigo

Unknown said...

que bueno que seas de Mexico ... :) . si Rigo el programa complla pues mikroC no distingue mayusculas y minusculas ... intente enviar un "hola mundo" por el bluetooth RN42 pero me di cuenta que esta enviando unicamente simbolos de interrogacion que los visualice en hyperterminal ... estuve leyendo un poco en internet y creo que esta relacionado con el reloj pero aun no encuentro el fallo . Tambien que puede ser cuestion de configurar el bluetooth a 9600 baudios . de casualidad tu sabes como hacerlo con comandos AT ?

Rigo said...

Hola. Perdón por la tardanza en contestar.
Ah! Sí, muy probable que sea por el reloj.Sí el módulo de Bluetooth no está por default a 9600 bps y no sabes como configurarlo, entonces cambia la velocidad en el programa a la que sea el default del módulo. Lo de los comandos AT generalmente viene en el manual de tu dispositivo de bluetooth. Lo hice hace tiempo pero la verdad no recuerdo.
Saludos

Unknown said...

problema solucionado!!

Rigo said...

¡Qué bueno!
¿Qué fue la solución?

editronikx said...

Rigo he mirado el codigo del PIC pero en la parte practica no he podido hacer funcionar este vendito acelerometro con un 18f2550, sera que me puede colaborar.
lo he intentado en arduino y tampoco me funciona.
editronikx@gmail.com

Unknown said...

el problema radicaba en la configuracion del baud rate del modulo bluetooth, pero mediante comandos AT fue sencillo arreglar este problema. mi juego ya esta funcionando.

Unknown said...

muchas gracias

Rigo said...

@Edison: Que tal. Disculpa que no haya contestado antes. El punto clave es entender cómo funciona y que comandos requiere el acelerómetro.
Trata de hacer un diagrama de flujo de todos los pasos necesarios para configurarlo y para recibir y enviarle datos. Una vez que tengas ese diagrama de flujo, entonces impleméntalo en el arduino (que es más fácil) o en el 2550.
Quisera poder ayudarte más pero en verdad ando muy corto de tiempo. ¡Suerte!

@Rosemberth:
Que bueno que encontraste la solución. espero que disfrutes tu creación.(Y publica tus resultados para que ayudes a más personas)
Saludos y suerte.

editronikx said...

rigo ayudame ami tambien, estoy barado con ese acelerometro, no lo puedo hacer funcionar e intentado con arduino leonardo y pic 16f877 pero no recibo nada, deme una mano mi correo es editronikx@gmail.com mi idea es hacer un tutorial para aprender a controlar este acelerometro para que otros no tengan el mismo problema que yo

editronikx said...

Ssludos.

rigo solo hasme un favor dime que cambio para usar un 18f2550, es que quiero descartar el acelerometro ya que con arduino no me funciona nada y ya tengo el codigo, pero ahora deseo ensayar con pic. saca un poquito de tu tiempo asi como todos loa hacemos cuando tenemos blog y nos toca responder a tanta gante que desea aprender

gracias

editronikx said...

Rigo ya me funciono el proyecto, me base un poco en su código y lo hice con arduino, funciona ok

Unknown said...

Hola que tal me gustaria saber si has programado el sensor LSM303 yo estoy usando el pic 16f876 y uso CCS nadamas que al momento de enviar los datos al serial en la posiscion x me manda 124 y no cambia y las otrasa dos posiciones me mandan ceros agradeceria mucho tu apoyo de antemano gracias como me podria poner encontacto contigo este es mi correo: mecatr_onics@hotmail.com

Unknown said...

la idea del tutorial me parece muy bueno ... muchas veces nos detenemos en cosas que son muy simples pero la falta de experiencia nos juega una mala pasada

Rigo said...

@Edidon: Que buena noticia que finalmente funcionó. Una discupla por no ayudar pero, la verdad ando con varios pendientes y aún no salgo de todos. Suerte con el proyecto.

@Miguel: Que tal Miguel. No, era uno de mis plane, de hecho compré el sensor pero no me ha dado tiempo de hacer nada. :-( Lo que dices suena como a un problema en el "rate" de comunicación o en la configuración del sensor.
Por desgracia no puedo ayudarte mucho puesto que no he trabajado con ese sensor.
@Rosemberth: Sin duda. Y así, poco a poco se va compartiendo el conocimiento. :-)

editronikx said...

les dejo el tutorial y el codigo de arduino para aquellos que deseen complementar acerca del acelerometro

http://editronikx.blogspot.com/2013/06/control-de-un-acelerometro-lis3lv02dl.html

http://www.youtube.com/watch?v=1dTLrEdVjx4

Related Posts Plugin for WordPress, Blogger...