NOTICE: The Processors Wiki will End-of-Life in December of 2020. It is recommended to download any files or other content you may need that are hosted on processors.wiki.ti.com. The site is now set to read only.

Android Sensor PortingGuide

From Texas Instruments Wiki
Jump to: navigation, search

TIBanner.png
Content is no longer maintained and is being kept for reference only!



Introduction[edit]

Content is no longer maintained and is being kept for reference only!



This section of guide provides a step by step explanation of what's involved in adding/porting sensors in a custom Android build like Rowboat.

Accelerometer[edit]

Android sensor sub system overview[edit]

AndroidSensor.jpg

Above diagram shows the android subsystem overview.

  • Application Framework
    • Sensor Applications uses the Sensor application framework to get the sensor data. It communicates with C++ layer through sensor Java native interface (JNI)
  • Sensor Libraries
    • Sensor middle layer mainly consists of Sensor Manager, Sensor service and Sensor hardware abstraction layer.
  • Input Subsystem
    • This is a generic Linux framework for all input devices like keyboard, mouse, touchscreen and defines a standard set of events. It interfaces to user space through /sys/class/input interface.
  • Evdev
    • Evdev provides a generic way for input device events to be accessible under /dev/input/eventX .
  • LIS331DLH Accelerometer Driver
    • This driver communicates with LIS331DLH accelerometer chip via GPIO and I2C bus. GPIO line is used for generating interrupts while I2C bus for accessing and configuring accelerometer registers.

Driver porting[edit]

On AM37x Flashboard Accelerometer(LIS331DLH) is connected to I2C 1 bus. Its relevant initialization and pin-muxing is done at <kernel>/arch/arm/mach-omap2/board-omap3evm.c file.

Modify LIS331DLH data structure[edit]

Modify the following structure to change the axes directions (negate_x, negate_y, negate_x) and axis mapping (axis_map_x, axis_map_y, axis_map_z). This can be used to calibrate the sensor.

  struct lis331dlh_platform_data lis331dlh_omap3evm_data = {
       .min_interval = 1,
       .poll_interval = 200,
       .g_range = LIS331DLH_G_8G,
       .axis_map_x = 0,
       .axis_map_y = 1,
       .axis_map_z = 2,
       .negate_x = 0,
       .negate_y = 0,
       .negate_z = 0,
  };

Add I2C board info structure[edit]

On Flashboard accelerometer is connected to I2C 1. If your sensor is interfaced on different I2C bus then please do the following changes to your board file.

  static struct i2c_board_info __initdata omap3evm_i2c_x_boardinfo[] = {
     {
             I2C_BOARD_INFO("lis331dlh", 0x18),
             .platform_data = &lis331dlh_omap3evm_data,
     },
  };

Where 0x18 is the lis331dlh chip address. Please change this address corresponding to your chip address.

Register i2c bus[edit]

Register I2C bus with the i2c sub-system.

  static int __init omap3_evm_i2c_init(void)
  {
       .
       .
       omap_register_i2c_bus(x, 100, omap3evm_i2c_x_boardinfo, ARRAY_SIZE(omap3evm_i2c_x_boardinfo));
       .
       .
       return 0;
  }
    
  Note: where x is i2c bus number.

Interrupt line modification[edit]

on Flash board accelerometer interrupt line is connected to GPIO 42.Please change the following if your accelerometer interrupt line is connected to different GPIO.

Pin mux change in board configuration file[edit]

Add following line to omap36x_board_mux structure to arch/arm/mach-omap2/board-omap3evm.c file.

  static struct omap_board_mux omap36x_board_mux[] __initdata = {
  {
      .
      .
      //Ex: Pin mux for GPIO 42.
      OMAP3_MUX(GPMC_A9, OMAP_MUX_MODE4 | OMAP_PIN_INPUT_PULLUP), 
  }
    
  Note: Please change OMAP3_MUX arguments as per your GPIO No.

LIS331DLH driver file modification[edit]

LIS331DLH accelerometer driver is located at <kernel>/driver/misc/lis331dlh.c file. Change the following macro for your interrupt gpio number.

  #define LIS331DLH_INT2_GPIO     GPIO_NO

Test Accelerometer driver[edit]

Enable Accelerometer sensor.

  #cat 1 > /sys/bus/i2c/drivers/lis331dlh/1-0018/enable
   
  Note: Please ckeck appropriate sysfs path as per your driver

Use getevent command to see accelerometer events

  #getevent
     add device 2: /dev/input/event2
     name:     "Acceleromter"
     /dev/input/event2: 0001 014a 00000001
     /dev/input/event2: 0003 0000 0000089e
     /dev/input/event2: 0003 0001 000005fe

Android hardware abstraction layer[edit]

Sensor hardware abstraction layer (HAL) is located in <android source>/hardware/ti/omap3/libsensors directory.

Adding new sensor support in android HAL Ex: Accelerometer[edit]

Implement a sensor class[edit]

Accelerometer sensor class in implemented in AccelSensor.h and AccelSensor.cpp file.

  class AccelSensor : public SensorBase {
       int mEnabled;
       .
       .
       int setInitialState();
       
   public:
      
       AccelSensor();
       virtual ~AccelSensor();
       virtual int readEvents(sensors_event_t* data, int count);
       virtual bool hasPendingEvents() const;
       virtual int setDelay(int32_t handle, int64_t ns);
       virtual int enable(int32_t handle, int enabled);
   };

Add new sensor support[edit]

Add new sensor support in sensors.cpp file.

  • Add new sensor to sSensorList Structure
  /* The SENSORS Module */
  static const struct sensor_t sSensorList[] = {
  .
  .
  { "STMicro 3 axis accelerometer",
    "STMicro",
    1, SENSORS_ACCELERATION_HANDLE,
    SENSOR_TYPE_ACCELEROMETER, RANGE_A, RESOLUTION_A, 0.23f, 20000, { } },
  };
  • Create object of new sensor
  sensors_poll_context_t::sensors_poll_context_t()
  {
       .
       .
       mSensors[accel] = new AccelSensor();
       mPollFds[accel].fd = mSensors[accel]->getFd();
       mPollFds[accel].events = POLLIN;
       mPollFds[accel].revents = 0;
       .
       .
       int wakeFds[2];
       int result = pipe(wakeFds);
       LOGE_IF(result<0, "error creating wake pipe (%s)", strerror(errno));
       fcntl(wakeFds[0], F_SETFL, O_NONBLOCK);
       fcntl(wakeFds[1], F_SETFL, O_NONBLOCK);
       mWritePipeFd = wakeFds[1];
               
       mPollFds[wake].fd = wakeFds[0];
       mPollFds[wake].events = POLLIN;
       mPollFds[wake].revents = 0;
            
 }


  • Update sensors_poll_context_t structure and add new sensor case to handleToDriver function.
  struct sensors_poll_context_t {
      struct sensors_poll_device_t device; // must be first
      .
      .
  private:
      enum {
           accel           = 0,
           light           = 1,
           proximity       = 2,
           press_temp      = 3,
           numSensorDrivers,
           numFds,
      };
     
    
   int handleToDriver(int handle) const {
           switch (handle) {
                    case ID_A:
                           return accel;
                       .
                       .
       }
           return -EINVAL;
   }

Calibration methods[edit]

Changing axes directions and swapping axes[edit]

This can be achieved by modifying the driver or android hardware abstraction layer.

Driver Modification[edit]

Accelerometer platform data structure is as follows.

  struct lis331dlh_platform_data lis331dlh_omap3evm_data = {
      .min_interval = 1,
      .poll_interval = 200,
      .g_range = LIS331DLH_G_8G,
      .axis_map_x = 0,
      .axis_map_y = 1,
      .axis_map_z = 2,
      .negate_x = 0,
      .negate_y = 0,
      .negate_z = 0,
  }; 

axis_map_x, axis_map_y, axis_map_z can be used to swap x, y and z axes. If axis_map_x is 0 then it will be mapped to x-axis in android, if it is 1 then it will be mapped to y axis in Android and so on.

To change the axes direction we can set negate_x, negate_y and negate_z value to 1. If negate_x, negate_y and negate_z values are set to 1 then driver will negate accelerometer axes readings before passing to user space (Android).

Android HAL modification[edit]

This type of calibration can be achieved in Android HAL as well by modifying readEvents() function in <android source>/hardware/ti/omap3/libsensors/AccelSensor.cpp file.

  int AccelSensor::readEvents(sensors_event_t* data, int count)
  {
      .
      .
      while (count && mInputReader.readEvent(&event)) {
          int type = event->type;
          if (type == EV_ABS) {
              float value = event->value;
              if (event->code == EVENT_TYPE_ACCEL_Y) {
                  mPendingEvent.data[1] =  -(value * CONVERT_A_Y);
              } else if (event->code == EVENT_TYPE_ACCEL_X) {
                  mPendingEvent.data[0] = -(value * CONVERT_A_X);
              } else if (event->code == EVENT_TYPE_ACCEL_Z) {
                  mPendingEvent.data[2] = -(value * CONVERT_A_Z);
              }
     .
     .
     .
  }

data[index]: index can be changed to swap axes and value can be negated to change the axis direction.

Accelerometer zero calibration[edit]

When the device rests on a level surface, X and Y should be around zero. The accelerometer can be zero calibrated i.e. adjusted so that the acceleration reads zero at the current acceleration of the phone.

For zero calibration, store the negative X, Y and Z values in three variables cx, cy and cz.To get zero calibrated X, Y and Z values simply add cx, cy and cz to the current sensor readings.

Following links show the examples for achieving zero calibration.

http://www.intuitor.com/student/Android%20Phone%20Site/StephanAccelerometerAndroid.php

http://stuffthathappens.com/blog/2009/03/15/android-accelerometer/

Important files[edit]

  • Sensor Manager Application Layer: <android source>/frameworks/base/core/java/android/hardware folder
  • Sensor JNI layer: <android source>/frameworks/base/core/jni/android_hardware_SensorManager.cpp file
  • Sensor Manager Library: <android source>/frameworks/base/libs/gui folder
  • Sensor Service: <android source>/frameworks/base/services/sensorservice folder
  • Sensor HAL: <android source>/hardware/ti/omap3/libsensors folder
  • Accelerometer Sensor driver: <kernel>/drivers/input/misc/lis331dlh.c file
E2e.jpg {{
  1. switchcategory:MultiCore=
  • For technical support on MultiCore devices, please post your questions in the C6000 MultiCore Forum
  • For questions related to the BIOS MultiCore SDK (MCSDK), please use the BIOS Forum

Please post only comments related to the article Android Sensor PortingGuide here.

Keystone=
  • For technical support on MultiCore devices, please post your questions in the C6000 MultiCore Forum
  • For questions related to the BIOS MultiCore SDK (MCSDK), please use the BIOS Forum

Please post only comments related to the article Android Sensor PortingGuide here.

C2000=For technical support on the C2000 please post your questions on The C2000 Forum. Please post only comments about the article Android Sensor PortingGuide here. DaVinci=For technical support on DaVincoplease post your questions on The DaVinci Forum. Please post only comments about the article Android Sensor PortingGuide here. MSP430=For technical support on MSP430 please post your questions on The MSP430 Forum. Please post only comments about the article Android Sensor PortingGuide here. OMAP35x=For technical support on OMAP please post your questions on The OMAP Forum. Please post only comments about the article Android Sensor PortingGuide here. OMAPL1=For technical support on OMAP please post your questions on The OMAP Forum. Please post only comments about the article Android Sensor PortingGuide here. MAVRK=For technical support on MAVRK please post your questions on The MAVRK Toolbox Forum. Please post only comments about the article Android Sensor PortingGuide here. For technical support please post your questions at http://e2e.ti.com. Please post only comments about the article Android Sensor PortingGuide here.

}}

Hyperlink blue.png Links

Amplifiers & Linear
Audio
Broadband RF/IF & Digital Radio
Clocks & Timers
Data Converters

DLP & MEMS
High-Reliability
Interface
Logic
Power Management

Processors

Switches & Multiplexers
Temperature Sensors & Control ICs
Wireless Connectivity