3-Axis Accelerometer (LIS302DL)
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.
Code:
'-------------------------------------------------------------------------------
' 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/...6/lis302dl.htm
BR,
-Gusse-
Couple of corrections to code
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.
Code:
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
Quote:
Originally Posted by
Glenn
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-
1 Attachment(s)
More you know, more painfull it is....
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/acce...n-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).
1 Attachment(s)
LIS302DL demo with bar graphics. Var so god!
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-er...sson/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-er...C/LIS302DL.wmv.
My test bench for accelerometer (add-on board) http://kotiweb.kotiportti.fi/karl-er...d_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).
Re: 3-Axis Accelerometer (LIS302DL)
[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
Re: 3-Axis Accelerometer (LIS302DL)
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-
Re: 3-Axis Accelerometer (LIS302DL)
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
Re: 3-Axis Accelerometer (LIS302DL)
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:
Code:
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:
Code:
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).
Re: 3-Axis Accelerometer (LIS302DL)
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