PDA

View Full Version : 3-Axis Accelerometer (LIS302DL)



Gusse
- 15th January 2009, 22:27
Hi,

I have been playing with ST's LIS302DL 3-axis accelerometer, which is quite nice IC. It uses I2C bus and device has 2 independed programmable interrupts. I'm using it only for motion detection (alarm) at the moment, but there are huge possibilities with the device :) (mainly due to my limited coding skills, but learning all the time)

Here is piece of my code with comments. I hope somebody find it usefull.

'-------------------------------------------------------------------------------
' 3D Accelerometer
'-------------------------------------------------------------------------------
Accelerometer_Init:
'Command SAD[6:1] SAD[0] = SDO R/W SAD+R/W
I2CDevice_3D_read=$39 'Read 001110 0 1 00111001 (39h)
I2CDevice_3D_write=$38 'Write 001110 0 0 00111000 (38h)

'Axes
I2CAddress_3D = $20 'CTRL_REG1
TEMP = %01000111 '47h -> DR=0, PD=1, FS=0, STP=00, Zen=1, Yen=1, Xen=1 (X,Y,Z enable, Output 100Hz)
gosub I2C_Write_3D '41h = X
'---------------------

'Filters
I2CAddress_3D = $21 'CTRL_REG2
TEMP = %00000111 '00h -> SIM = 0, BOOT = 0, --, FDS = 0, HP FF_WU2 = 0, HP FF_WU1 = 1, HP coeff2 = 1, HP coeff1 = 1 (HP 0.25Hz for FF_WU1)
gosub I2C_Write_3D

'---------------------

'Interrupts
I2CAddress_3D = $22 'CTRL_REG3
TEMP = %00000001 '01h -> IHL = 0, PP_OD = 0, I2CFG2-0 = 000, I1CFG2-0 = 001 (FF_WU 1 = INT1)
gosub I2C_Write_3D

'---------------------

'Sensitivity
I2CAddress_3D = $32 'FF_WU_THS_1
TEMP = $02 ' 0Ah -> DCRM = 0, THS6 = 0, THS5 = 0, THS4 = 0, THS3 = 0, THS2 = 0, THS1 = 1, THS0 = 0 (~36mg wake-up threshold, ~18mg step)
gosub I2C_Write_3D

'---------------------

'Duration
I2CAddress_3D = $33 'FF_DURATION_1
TEMP = $0D '05h -> D7 = 0, D6 = 0, D5 = 0, D4 = 0, D3 = 1, D2 = 1, D1 = 0, D0 = 1 (130ms, 0 - 2.55s, 10ms step)
gosub I2C_Write_3D '0Ah = 100ms, 0Fh = 150ms, 14h = 200ms, 28h = 400ms, 32h = 500ms,

'---------------------

'Wake-Up Thresholds
I2CAddress_3D = $30 'FF_WU_GFG_1
TEMP = %01101010 '6Ah -> AOI = 0, LIR = 1, ZHIE = 1, ZLIE = 0, YHIE = 1, YLIE = 0, XHIE = 1, XLIE = 0 (wake-up above thresholde on x,y,z)
gosub I2C_Write_3D

'---------------------

'I2CAddress_3D = $36 'FF_WU_THS_2
'TEMP = $14 '14h -> DCRM = 0, THS6 = 0, THS5 = 0, THS4 = 1, THS3 = 0, THS2 = 1, THS1 = 0, THS0 = 0 (~350mg wake-up threshold, ~18mg step)
'gosub I2C_Write_3D

''---------------------
'I2CAddress_3D = $37 'FF_DURATION_2
'TEMP = $0A '0Ah -> D7 = 0, D6 = 0, D5 = 0, D4 = 0, D3 = 1, D2 = 0, D1 = 1, D0 = 0 (100ms, 0 - 2.55sec, 10msec step)
'gosub I2C_Write_3D

''---------------------

'I2CAddress_3D = $34 'FF_WU_GFG_2
'TEMP = $78 '78h -> AOI = 0, LIR = 1, ZHIE = 1, ZLIE = 1, YHIE = 1, YLIE = 0, XHIE = 0, XLIE = 0 (wake-up above thresholde on x,y,z)
'gosub I2C_Write_3D

'---------------------
I2CAddress_3D = $23 'Reset acceration/tilt value. Needed if HP enable in CTRL_REG2
gosub I2C_Read_3D
Return

'-------------------------------------------------------------------------------
I2C_Write_3D:
I2CWRITE SDA_3D, SCL_3D, I2CDevice_3D_write, I2CAddress_3D,[ TEMP ]
Return

I2C_Read_3D:
I2cread SDA_3D, SCL_3D, I2CDevice_3D_read, I2CAddress_3D,[ TEMP ]
Return

'-------------------------------------------------------------------------------
Accelerometer:
IF Int1_3D = 1 THEN ' Int1_3D is IO pin for Interrup coming from 3D sensor
I2CAddress_3D = $31 ' Clear interrupt request
gosub I2C_Read_3D
I2CAddress_3D = $23 ' Reset acceration/tilt value after interrupt
gosub I2C_Read_3D
PIR_Alarm = 1 ' This is indecator that something must be done in main program
endif

'IF Int2_3D = 1 THEN ' For 2nd interrupt pin
' I2CAddress_3D = $35
' gosub I2C_Read_3D
' I2CAddress_3D = $23
' gosub I2C_Read_3D
' PIR_Alarm = 1
'endif
return

Accelerometer_Clear: ' If sensor has moved during event hadling, then interrupt must be cleared once before new sequence
I2CAddress_3D = $31
gosub I2C_Read_3D
Return
'-------------------------------------------------------------------------------

More info and datasheets can be found here: http://www.st.com/stonline/products/literature/ds/12726/lis302dl.htm

BR,
-Gusse-

Glenn
- 17th January 2009, 15:33
I also played around with an ST accelerometer, but I took the safe route and choosed LIS 244AL instead, with analouge outputs.

Very easy to use when connected to ADC pins.

..But it sure was HELL to solder on that TINY little capsule..

Humans isn't supposed to solder this stuff :(

http://www.repulsiv.se/pics/lga16under.jpg

(The lead in the pencil is 0.5mm)

I destroyed the first one, but got the second one to work, after I bought some 0.2mm wire.

Gusse
- 17th January 2009, 17:10
One reason to use LIS302DL was mechanical dimensions: 0.8mm pitch and 0.5mm pad sizes and of cource this component was easily available.

For me digital output version is much easier and more safe. Programmable HP filter and threshold trigger (for interrupt) works very well in my application.
When accelerometer is enable (alarm mode), then most of the time PIC is sleeping and when it wake up, then INT-pin is polled.

I was supprised how easy it was to use :)

Next step is to write SW, which will use actual acceleration data capture by LIS302DL. Lets see how easy/difficult that will be...

Gusse
- 18th January 2009, 15:40
Here is code, which captures X and Y axis acceleration data and calculate average (over 5 samples) resultant acceleration and also maximum detected acceleration (that is also averaged).

Acceleratio var word
Acceleratio_max var word
X_Data var Byte
Y_Data var Byte
COUNTER VAR BYTE
TEMP VAR BYTE

'-------------------------------------------------------------------------------
Accelerometer_Init:
Acceleratio = 0
Acceleratio_max = 0
COUNTER = 0

'Axes
I2CAddress_3D = $20 'CTRL_REG1
TEMP = %01000011 'DR=0, PD=1, FS=0, STP=00, Zen=0, Yen=1, Xen=1 (X,Y enable, Output 100Hz)
gosub I2C_Write_3D '

'Interrupts
I2CAddress_3D = $22 'CTRL_REG3
TEMP = %00000100 'IHL = 0, PP_OD = 0, I2CFG2-0 = 000, I1CFG2-0 = 100 (DataReady = INT1)
gosub I2C_Write_3D

Return

'-------------------------------------------------------------------------------
I2C_Write_3D:
I2CWRITE SDA_3D, SCL_3D, I2CDevice_3D_write, I2CAddress_3D,[ TEMP ]
Return

I2C_Read_3D:
I2cread SDA_3D, SCL_3D, I2CDevice_3D_read, I2CAddress_3D,[ TEMP ]
Return

'-------------------------------------------------------------------------------
Acceleration_Menu: 'Start from here
gosub Accelerometer_Init
IF Int1_3D = 1 THEN 'Int1_3D is IO pin for Interrup coming from 3D sensor, DataReady in device
COUNTER = COUNTER + 1
'---------------------------
I2CAddress_3D = $29 'Read OUTX value
gosub I2C_Read_3D
if TEMP > 127 then 'Two's complementary changed to amplitude information
X_Data = 255 - TEMP 'Acceleration data presented in two's complement
else
X_Data = TEMP
ENDIF
'---------------------------
I2CAddress_3D = $2B 'Read OUTY value
gosub I2C_Read_3D
if TEMP > 127 then 'Two's complementary changed to amplitude information
Y_Data = 255 - TEMP 'Acceleration data presented in two's complement
else
Y_Data = TEMP
ENDIF
'---------------------------
Acceleratio = Acceleratio + (18 * SQR((X_Data * X_Data) + (Y_Data * Y_Data))) 'Average factor 5x
'--------------------------- 'Calculate resultant force
IF COUNTER = 5 then
COUNTER = 0
Acceleratio = Acceleratio/5
IF Acceleratio > Acceleratio_max then
Acceleratio_max = Acceleratio
endif
'ADD YOUR CODE HERE TO SHOW ACCELERATIO AND ACCELERATIO_MAX ON YOUR DISPLAY
Acceleratio = 0
endif
'---------------------------
Gosub Accelerometer_Clear
endif
goto Acceleration_Menu
'-------------------------------------------------------------------------------
Accelerometer_Clear: 'Clear interrupt
I2CAddress_3D = $31
gosub I2C_Read_3D
Return

BR,
-Gusse-

Glenn
- 19th January 2009, 01:43
Looks really good, if I knowed this before I started myself I probably would have ordered a I2C version instead :)

..But I might borrow some of your code anyway :)

I was thinking of using a timer and calculate speed from it, but I dont know how accurate it would be.

Gusse
- 19th January 2009, 11:57
I noticed couple of misstakes in the code.

One in the two's complement calculation formula. Previously posted formula gave result as: 255 = 0, 254 = (-)1, etc ... Correct formula should give 255 = (-)1, 254 = (-)2, etc ...
Error was minor, but here is updated code (only change is 255 -> 256).

Other in Acceleration_Menu -loop. Accelerometer_Init required only once you start.


Acceleratio var word
Acceleratio_max var word
X_Data var Byte
Y_Data var Byte
COUNTER VAR BYTE
TEMP VAR BYTE

'-------------------------------------------------------------------------------
Accelerometer_Init:
Acceleratio = 0
Acceleratio_max = 0
COUNTER = 0

'Axes
I2CAddress_3D = $20 'CTRL_REG1
TEMP = %01000011 'DR=0, PD=1, FS=0, STP=00, Zen=0, Yen=1, Xen=1 (X,Y enable, Output 100Hz)
gosub I2C_Write_3D '

'Interrupts
I2CAddress_3D = $22 'CTRL_REG3
TEMP = %00000100 'IHL = 0, PP_OD = 0, I2CFG2-0 = 000, I1CFG2-0 = 100 (DataReady = INT1)
gosub I2C_Write_3D

Return

'-------------------------------------------------------------------------------
I2C_Write_3D:
I2CWRITE SDA_3D, SCL_3D, I2CDevice_3D_write, I2CAddress_3D,[ TEMP ]
Return

I2C_Read_3D:
I2cread SDA_3D, SCL_3D, I2CDevice_3D_read, I2CAddress_3D,[ TEMP ]
Return

'-------------------------------------------------------------------------------
Acceleration_Menu:
gosub Accelerometer_Init 'Start from here

Acceleration_Loop:
IF Int1_3D = 1 THEN 'Int1_3D is IO pin for Interrup coming from 3D sensor, DataReady in device
COUNTER = COUNTER + 1
'---------------------------
I2CAddress_3D = $29 'Read OUTX value
gosub I2C_Read_3D
if TEMP > 127 then 'Two's complementary changed to amplitude information
X_Data = 256 - TEMP 'Acceleration data presented in two's complement
else
X_Data = TEMP
ENDIF
'---------------------------
I2CAddress_3D = $2B 'Read OUTY value
gosub I2C_Read_3D
if TEMP > 127 then 'Two's complementary changed to amplitude information
Y_Data = 256 - TEMP 'Acceleration data presented in two's complement
else
Y_Data = TEMP
ENDIF
'---------------------------
Acceleratio = Acceleratio + (18 * SQR((X_Data * X_Data) + (Y_Data * Y_Data))) 'Average factor 5x
'--------------------------- 'Calculate resultant force
IF COUNTER = 5 then
COUNTER = 0
Acceleratio = Acceleratio/5
IF Acceleratio > Acceleratio_max then
Acceleratio_max = Acceleratio
endif
'ADD YOUR CODE HERE TO SHOW ACCELERATIO AND ACCELERATIO_MAX ON YOUR DISPLAY
Acceleratio = 0
endif
'---------------------------
Gosub Accelerometer_Clear
endif
goto Acceleration_Loop
'-------------------------------------------------------------------------------
Accelerometer_Clear: 'Clear interrupt
I2CAddress_3D = $31
gosub I2C_Read_3D
Return


Looks really good, if I knowed this before I started myself I probably would have ordered a I2C version instead :)

..But I might borrow some of your code anyway :)

I was thinking of using a timer and calculate speed from it, but I dont know how accurate it would be.

Thanks! Feel free to borrow, therefore I posted it here :)
I would guess that digi output device would give overall better accuracy, but I might be wrong.

BR,
-Gusse-

Gusse
- 20th January 2009, 04:34
It seems to work quite nicely.
http://kotiweb.kotiportti.fi/karl-erik.gustafsson/PIC/1.jpg http://kotiweb.kotiportti.fi/karl-erik.gustafsson/PIC/2.jpg http://kotiweb.kotiportti.fi/karl-erik.gustafsson/PIC/3.jpg

1) Start value ~0.07 - 0.10G. X-axis = 0 deg, Y-axis = 0 deg.
2) Y-axis tilted 90 deg. Should show 1G in this position. OK.
3) X-axis tilted ~45 deg.
BR,
-Gusse-

Glenn
- 21st January 2009, 01:50
Nice!

And a LCD that looks identical as the one that I have cannibalized out of a nokia phone and going to solder wires on to use with my PIC's :)

Do you want to post the updated code too ?

..This is how far I got..

http://www.repulsiv.se/pics/accelerometer-breadboard.jpg

Your setup is much more elegant :)

..Note that I already connected a cable for an Z-axis, I bought a prototypeboard with a 3-axis accelerometer from sure electronics that I'm going to use too.

The "normal" value seem to be 120, and using 8bit AD-converter that would be.. lets se..

5v Vref /256 = 0,01953125
120 * 0,01953125 = 2,34375

With a Vref at 5v 1G should be 2.5V, so its a bit strange..

I have to make some effort at making PBP do that math and display the "real" G-value too.. readed Melanies thread about it but.. well :)

Gusse
- 21st January 2009, 17:10
Display is from Nokia 3310 and it is easy to play with. Yeah! :)

I could try to make a code with all neccesary LCD srcipts too. At the moment this accelerometer is just one part of a bigger system and a part of a bigger code bunch. It will take some time, but I'll come back with the code, no problem. Anyway, origin of the display driver is from this forum, therefore I would like to thank those who have done the pioneer work! Thanks!

As said earlier, my primary use case was motion detection (alarm). For that purpose LIS302DL works fine, but then I started to look more advanced solutions; acceleration, speed, range, etc. Nice features, but one problem is causing grey hairs to my.

If device is at fully horisontal level (Z-axis is pointing to center of the earth), then everything is OK. But if it is rotated/tilted X, Y, Z or any combinations (pitch, roll, yaw), then readings are not any more right. Spec also says so.

There are quite lot of discussions about how to get rid of this limitation, but no really simply solution. This is one good post, which describes more accurately the problem http://www.electronicspoint.com/accelerometer-tilt-compensation-t119225.html

BR,
-Gusse-

EDIT: Here is also code for LIS302DL with Nokia 3310 LCD. This one shows captured acceleration values on screen: 1st X, 2nd Y, 3rd Z. No bargraphics included because grachics are located in external EEPROM. LCD is connected to PortB, accelerometer to PortC & D (partial), see file for more details. Change pins to fit you application (I'm using 16F877A).

Gusse
- 22nd January 2009, 09:39
Here is an updated demo code for LIS302DL with Nokia 3310 LCD. This shows all three axis with bar graphics and numbers.
http://kotiweb.kotiportti.fi/karl-erik.gustafsson/PIC/4.jpg
Also small video clip, which shows how the system works (I'm rotation PIC and LIS302DL in my hand) http://kotiweb.kotiportti.fi/karl-erik.gustafsson/PIC/LIS302DL.wmv.

My test bench for accelerometer (add-on board) http://kotiweb.kotiportti.fi/karl-erik.gustafsson/PIC/PIC_and_LIS302DL.gif.

And here is the code.

BR,
-Gusse-

EDIT: If your screen is too light or too dark then tune "Contrast" value. I have noticed that there are differences between new and old 3310 LCD displays (tested both).

alexpanrui
- 3rd February 2009, 14:54
my lis302dl is not working properly.....no matter which register i tried to read, the data is always 0xFF....shouldnt be right according to the datasheet....even the Who_AM_I register gave me 0xFF...BTW the sensor was working few days a ago. is it detected?help.....

alexpanrui
- 3rd February 2009, 15:10
I am using PIC16f877 to interface with LIS302DL. I browsed through some threads available over the net. They said we need to add pullups at the data lines and SCL. why? I dont include any pullups. i just directly connect the sensor to the PIC. anything wrong?

alexpanrui
- 3rd February 2009, 15:24
SPI is used for my case

Gusse
- 4th February 2009, 10:51
Can you share your schematic and code?

I'm not so familiar with SPI interface, but could you change LIS302DL to I2C mode (pin7, CS tight to VCC and pin12 GND) and try to read registers then? Then pull-ups are needed (4k7 for both CLK and SDA).

-Gusse-

alexpanrui
- 4th February 2009, 14:48
sry, i forgot to mention that the sensor was working before. I read the datasheet again. i noticed that the absolute max rating for Vin (input voltage for all control pins) is from -0.3v to VDD_IO+0.3 v. I hooked up VDD-IO to 3v. so based on the max rating, the input voltage should be no more than 3.3v. But the output high voltage from PIC is ard 4.5v. Could this be the reason that the sensor stops working?

Gusse
- 4th February 2009, 16:19
It might be that device get damaged if Vdd_IO is too much higher than Vdd (spec says Vdd + 0.1V). On the otherhand, I have used 5V (4.95V) for both Vdd and Vdd_IO without any problems or damages, PIC is also running on 5V. Absolute maximum voltage for LIS302DL is +6V (both Vdd and Vdd_IO).

Can you measure how much current accelerometer is taking from supply?

-Gusse-

rodrik
- 14th November 2012, 14:06
[14-11, 15:02] rodrik: Hello Gusse, I find your post and liked it. I want to use the LIS302DL for car use. Is importance how the direction of placing ? can I just drop or have to locate in certain angle ? Regarding the codes. I want to have the data on serial port. Is data flows continuously or only above the predefined values the data flows out? Thank you in advance

Haim Rodrik

Gusse
- 15th November 2012, 20:29
Hi Rodik,

What is your planned application in car?

If you are planning to monitor movements (i.e alarm use), then placing is not a problem. You can reset acceleration/tilt values for interrupt at any angle.
If you are keen to know real acceleration values in all axis, then IC need to be at level, X&Y=0, Z=90. Bit more demanding, but ... Constant tilting will give static values.

Values need to be read from IC via I2C, so if constant reading is needed then you have to do reading loop for that purpose. Data can be put to serial port as well as to LCD, so that is no problem. You have to adjust output part of the code.

BR,
-Gusse-

rodrik
- 26th January 2013, 21:39
Hi Gusse,

Thank you very much for your reply.
I am sorry for delay. We moved to new house, I got internet just few days ago. I need to detect lifting big garbadge container. I can put the IC verticaly in manner that Z can detect forward movement X lift up detection. Y its useless. The G values not important jus detect lift up and if moves forward (towing) and stop. I can read the values via serial (SEROUT) pin.
As I understand , I have configure a value if its exeedes , INT lines falls to "0" logic. I look at ZIP file as I see the "Power_3D VAR PortD.5 'Power_3D" its must be connected to LIS302DL's VCC. What about pin#1 ? (VDD_IO)
Thanks again
Have a great weekend

Haim

Gusse
- 27th January 2013, 22:56
Hi Haim,

It is OK to put IC vertically and reset acceration/tilt values (HP_FILTER_RESET (23h)).
You have to configure certain parameters if you want to use interrupt. Here are couple of examples from working piece of codes:

Code to init accelerometer:

Accelerometer_Init:

'Axes
I2CAddress_3D = $20 'CTRL_REG1
TEMP = %01000111 'DR=0, PD=1, FS=0, STP=00, Zen=1, Yen=1, Xen=1 (X,Y,Z enable, Output 100Hz)
gosub I2C_Write_3D
'---------------------

'Filters
I2CAddress_3D = $21 'CTRL_REG2
TEMP = %00000111 'SIM = 0, BOOT = 0, --, FDS = 0, HP FF_WU2 = 0, HP FF_WU1 = 1, HP coeff2 = 1, HP coeff1 = 1 (HP 0.25Hz for FF_WU1)
gosub I2C_Write_3D

'---------------------

'Interrupts
I2CAddress_3D = $22 'CTRL_REG3
TEMP = %00000001 'IHL = 0, PP_OD = 0, I2CFG2-0 = 000, I1CFG2-0 = 001 (FF_WU 1 = INT1)
gosub I2C_Write_3D

'---------------------

'Sensitivity
I2CAddress_3D = $32 'FF_WU_THS_1
TEMP = $02 'DCRM = 0, THS6 = 0, THS5 = 0, THS4 = 0, THS3 = 0, THS2 = 0, THS1 = 1, THS0 = 0 (~36mg wake-up threshold, ~18mg step)
gosub I2C_Write_3D

'---------------------

'Duration
I2CAddress_3D = $33 'FF_DURATION_1
TEMP = $0D 'D7 = 0, D6 = 0, D5 = 0, D4 = 0, D3 = 1, D2 = 1, D1 = 0, D0 = 1 (130ms, 0 - 2.55s, 10ms step)
gosub I2C_Write_3D '0Ah = 100ms, 0Fh = 150ms, 14h = 200ms, 28h = 400ms, 32h = 500ms,

'---------------------

'Wake-Up Thresholds
I2CAddress_3D = $30 'FF_WU_GFG_1
TEMP = %01101010 'AOI = 0, LIR = 1, ZHIE = 1, ZLIE = 0, YHIE = 1, YLIE = 0, XHIE = 1, XLIE = 0 (wake-up above thresholde on x,y,z)
gosub I2C_Write_3D

'---------------------


Code how to deal when INT will occur:

Accelerometer:
IF Int1_3D = 1 THEN ' Int1_3D is IO pin for Interrup coming from 3D sensor
gosub Accelerometer_Clear
Accel_Alarm = 1 ' This is indecator that something must be done in main program
endif
return

Accelerometer_Clear: ' If sensor has moved during event hadling, then interrupt must be cleared once before new sequence
I2CAddress_3D = $31 ' Clear interrupt request
gosub I2C_Read_3D
I2CAddress_3D = $23 ' Reset acceration/tilt value after interrupt
gosub I2C_Read_3D
Return

Vdd_IO = Vdd = 5V. Even spec says 3.6V, I have used 5V already several years for same parts. Same voltage is used also for I2C pull-ups & CS (pins 1, 3, 6, 7).

rodrik
- 28th January 2013, 05:20
Thank you very much , I will try and let you know the results. If you need assistance for GSM and GPS, I am very very experienced
thanks again
haim