Wiki

This version is outdated by a newer approved version.DiffThis version (31 Jan 2012 10:37) is a draft.
Approvals: 0/1

This is an old revision of the document!


ADXL345 Input 3-Axis Digital Accelerometer Linux Driver

Supported Devices

Reference Circuits

Evaluation Boards

Description

The ADXL345 is a small, thin, ultra low power, 3-axis accelerometer with high resolution (13-bit) measurement up to ±16 g. Digital output data is formatted as 16-bit twos complement and is accessible through either a SPI (3- or 4- wire) or I2C digital interface.

The ADXL345 is well suited for mobile device applications. It measures the static acceleration of gravity in tilt-sensing applications, as well as dynamic acceleration resulting from motion or shock. Its high resolution (4mg/LSB) enables resolution of inclination changes of as little as 0.25°.

Several special sensing functions are provided. Activity and inactivity sensing detect the presence or lack of motion and if the acceleration on any axis exceeds a user-set level. Tap sensing detects single and double taps. Free-Fall sensing detects if the device is falling. These functions can be mapped to interrupt output pins. An integrated 32 level FIFO can be used to store data to minimize host processor intervention.

Low power modes enable intelligent motion-based power management with threshold sensing and active acceleration measurement at extremely low power dissipation.

ADXL345 - Small, Ultra Low Power, 3-Axis, ±2/4/8/16g Digital Accelerometer
ADXL346 - Ultra Low Power, Three-Axis, +-2/4/8/16g Digital Accelerometer

ADXL34x Hardware Features

ADXL345/346:

  • Ultra low power
  • Power consumption scales automatically with bandwidth
  • User selectable fixed 10-bit resolution or 4mg/LSB scale factor in all g-ranges, up to 13-bit resolution at ±16 g
  • 32 level output data FIFO minimizes host processor load
  • Built in motion detection functions
    • Tap/Double Tap detection
    • Activity/Inactivity monitoring
    • Free-Fall detection
  • Supply and I/O voltage range: 1.8 V to 3.6 V (ADXL345) and 1.7 V to 2.75 V (ADXL346)
  • SPI (3 and 4 wire) and I2C digital interfaces
  • Flexible interrupt modes – Any interrupt mappable to either interrupt pin
  • See data sheet for additional features

ADXL346:

  • 4- and 6-position orientation sensing

Configuration

Selectable ADXL34X I2C Device Address:

SDO I2C Address
0 0x53
1 0x1D

Software configurable features

ADXL34x Linux Driver Features

ADXL345/346:

  • Driver supports both SPI (3 and 4 wire) and I2C digital interface
    • I2C client using the 2.6 new style binding driver model
    • SPI using the generic Linux SPI Bus Driver Model
  • Support for Linux Power Management (PM) suspend resume
  • User selectable Sample Rate / Bandwidth trough sysfs hooks
  • User selectable resolution
  • Support for 32 level output data FIFO that minimizes host processor load
  • Option to report acceleration as Linux Input Absolute or Relative events. (EV_ABS or EV_REL)
  • Motion detection functions
    • Tap/Double Tap detection
      • User selectable Linux Input Event Codes for TAP_x,y,z axis
    • Activity/Inactivity monitoring
      • User selectable Linux Input Event Code for Activity/Inactivity reporting
      • Option to minimize host processor load and save additional power by automatically switch to sleep mode during periods of inactivity.
  • Free-Fall detection
    • User selectable Linux Input Event Code for Free-Fall reporting

ADXL346:

  • 4- and 6-position orientation sensing
    • User selectable Linux Input Event Code for individual positions

Source Code

Status

Status

Source Mainlined?
git Yes

Files

ADXL345/6 driver porting

Starting with linux-2.6.36 the ADXL34x driver is mainlined. If you are using an pre linux-2.6.36 kernel get the source from our repositories and add them to your kernel tree.

If you are using a kernel version without the threaded irq capabilities (< 2.6.30) get there driver from here:

    • Copy to linux-2.6.x/drivers/input/misc/adxl34x.c
    • Copy to linux-2.6.x/drivers/input/misc/adxl34x.h
    • Copy to linux-2.6.x/drivers/input/misc/adxl34x-i2c.c
    • Copy to linux-2.6.x/drivers/input/misc/adxl34x-spi.c
    • Copy to linux-2.6.x/include/linux/input/adxl34x.h

For the latest version of checkout the Files section of this document.

Add following lines to linux-2.6.x/drivers/input/misc/Kconfig:

config INPUT_ADXL34X
	tristate "Analog Devices ADXL34x Three-Axis Digital Accelerometer"
	default n
	help
	  Say Y here if you have a Accelerometer interface using the
	  ADXL345/6 controller, and your board-specific initialization
	  code includes that in its table of devices.

	  This driver can use either I2C or SPI communication to the
	  ADXL345/6 controller.  Select the appropriate method for
	  your system.

	  If unsure, say N (but it's safe to say "Y").

	  To compile this driver as a module, choose M here: the
	  module will be called adxl34x.

config INPUT_ADXL34X_I2C
	tristate "support I2C bus connection"
	depends on INPUT_ADXL34X && I2C
	default y
	help
	  Say Y here if you have ADXL345/6 hooked to an I2C bus.

	  To compile this driver as a module, choose M here: the
	  module will be called adxl34x-i2c.

config INPUT_ADXL34X_SPI
	tristate "support SPI bus connection"
	depends on INPUT_ADXL34X && SPI
	default y
	help
	  Say Y here if you have ADXL345/6 hooked to a SPI bus.

	  To compile this driver as a module, choose M here: the
	  module will be called adxl34x-spi.

Add following lines to linux-2.6.x/drivers/input/misc/Makefile:

obj-$(CONFIG_INPUT_ADXL34X)		+= adxl34x.o
obj-$(CONFIG_INPUT_ADXL34X_I2C)		+= adxl34x-i2c.o
obj-$(CONFIG_INPUT_ADXL34X_SPI)		+= adxl34x-spi.o

Example platform device initialization

For compile time configuration, it’s common Linux practice to keep board- and application-specific configuration out of the main driver file, instead putting it into the board support file.

For devices on custom boards, as typical of embedded and SoC-(system-on-chip) based hardware, Linux uses platform_data to point to board-specific structures describing devices and how they are connected to the SoC. This can include available ports, chip variants, preferred modes, default initialization, additional pin roles, and so on. This shrinks the board-support packages (BSPs) and minimizes board and application specific #ifdefs in drivers.

21 Oct 2010 16:10

Digital Accelerometer characteristics are highly application specific and may vary between boards and models. The platform_data for the device's “struct device” holds this information.

<source trunk/include/linux/input/adxl34x.h c linux-kernel>

Example Platfrom / Board file (SPI Interface Option)

Declaring SPI slave devices

Unlike PCI or USB devices, SPI devices are not enumerated at the hardware level. Instead, the software must know which devices are connected on each SPI bus segment, and what slave selects these devices are using. For this reason, the kernel code must instantiate SPI devices explicitly. The most common method is to declare the SPI devices by bus number.

This method is appropriate when the SPI bus is a system bus, as in many embedded systems, wherein each SPI bus has a number which is known in advance. It is thus possible to pre-declare the SPI devices that inhabit this bus. This is done with an array of struct spi_board_info, which is registered by calling spi_register_board_info().

For more information see: Documentation/spi/spi-summary.rst

21 Oct 2010 16:10

These snippets are all from the same file. arch/blackfin/mach-bf548/boards/ezkit.c:

#include <linux/spi/adxl34x.h>

<source trunk/arch/blackfin/mach-bf548/boards/ezkit.c:adxl34x_info{} c linux-kernel> <source trunk/arch/blackfin/mach-bf548/boards/ezkit.c:spi_adxl34x_chip_info{} c linux-kernel> <source trunk/arch/blackfin/mach-bf548/boards/ezkit.c:bfin_spi_board_info[] c linux-kernel>

Example Platfrom / Board file (I2C Interface Option)

Declaring I2C devices

Unlike PCI or USB devices, I2C devices are not enumerated at the hardware level. Instead, the software must know which devices are connected on each I2C bus segment, and what address these devices are using. For this reason, the kernel code must instantiate I2C devices explicitly. There are different ways to achieve this, depending on the context and requirements. However the most common method is to declare the I2C devices by bus number.

This method is appropriate when the I2C bus is a system bus, as in many embedded systems, wherein each I2C bus has a number which is known in advance. It is thus possible to pre-declare the I2C devices that inhabit this bus. This is done with an array of struct i2c_board_info, which is registered by calling i2c_register_board_info().

So, to enable such a driver one need only edit the board support file by adding an appropriate entry to i2c_board_info.

For more information see: Documentation/i2c/instantiating-devices.rst

21 Oct 2010 16:10

These snippets are all from the same file. arch/blackfin/mach-bf548/boards/ezkit.c:

<source trunk/arch/blackfin/mach-bf548/boards/ezkit.c:adxl34x_info{} c linux-kernel> <source trunk/arch/blackfin/mach-bf548/boards/ezkit.c:bfin_i2c_board_info1[] c linux-kernel>

Adding Linux driver support

Configure kernel with “make menuconfig” (alternatively use “make xconfig” or “make qconfig”)

The ADXL34x Driver depends on CONFIG_SPI or CONFIG_I2C
Input device support
  -*- Generic input layer (needed for keyboard, mouse, ...)
  < >   Support for memoryless force-feedback devices
  < >   Polled input device skeleton
  < >   Sparse keymap support library
        *** Userland interfaces ***
  < >   Mouse interface
  < >   Joystick interface
  <*>   Event interface
  < >   Event debugging
        *** Input Device Drivers ***
  [ ]   Keyboards  --->
  [ ]   Mice  --->
  [ ]   Joysticks/Gamepads  --->
  [ ]   Tablets  --->
  [ ]   Touchscreens  --->
  [*]   Miscellaneous devices  --->
	 < >   Analog Devices AD714x Capacitance Touch Sensor
	 <*>   Analog Devices ADXL34x Three-Axis Digital Accelerometer
	 <*>     support I2C bus connection (NEW)
	 <*>     support SPI bus connection (NEW)
        Hardware I/O ports  --->

Hardware configuration

Driver testing

Driver compiled as a module

I2C Interface:

root:~> modprobe evdev
root:~> modprobe adxl34x
input: ADXL34x accelerometer as /devices/platform/i2c-bfin-twi.1/i2c-adapter/i2c-1/1-0053/input/input1
adxl34x 1-0053: ADXL345 accelerometer, irq 140

SPI Interface:

root:~> modprobe evdev
root:~> modprobe adxl34x
input: ADXL34x accelerometer as /devices/platform/bfin-spi.1/spi1.2/input/input1
adxl34x spi1.2: ADXL345 accelerometer, irq 140

Driver compiled into the kernel

Your kernel startup messages should include something like this

I2C Interface:

input: ADXL34x accelerometer as /devices/platform/i2c-bfin-twi.1/i2c-adapter/i2c-1/1-0053/input/input1
adxl34x 1-0053: ADXL345 accelerometer, irq 140

SPI Interface:

input: ADXL34x accelerometer as /devices/platform/bfin-spi.1/spi1.2/input/input1
adxl34x spi1.2: ADXL345 accelerometer, irq 140

Common Problems

In case you see a message like this

adxl34x spi1.2: Failed to probe ADXL34x accelerometer

This means that the SPI communication and initilaization with the ADXL34x failed. check bus_num and chip_select in your platform device file

Checking for proper installation

After the kernel boot your device folder should include at least one device node for the accelerometer

root:/> ls -al /dev/input/
drw-r--r--    2 root     root            0 Jan  1 00:03 .
drwxr-xr-x    5 root     root            0 Jan  1 00:03 ..
crw-rw-r--    1 root     root      13,  64 Jan  1 00:03 event0
crw-rw-r--    1 root     root      13,  65 Jan  1 00:03 event1
root:/>

Check that the interrupt is registered.

root:~> cat /proc/interrupts | grep adxl34x
140:          0   adxl34x

root:~> cat /sys/class/input/input1/name
ADXL34x accelerometer

Use the event_test utility to test proper function

root:/> event_test /dev/input/event1
Input driver version is 1.0.0
Input device ID: bus 0x18 vendor 0x0 product 0x159 version 0x0
Input device name: "ADXL34x accelerometer"
Supported events:
  Event type 0 (Reset)
    Event code 0 (Reset)
    Event code 1 (Key)
    Event code 3 (Absolute)
  Event type 1 (Key)
    Event code 330 (Touch)
  Event type 3 (Absolute)
    Event code 0 (X)
      Value     15
      Min    -4096
      Max     4096
      Fuzz       3
      Flat       3
    Event code 1 (Y)
      Value    -15
      Min    -4096
      Max     4096
      Fuzz       3
      Flat       3
    Event code 2 (Z)
      Value    242
      Min    -4096
      Max     4096
      Fuzz       3
      Flat       3
Testing ... (interrupt to exit)
Event: time 107831.548000, type 3 (Absolute), code 0 (X), value -7
Event: time 107831.548000, type 3 (Absolute), code 1 (Y), value -2
Event: time 107831.548000, type 3 (Absolute), code 2 (Z), value 12
Event: time 107831.548000, type 0 (Reset), code 0 (Reset), value 0
Event: time 107831.588000, type 3 (Absolute), code 0 (X), value -17
Event: time 107831.588000, type 3 (Absolute), code 1 (Y), value 4
Event: time 107831.588000, type 0 (Reset), code 0 (Reset), value 0
Event: time 107831.632000, type 3 (Absolute), code 0 (X), value -16
Event: time 107831.632000, type 3 (Absolute), code 2 (Z), value 11
In case you move the accelerometer and don't receive events, it's likely that something with your Interrupt is wrong.
check irq number in your platform device file
In case you get a message like: evtest: No such device, it's likely that you have not install the necessary modules

Visualizing Linux Input Events using df_input example from DirectFB

root:/> df_input &

   ~~~~~~~~~~~~~~~~~~~~~~~~~~| DirectFB 1.2.7 |~~~~~~~~~~~~~~~~~~~~~~~~~~
        (c) 2001-2008  The world wide DirectFB Open Source Community
        (c) 2000-2004  Convergence (integrated media) GmbH
      ----------------------------------------------------------------

(*) DirectFB/Core: Single Application Core. (2009-05-27 15:03)
[1] 401 df_input
root:/> (*) Direct/Thread: Started 'VT Switcher' (405) [CRITICAL OTHER/OTHER 0/0] <12288>...
(*) Direct/Thread: Started 'Keyboard Input' (406) [INPUT OTHER/OTHER 0/0] <12288>...
(*) DirectFB/Input: Keyboard 0.9 (directfb.org)
(*) Direct/Thread: Started 'Linux Input' (407) [INPUT OTHER/OTHER 0/0] <12288>...
(*) DirectFB/Input: bf54x-keys (1) 0.1 (directfb.org)
(*) Direct/Thread: Started 'Linux Input' (408) [INPUT OTHER/OTHER 0/0] <12288>...
(*) DirectFB/Input: ADXL34x accelerometer (2) 0.1 (directfb.org)
(*) DirectFB/Graphics: Generic Software Rasterizer 0.6 (directfb.org)
(*) DirectFB/Core/WM: Default 0.3 (directfb.org)
(*) FBDev/Surface: Allocated 480x272 24 bit RGB24 buffer (index 0) at offset 0 and pitch 1440.
(*) FBDev/Surface: Allocated 480x272 24 bit RGB24 buffer (index 0) at offset 0 and pitch 1440.
(*) Direct/Interface: Loaded 'FT2' implementation of 'IDirectFBFont'.
(*) Direct/Interface: Loaded 'PNG' implementation of 'IDirectFBImageProvider'.

root:/>

 df_input example screenshot

ADXL34x Sysfs runtime controls

root:/> cd sys/class/input/input1/device/
root:/sys/devices/platform/bfin-spi.1/spi1.2> ls -al
drwxr-xr-x    3 root     root            0 Jan  2 10:39 .
drwxr-xr-x    4 root     root            0 Jan  2 10:39 ..
-rw-rw-r--    1 root     root         4096 Jan  2 12:01 autosleep
-rw-rw-r--    1 root     root         4096 Jan  2 12:01 calibrate
-rw-rw-r--    1 root     root         4096 Jan  2 12:01 disable
lrwxrwxrwx    1 root     root            0 Jan  2 12:01 driver -> ../../../../bus/spi/drivers/adxl34x
drwxr-xr-x    3 root     root            0 Jan  2 10:39 input
-r--r--r--    1 root     root         4096 Jan  2 12:01 modalias
-rw-rw-r--    1 root     root         4096 Jan  2 12:01 rate
lrwxrwxrwx    1 root     root            0 Jan  2 12:01 subsystem -> ../../../../bus/spi
-rw-r--r--    1 root     root         4096 Jan  2 12:01 uevent
root:/sys/devices/platform/bfin-spi.1/spi1.2>

Device Calibration

root:/sys/devices/platform/bfin-spi.1/spi1.2> echo 1 > calibrate
root:/sys/devices/platform/bfin-spi.1/spi1.2> cat calibrate
2,10,-204

Controlling the Output Data Rate

Output Data Rate (Hz) Bandwidth (Hz) Value
3200 1600 15
1600 800 14
800 400 13
400 200 12
200 100 11
100 50 10
50 25 9
25 12.5 8
12.5 6.25 7
6.25 3.125 6
3.125 1.563 5
1.563 0.782 4
0.782 0.39 3
0.39 0.195 2
0.195 0.098 1
0.098 0.048 0

Writing 'value' into rate sets the desired sample rate
Reading rate returns the current value

See table above for supported sample rates

root:/sys/devices/platform/bfin-spi.1/spi1.2> echo 8 > rate
root:/sys/devices/platform/bfin-spi.1/spi1.2> cat rate
8

Be aware: The ADXL34x conforms to The I2C Bus Specification, Version 2.1, January 2000, available from Phillips Semiconductor. It supports standard (100 kHz) and fast (400 kHz) data transfer modes.

Very high output data rates are only possible via fast I2C (400kHz) or the SPI interface.

Enabling / Disabling the Device

Writing '1' into disable - disables the ADXL34x (low power suspend mode)
Writing '0' into disable - enables the ADXL34x

root:/sys/devices/platform/bfin-spi.1/spi1.2> echo 1 > disable
root:/sys/devices/platform/bfin-spi.1/spi1.2> echo 0 > disable
root:/sys/devices/platform/bfin-spi.1/spi1.2>

Enabling / Disabling Autosleep Upon Inactivity

Writing '1' into autosleep - enables Autosleep Upon Inactivity
Writing '0' into autosleep - disables Autosleep Upon Inactivity

root:/sys/devices/platform/bfin-spi.1/spi1.2> echo 1 > autosleep
root:/sys/devices/platform/bfin-spi.1/spi1.2> echo 0 > autosleep
root:/sys/devices/platform/bfin-spi.1/spi1.2>

More Information

ADXL345/6 Android Acceleration Sensor

Using this driver under Android as Acceleration Sensor Follow the link here ADXL345 Android Sensor

resources/tools-software/linux-drivers/input-misc/adxl345.1328002655.txt.gz · Last modified: 31 Jan 2012 10:37 (external edit)