Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android2.3.4增加gsensor

android2.3.4增加gsensor

編輯:關於Android編程

sensor:lsm330dlc(acc + gyr)
1、將lsm330dlc驅動代碼放到drivers/input/misc目錄下,修改此上當下的kconfig和Makefile文件分別增加如下字段:

Kconfig
config SENSORS_LSM330DLC
tristate "ST's family of MEMS sensor modules of LSM330DLC"
depends on I2C && INPUT && MACH_ZT6810
select INPUT_POLLDEV
default y
help
This driver provides support for the LSM330DLC gyroscope and accelerator connected via I2C.


Makefile
obj-$(CONFIG_SENSORS_LSM330DLC)+= lsm330dlc_acc.o lsm330dlc_gyr.o


2、對照硬件原理圖,修改lsm330dlc.h中的相應中斷IO及數據全能IO,如:

/*Xandy modify the accelerator and gyro interrupt pins @2012/9/12*/
#define INT1_GPIO_ACC 178
#define INT2_GPIO_ACC 179 
#define INT1_GPIO_GYR 181
#define INT2_GPIO_GYR 180 
/*Xandy add Sensors enable pin*/
#define SENSOR_EN_GPIO 38


3、修改BSP相應文件(既對應的board-xx.c文件),對lsm330dlc進行驅動注冊(I2C總線),如:

#ifdef CONFIG_SENSORS_LSM330DLC
static struct i2c_board_info __initdata zt6810_i2c_LSM330DLC[] = {
       {
               I2C_BOARD_INFO("lsm330dlc_acc", 0x19),
       },
       {
      I2C_BOARD_INFO("lsm330dlc_gyr", 0x6B),
},
};
#endif
static int __init zt6810_i2c_init(void)
{
omap_register_i2c_bus(1, 2600, zt6810_i2c_boardinfo,
ARRAY_SIZE(zt6810_i2c_boardinfo));
/* Bus 2 is used for Battery ckeck(bq27410) */
#ifdef CONFIG_BATTERY_MAX17049
omap_register_i2c_bus(2, 100, zt6810_i2c_MAX17049, ARRAY_SIZE(zt6810_i2c_MAX17049));
#else
omap_register_i2c_bus(2, 100, NULL, 0);
#endif
/* projector don't work reliably with 400kHz */
#ifdef CONFIG_SENSORS_LSM330DLC 
omap_register_i2c_bus(3, 200, zt6810_i2c_LSM330DLC, ARRAY_SIZE(zt6810_i2c_LSM330DLC));
#endif
return 0;
}


內核編譯通過之後,將uImage燒錄到樣機,如果不出意外,在串口終端進入相應目錄,ls一下將會看到如下內容:

 

\

\

\

 

 

 

可以看出acc在I2C總線注冊成功,相應的I2C總線號及address為3-0019,而gyr則為3-006B
4、在串口終端裡輸入如下命令:

# cat /proc/bus/input/devices

 

將會得到如下信息:

# cat /proc/bus/input/devices
I: Bus=0019 Vendor=0001 Product=0001 Version=0100
N: Name="gpio-keys"
P: Phys=gpio-keys/input0
S: Sysfs=/devices/platform/gpio-keys/input/input0
U: Uniq=
H: Handlers=kbd event0
B: EV=3
B: KEY=4 0 0 0 100000 0 0 0
I: Bus=0019 Vendor=0001 Product=0001 Version=0003
N: Name="TWL4030 Keypad"
P: Phys=twl4030_keypad/input0
S: Sysfs=/devices/platform/omap/omap_i2c.1/i2c-1/1-004a/twl4030_keypad/input/input1
U: Uniq=
H: Handlers=kbd event1
B: EV=100013
B: KEY=800 c1680 0 2000000 100000aa
B: MSC=10
I: Bus=0000 Vendor=0000 Product=0000 Version=0000
N: Name="ADS7846 Touchscreen"
P: Phys=spi1.0/input0
S: Sysfs=/devices/platform/omap2_mcspi.1/spi1.0/input/input2
U: Uniq=
H: Handlers=mouse0 event2
B: EV=b
B: KEY=400 0 0 0 0 0 0 0 0 0 0
B: ABS=1000003
I: Bus=0000 Vendor=0000 Product=0000 Version=0000
N: Name="twl4030_pwrbutton"
P: Phys=twl4030_pwrbutton/input0
S: Sysfs=/devices/platform/omap/omap_i2c.1/i2c-1/1-0049/twl4030_pwrbutton/input/input3
U: Uniq=
H: Handlers=kbd event3
B: EV=3
B: KEY=100000 0 0 0
I: Bus=0018 Vendor=0000 Product=0000 Version=0000
N: Name="lsm330dlc_acc"
P: Phys=
S: Sysfs=/devices/platform/omap/omap_i2c.3/i2c-3/3-0019/input/input4
U: Uniq=
H: Handlers=js0 event4
B: EV=9
B: ABS=100 107
I: Bus=0018 Vendor=0000 Product=0000 Version=0000
N: Name="lsm330dlc_gyr"
P: Phys=
S: Sysfs=/devices/platform/omap/omap_i2c.3/i2c-3/3-006b/input/input5
U: Uniq=
H: Handlers=js1 event5
B: EV=9
B: ABS=7

 


這裡列出的是目前系統已經注冊的input設備的一些信息,最後兩項就是之前加入的sensor(acc + gyr)注冊的相應input設備

為什麼sensor會注冊成input設備,看看相應的驅動源碼裡有如下內容:

static int lsm330dlc_acc_input_init(struct lsm330dlc_acc_data *acc)
{
int err;
INIT_DELAYED_WORK(&acc->input_work, lsm330dlc_acc_input_work_func);
acc->input_dev = input_allocate_device();
if (!acc->input_dev) {
err = -ENOMEM;
dev_err(&acc->client->dev, "input device allocation failed\n");
goto err0;
}
acc->input_dev->open = lsm330dlc_acc_input_open;
acc->input_dev->close = lsm330dlc_acc_input_close;
acc->input_dev->name = LSM330DLC_ACC_DEV_NAME;
//acc->input_dev->name = "accelerometer";
acc->input_dev->id.bustype = BUS_I2C;
acc->input_dev->dev.parent = &acc->client->dev;
input_set_drvdata(acc->input_dev, acc);
set_bit(EV_ABS, acc->input_dev->evbit);
/* next is used for interruptA sources data if the case */
set_bit(ABS_MISC, acc->input_dev->absbit);
/* next is used for interruptB sources data if the case */
set_bit(ABS_WHEEL, acc->input_dev->absbit);
input_set_abs_params(acc->input_dev, ABS_X, -G_MAX, G_MAX, FUZZ, FLAT);
input_set_abs_params(acc->input_dev, ABS_Y, -G_MAX, G_MAX, FUZZ, FLAT);
input_set_abs_params(acc->input_dev, ABS_Z, -G_MAX, G_MAX, FUZZ, FLAT);
/* next is used for interruptA sources data if the case */
input_set_abs_params(acc->input_dev, ABS_MISC, INT_MIN, INT_MAX, 0, 0);
/* next is used for interruptB sources data if the case */
input_set_abs_params(acc->input_dev, ABS_WHEEL, INT_MIN, INT_MAX, 0, 0);
err = input_register_device(acc->input_dev);
if (err) {
dev_err(&acc->client->dev,
"unable to register input device %s\n",
acc->input_dev->name);
goto err1;
}
 
return 0;
err1:
input_free_device(acc->input_dev);
err0:
return err;
}

我們在終端裡再輸入如下命令:
# getevent
將得到如下信息:
# getevent
could not get driver version for /dev/input/mice, Not a typewriter
add device 1: /dev/input/event2
  name:     "ADS7846 Touchscreen"
could not get driver version for /dev/input/mouse0, Not a typewriter
add device 2: /dev/input/event0
  name:     "gpio-keys"
add device 3: /dev/input/event5
  name:     "lsm330dlc_gyr"
could not get driver version for /dev/input/js1, Invalid argument
add device 4: /dev/input/event4
  name:     "lsm330dlc_acc"
could not get driver version for /dev/input/js0, Invalid argument
add device 5: /dev/input/event1
  name:     "TWL4030 Keypad"
add device 6: /dev/input/event3
  name:     "twl4030_pwrbutton"
/dev/input/event4: 0003 0000 00000001
/dev/input/event4: 0003 0001 ffffff5f
/dev/input/event4: 0003 0002 000003df
/dev/input/event4: 0000 0000 00000000
/dev/input/event4: 0003 0000 fffffffe
/dev/input/event4: 0003 0001 ffffff5e
/dev/input/event4: 0003 0002 000003e2
/dev/input/event4: 0000 0000 00000000
/dev/input/event4: 0003 0000 00000002
/dev/input/event4: 0003 0001 ffffff5d
/dev/input/event4: 0003 0002 000003e5
/dev/input/event4: 0000 0000 00000000
/dev/input/event4: 0003 0000 00000001
/dev/input/event4: 0003 0001 ffffff5f
/dev/input/event4: 0003 0002 000003df
/dev/input/event4: 0000 0000 00000000
/dev/input/event4: 0003 0000 fffffffe
/dev/input/event4: 0003 0001 ffffff66
/dev/input/event4: 0003 0002 000003e4
......


getevent命令是用來獲取系統輸入事件的,很容易看出,當前系統一直有event4的事件發生,對照上面的信息:
add device 4: /dev/input/event4
  name:     "lsm330dlc_acc"
可見前面加入的sensor(acc)已經開始工作了並不停地往系統上報當前的加速度事件!
如果正常配置且編譯通過了sensor的驅動,但無法得到這些信息,那麼你就有必要查查你的硬件是否正常了,如:芯片是不是一致;有沒有虛焊,最後找個示波器掛一下,看看相應的I2C波形正不正常!
5、完成了上面的工作,並不等於完成了全部的工作,現在雖然sensor已經開始工作了,但當你進入到具有重力感應的界面,如:系統設置。
發現UI目前是不會轉動的,或者你下一個sensor測試工具,也是一樣的。
這是因為在HAL裡面,還沒有打通sensor事件上報的通道,下面來看看HAL裡面的代碼要如何修改。
sensor HAL層的代碼在
hardware/ti/omap3/libsensors
目錄下面。
先來看看sensors.cpp這個文件。這裡是sensor進行HAL層封裝的,在這裡可以看到有
struct sensors_module_t HAL_MODULE_INFO_SYM = {
        common: {
                tag: HARDWARE_MODULE_TAG,
                version_major: 1,
                version_minor: 0,
                id: SENSORS_HARDWARE_MODULE_ID,
                name: "Sensor module",
                author: "Texas Instruments Inc.",
                methods: &sensors_module_methods,
        },
        get_sensors_list: sensors__get_sensors_list,
};
這是HAL層封裝的一個標准結構,我們主要來看看下面這段代碼:
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;
mSensors[gyro] = new GyroSensor();
mPollFds[gyro].fd = mSensors[gyro]->getFd();
mPollFds[gyro].events = POLLIN;
mPollFds[gyro].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;
}
可以看出,這裡new了兩個sensor設備,一個是ACC,另外一個則是GYR!進入到accelSensor.cpp,在下面這個構造函數裡:
AccelSensor::AccelSensor()
    : SensorBase(NULL, "lsm330dlc_acc"),
      mEnabled(0),
      mInputReader(4),
      mHasPendingEvent(false)
{
    memset(&mPendingEvent, 0, sizeof(mPendingEvent));
    mPendingEvent.version = sizeof(sensors_event_t);
    mPendingEvent.sensor = ID_A;
    mPendingEvent.type = SENSOR_TYPE_ACCELEROMETER;
mPendingEvent.acceleration.status = SENSOR_STATUS_ACCURACY_HIGH;
    if (data_fd)
{
        strcpy(input_sysfs_path, ACCEL_SENSOR_NAME);
        input_sysfs_path_len = strlen(input_sysfs_path);
        enable(0, 1);
    }
}

 


黃色背景標注的是需要修改的,其中ACCEL_SENSOR_NAME的宏定義相應如下:
/*Xandy add AccelSensor name and GyroSensor name macro definition*/
#ifdef CONFIG_SENSOR_LSM330DLC
#define ACCEL_SENSOR_NAME"/sys/bus/i2c/drivers/lsm330dlc_acc/3-0019/"
#define GYRO_SENSOR_NAME "/sys/bus/i2c/drivers/lsm330dlc_gyr/3-006b/"  
#else
#define ACCEL_SENSOR_NAME "/sys/bus/i2c/drivers/lis331dlh/1-0018/"
#define GYRO_SENSOR_NAME "/sys/bus/i2c/drivers/l3g4200dh_i2c/1-0068/"
#endif
其中CONFIG_SENSOR_LSM330DLC這個宏開關我在相應的Android.mk裡作了如下定義:
# Xandy add macro define for accel and gyro sensors
ifeq ($(SENSOR_LSM330DLC), true)
LOCAL_CFLAGS += -DCONFIG_SENSOR_LSM330DLC
endif
而SENSOR_LSM330DLC則在相應工程(device目錄下對應你此時的vendor)的BoardConfig.mk裡作如下定義:
#Xandy add accel and gyro sensors
BOARD_HAS_SENSOR := true
SENSOR_LSM330DLC := true
這些其實都是宏定義及編譯開關設置的問題,這樣做的目的是方便不同工程(vendor)之間的切換及添加新的設備支持
GYR HAL的修改和ACC的一樣,這裡不多提了!
經過這些修改之後,用mm編譯相應的lib,並將lib通過adb push 到樣機的文件系統裡對應目錄下,重啟系統之後如果一切正常,現在進入到有UI旋轉的界面,就會起作用了,
但是,很有很可此時的旋轉方向和你運行的方向是不一致的,那麼你還得修改一下Sensor HAL中sensors.h裡面的如下宏:
#ifdef CONFIG_SENSOR_LSM330DLC
#define EVENT_TYPE_ACCEL_X          REL_X
#define EVENT_TYPE_ACCEL_Y          REL_Y
#define EVENT_TYPE_ACCEL_Z          REL_Z
#else
#error you must define ACCEL X Y Z
#endif


#ifdef CONFIG_SENSOR_LSM330DLC
#define EVENT_TYPE_GYRO_X           REL_X//REL_RX
#define EVENT_TYPE_GYRO_Y           REL_Y//REL_RY
#define EVENT_TYPE_GYRO_Z           REL_Z//REL_RZ
#else
#error you must define GYRO X Y Z
#endif
修改這些 x、y、z的定義,例如改成如下順利:
#ifdef CONFIG_SENSOR_LSM330DLC
#define EVENT_TYPE_GYRO_X           REL_Z
#define EVENT_TYPE_GYRO_Y           REL_X
#define EVENT_TYPE_GYRO_Z           REL_Y
#else
#error you must define GYRO X Y Z
#endif
具體順利怎樣,根據你的硬件擺放位置來定


至此sensor的調試就基本上完成了,如果還有什麼要修改的,那就是一些微調了,如靈敏度等

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved