ETZKX Accelerometer


This page is dedicated to the etzkx accelerometer

Download the software from:

git clone git://git.etezian.org/etzkx.git

Or download the tarball here

Browse the code from gitweb from here

The etzkx accelerometer has been presented at FOSDEM 2013, download the slides of the event here

Device description

The kxcnl-1010 accelerometer is an ultra low-power device based on a differential capacitance arising from acceleration-induced motion of the sensor element. The device has a dynamically user selectable sensitivity scale of +-2/+-4/+-6/+-8g. Moreover the user has the possibility to select the sampling frequency (odr) from 3.125Hz to 1.6kHz.

The X, Y, Z coordinates are accessible by polling the device. Interrupt generation on data ready is also possible if preferred.

The device is capable of running two state machines for gesture recognition such as orientation change, shake, tap, etc. Two sets of registers are used to load the algorithms for the state machine.

The communication with the CPU is done via I2C bus. Two interrupt lines allow signalling the state machines behavior and possibly the presence of new data.

The device implements a hardware selftest functionality which allows testing of the reliability of the device.

The driver

The driver is located under

driver/misc/etzkx.c
include/linux/i2c/etzkx.h

and is placed in between the i2c driver and the userspace interfaces

 __________________________
|        |        |        |
| input  | sysfs  |  char  |
| device |        | device |
|________|________|________|
|                          |
|          etzkx           |
|__________________________|
|                          |
|         i2c smbus        |
|__________________________|
|                          |
|         i2c  xfer        |
|                          |
+==========================+
|                          |
|        kxcnl-1010        |
|__________________________|

In the menuconfig the driver is reachable

Device Drivers  --->
   [*] Misc devices  --->
      <*>   ETZKX kxcnl 3d digital accelerometer

The interfaces

The driver generates three types of interfaces:

  • sysfs: provides information related to the device and sets some basic parameters like output data rate (odr) and range.

  • input event: provides the X, Y, Z coordinates.

  • character device: provides state machine related information.

Sysfs interfaces

Here is a list of all the sysfs interfaces generated by the driver

hwid RO - shows the chip installed on the board

enable RW - enables/disables the streaming of X, Y, Z coordinates which are readable from the input event file 1 enables the the streaming 0 disables the streaming

odr RW - sets the output data rate of the chip, i.e. sets the frequency of working of the chip. The available data rates are (in Hz) 3.125, 6.25, 12.5, 25, 50, 100, 400, 1600. It is possible to write a generic frequency and the driver will normalize it to the closest available. When a state machine is running the user is prevented form changing the odr.

delay RW - sets the driver polling rate in ms. Usually is

                         1
               delay = -----
                        odr

      but depending of some state machine conditions, odr and delay
      might not be synchronized.

range RW - sets the sensitivity measured in g. The available g range are +-2g, +-4g, +-6g, +-8g. When a state machine is running, the user is prevented from changing the range.

self_test RW - enables/disables the self-test functionality. When the self_test is enabled the X, Y, Z axes are affected by an offset, that offset allows to evaluate the liability of the device (refer to the datasheets for the self test patterns) 1 enables self test 0 disables self test

drv_version RO - shows the driver version

Input event interface

The input event is generated under /dev/input/eventX, where X is an incremental number chosen by the input driver framework.

To eventX file is associated the 'etzkx' name which is discoverable using an ioctl function with EVIOCGNAME flag.

DIR *dir;
struct dirent *de;
char *fname;
[...]

dir = opendir("/dev/input");
while ( (de = readdir(dir)) )
{
    fd = open(de->d_name, O_RDONLY))
    ioctl(fd, EVIOCGNAME(sizeof(fname) - 1), &fname)

    if (!strcmp(fname, "etzkx"))
        /*** found it! ***/

    close (fd);
}

The driver streams the coordinates every "delay" ms (or "odr" Hz) through this interface. The input driver sends a struct input_event to the interface buffer, which has the following structure:

#include <linux/input.h>

struct input_event {
    struct timeval time;
    __u16 type;
    __u16 code;
    __s32 value;
};

where the type event is EV_ABS, the code of the event is ABS_X, ABS_Y, ABS_Z corresponding to the X, Y, Z coordiantes and in the end the value field is the specific coordinate value. The driver sends three different events for each coordinate followed by a synchronization event which has type=0, code=0 and value=0.

A possible reading algorithm can be

struct input_event ev;

while (1)
{
    do
    {
        read(fd, &ev, sizeof(struct input_event));

        if (ev.type == EV_ABS)
            switch (ev.code)
            {
                case ABS_X:
                    X = ev.value;
                    break;
                case ABS_Y:
                    Y = ev.value;
                    break;
                case ABS_Z:
                    Z = ev.value;
                    break;
            }
    } while (ev.type != EV_SYN);
}

Character device

The character device is used to report to the userspace the running state machine's outcome. The interface is capable of polling so that it is possible to use select() or poll() on it. The character interface is generated as

/dev/etzkx_stm

The driver communicates with userspace by writing 64 bit structure on the interface

+-----+--------------------------+
| 32  | algorithm id             |
+-----+--------------------------+
| 32  | specific algorithm data  |
+-----+--------------------------+

Currently, three algorithms are implemented:

  • algorithm id ETZKX_STM_ID_TIMING: timing algorithm used for testing. It sends an interrupt every 16 odr.

    ETZKX_STM_ID_ORIENTATION: sends an interrupt every orientation change (portrait or landscape)

    ETZKX_STM_ID_DOUBLE_TAP: sends an interrupt every time that a double tap is detected

  • specific algorithm data timing (bit order) 32 bit: not relevant, uninitialized

    orientation (bit order) 16 bit: 1 if portrait, 0 otherwise 16 bit: 1 if landscape, 0 otherwise

    double tap (bit order) 8 bit: 1 if +x, 2 if -x, 0 otherwise 8 bit: 1 if +y, 2 if -y, 0 otherwise 8 bit: 1 if +z, 2 if -z, 0 otherwise 8 bit: double tap peak

The /dev/etzkx_stm file is capable of ioctl with the following flags

ETZKXIO_ENABLE_TIMING: enables timing algorithm
ETZKXIO_DISABLE_TIMING: disable timing algorithm
ETZKXIO_ENABLE_ORIENTATION: enables orientation algorithm
ETZKXIO_DISABLE_ORIENTATION: disables orientation algorithm
ETZKXIO_ENABLE_DOUBLE_TAP: enables double tap algorithm
ETZKXIO_DISABLE_DOUBLE_TAP: disables double tap algorithm

ETZKXIO_WHICH_ORIENTATION: asks to the driver the actual orientation
status. The driver provides via ioctl an algorithm structure like
this:

   32 bit: ETZKX_STM_ID_ORIENTATION
   16 bit: 1 if portrait, 0 otherwise
   16 bit: 1 if landscape, 0 otherwise

ETZKXIO_INSTANT_ORIENTATION: like ETZKXIO_WHICH_ORIENTATION, with the
difference that the calculation of the orientation is calculated by
comparing the X and Y coordinates.

ETZKXIO_RUNNING_ALGO: reports to the userspace the two running
algorithms for each state machine slot:

   32 bit: running algorithm id on slot 1
   32 bit: running algorithm id on slot 2

if no state machine is loaded, the id is equal to ETZKX_STM_ID_NO_STM

Driver usage

The driver follows a state machine way of working and at any time it tracks the state which the driver is in.

                 __STRM --- STRM + STM1
                /       \/              \
               /        /\               \

STBY --- ACTIVE --- STM1 STRM + STM2 --- STRM + STM1 + STM2 \ \/ / __ /\ / STM2 --- STM1 + STM2

To reach each driver state, userspace applications have to enable/disable the available features using the related interfaces.

Enable/disable streaming (STRM state): echo 1 > /sys/.../enable echo 0 > /sys/.../enable

Enable/disable state machine (STM1/STM2 state): ioctl (fd, ETZKXIO_ENABLE_ORIENTATION, 0); ioctl (fd, ETZKXIO_ENABLE_DOUBLE_TAP, 0); ioctl (fd, ETZKXIO_DISABLE_ORIENTATION, 0); ioctl (fd, ETZKXIO_DISABLE_DOUBLE_TAP, 0);

Self test

The self test checks the electromechanical functionality of the sensor. The driver sets the self test state as a specific branch of the driver state machine:

                   _
                  /  ST
                 /    ^

STDBY <---> ACTIVE | \ | _ v STRM

To enable/disable the self test

echo 1 > /sys/.../self_test
echo 0 > /sys/.../self_test

This applies an extra capacitance to every axes which adds an offset to the X, Y, Z output, it can be different for each coordinate.

The suppliers provides the minimum Dx, Dy, Dz offset in order to consider the device reliable. The evaluation should be done like follows:

|Xst - X| > Dx
|Yst - Y| > Dy
|Zst - Z| > Dz

where Xst, Yst and Zst are the coordinates measured after applying the self test on the accelerometer.

Datasheets

Download the datasheets and get more informations from Kionix website for the kxcnl device.

TODO

Currently I'm working for supporting the ST Lis3dsh accelerometer which has some small differences.

Contributions and queries

For any kind of contribution or question feel free to contact Andi Shyti at andi@etezian.org