• gsensor架构和原理分析【转】


    本文转载自:http://blog.csdn.net/u012296694/article/details/48055491

    本文主要描述了在android2.3平台G-sensor相关软硬件的体系架构和实现原理,按照Applications、Framework、HAL、Driver和Hardware五大层次分别介绍。

    1.系统架构 (Architecture)

    1.1 Android体系架构图

     

    1.2 Sensor子系统架构图

     · Application Framework

           Sensor应用程序通过Sensor应用框架来获取sensor数据,应用框架层的Sensor Manager通过JNI与C++层进行通信。

     · Sensor Libraries

           Sensor中间层主要由Sensor Manager、Sensor service和Sensor硬件抽象层组成。

     · Input Subsystem

           通用的Linux输入框架专为与键盘、鼠标和触摸屏等输入设备而设计,并定义了一套标准事件集合。Sensor输入子系统采用采用了通用的Linux输入框架,它通过/sys/class/input节点和用户空间进行交互。

     · Event Dev

           Evdev提供了一种访问/dev/input/eventX输入设备事件的通用方法。

     · AccelerometerDriver

           此驱动通过SIRQ和I2C总线与MMA7660模组进行通信。SIRQ用来产生传感器事件中断。

    2 应用 (Applications)

    2.1 应用开发五步曲

    (1)   获取传感器管理器对象;

    mSensorManager =(SensorManager) getSystemService(SENSOR_SERVICE);

    (2)   获取传感器对象;

    mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);

    (3)  定义事件监听器;

    mEventListener =new SensorEventListener() {

    [java] view plaincopy
     
     
    1. @Override  
    2. publicvoid onSensorChanged(SensorEvent event) {  
    3.    float[] values = event.values;  
    4.    mTextView.setText("Accelerometer:" + values[0] +", "  
    5.           + values[1] +", " + values[2]);  
    6. }  
    7.   
    8. @Override  
    9. publicvoidonAccuracyChanged(Sensor sensor,int accuracy) {  
    10. }  

    (4)   注册事件监听器;

    protectedvoid onResume() {

    [java] view plaincopy
     
     
    1. super.onResume();  
    2.   
    3. mSensorManager.registerListener(mEventListener, mSensor,  
    4.        SensorManager.SENSOR_DELAY_NORMAL);  

    (5)   卸载事件监听器;

    protectedvoid onPause() {

    [java] view plaincopy
     
     
    1.    super.onPause();  
    2.     
    3.    mSensorManager.unregisterListener(mEventListener);  
    3 框架 (Framework)

    3.1 工作模型

     

    3.1.1 SensorManager的创建

     
    nativeClassInit(): 初始化Native类信息;
    sensors_module_init(): 创建Native SensorManager实例,从SensorService读取Sensor设备列表;
    sensors_module_get_next_sensor(): 从SensorService读取下一个Sensor设备;
     

    3.1.2 SensorThread数据接收处理

     
    sensors_create_queue(): 创建和SensorService共享的消息队列;
    sensors_data_poll(): 从消息队列中读取SensorService发过来的消息;
     

    3.1.3 SensorService的工作原理

     
    SensorDevice::poll(): 调用HAL接口读取数据;
    SensorEventConnection::sendEvents(): 往消息队列中写入消息,SensorThread后续会读取该消息;
     

    3.1.4 SensorDevice对HAL的访问

    4 硬件抽象层 (HAL)

    在linux操作系统中,应用同硬件之间的交互都是通过设备驱动来实现,Android系统为了降低应用开发人员开发难度,屏蔽硬件差异,定义出硬件抽象层,为开发人员提供获取各种设备相关的信息的接口。

    4.1 Sensors HAL关键流程

    4.1.1 打开Sensor设备

    SensorBase ::openInput() : 打开input子系统的sensor消息文件句柄;
    ioctl(EVIOCGABS(...)) : 获取ABS_X/ABS_Y/ABS_Z的加速度;
     

    4.1.2 轮循Sensor事件

    InputEventCircularReader::fill(): 调用read()从input子系统中读取事件放入环形缓冲区;
    InputEventCircularReader::readEvent(): 从环形缓冲区中读取事件;
    InputEventCircularReader::next(): 移动环形缓冲区当前指针;
     
    5.2 Sensors HAL关键数据结构

    5.2.1 sensors_module_t

    [cpp] view plaincopy
     
     
    1. struct sensors_module_t {  
    2.     struct hw_module_t common;  
    3.   
    4.     /** 
    5.      * Enumerate all available sensors. The list is returned in "list". 
    6.      * @return number of sensors in the list 
    7.      */  
    8.     int (*get_sensors_list)(struct sensors_module_t* module,  
    9.             struct sensor_t const** list);  
    10. };  

    hw_get_module()会加载HAL模块,并返回HAL入口数据结构(hw_module_t)。HAL_MODULE_INFO_SYM默认是“HAL”,在hw_get_module中用dlsym获取。
    [cpp] view plaincopy
     
     
    1. const struct sensors_module_t HAL_MODULE_INFO_SYM = {  
    2.     .common = {  
    3.         .tag = HARDWARE_MODULE_TAG,  
    4.         .version_major = 1,  
    5.         .version_minor = 0,  
    6.         .id = SENSORS_HARDWARE_MODULE_ID,  
    7.         .name = "MMA7660 Sensors Module",  
    8.         .author = "The Android Open Source Project",  
    9.         .methods = &sensors_module_methods,  
    10.     },  
    11.     .get_sensors_list = sensors__get_sensors_list  
    12. };  

    5.2.2 hw_module_methods_t
     static struct hw_module_methods_t sensors_module_methods = {
    [cpp] view plaincopy
     
     
    1. .open = open_sensors  

    5.2.3 sensors_poll_context_t

    [cpp] view plaincopy
     
     
    1. struct sensors_poll_context_t {  
    2.     struct sensors_poll_device_t device; // must be first  
    3.     sensors_poll_context_t();  
    4.     ~sensors_poll_context_t();  
    5.     int activate(int handle, int enabled);  
    6.     int setDelay(int handle, int64_t ns);  
    7.     int pollEvents(sensors_event_t* data, int count);  
    8.     int handleToDriver(int handle);  
    9. };  

    5.2.4 sensors_poll_device_t
     
    [cpp] view plaincopy
     
     
    1. struct sensors_poll_device_t {  
    2. struct hw_device_t common;  
    3.   
    4.     int (*activate)(struct sensors_poll_device_t *dev,  
    5.             int handle, int enabled);  
    6.   
    7.     int (*setDelay)(struct sensors_poll_device_t *dev,  
    8.             int handle, int64_t ns);  
    9.   
    10.     int (*poll)(struct sensors_poll_device_t *dev,  
    11.             sensors_event_t* data, int count);  
    12. };  

    5.2.5 sensor_t
    定义传感器的基本参数。
    [cpp] view plaincopy
     
     
    1. static const struct sensor_t sSensorList[] = {  
    2.         { "MMA7660 3-axis Accelerometer",  
    3.                 "Freescale Semiconductor",  
    4.                 1, SENSORS_HANDLE_BASE+ID_A,  
    5.                 SENSOR_TYPE_ACCELEROMETER, 3.0f*9.81f, (3.0f*9.81f)/64.0f, 0.35f, 0, { } },  
    6. };  
    [cpp] view plaincopy
     
     
    1. struct sensor_t {  
    2.     const char*     name;  
    3.     const char*     vendor;   
    4.     int             version;  
    5.     int             handle;  
    6.     int             type;  
    7.     float           maxRange;  
    8.     float           resolution;  
    9.     float           power;  
    10.     int32_t         minDelay;  
    11.     void*           reserved[8];  
    12. };  

    6 驱动 (driver)

    6.1 mma7660驱动框架

    mma7660与主机通信是通过I2C接口,因此mma7660驱动程序采用Linux系统的I2C子系统框架来实现,主要由3部分组成:
     
    (1) I2C核心
    I2C核心提供了I2C总线驱动和设备驱动的注册、注销方法,I2C通信方法(即“algorithm”)上层的、与具体适配器无关的代码以及探测设备、检测设备地址的上层代码等。这部分是与平台无关的。
    此部分在Linux内核的I2C驱动中实现,mma7660驱动使用其提供的功能接口来注册设备驱动。

    (2) I2C总线驱动
    I2C总线驱动是对I2C硬件体系结构中适配器端的实现。I2C总线驱动主要包含了I2C适配器数据结构i2c_adapter、I2C适配器的algorithm数据结构i2c_algorithm和控制I2C适配器产生通信信号的函数。经由I2C总线驱动的代码,我们可以控制I2C适配器以主控方式产生开始位、停止位、读写周期,以及以从设备方式被读写、产生ACK等。不同的CPU平台对应着不同的I2C总线驱动。
    此部分在Linux内核的I2C驱动中实现,mma7660驱动直接获取其提供的adapter,并调用I2C核心的接口来注册。

    (3) I2C设备驱动
    I2C设备驱动是对I2C硬件体系结构中设备端的实现。设备一般挂接在受CPU控制的I2C适配器上,通过I2C适配器与CPU交换数据。I2C设备驱动主要包含了数据结构i2c_driver和i2c_client,mma7660驱动需要实现其中的成员函数。
    在Linux内核源代码中的drivers目录下的i2c_dev.c文件,实现了I2C适配器设备文件的功能,应用程序通过“i2c-%d”文件名并使用文件操作接口open()、write()、read()、ioctl()和close()等来访问这个设备。应用层可以借用这些接口访问挂接在适配器上的I2C设备的存储空间或寄存器并控制I2C设备的工作方式。

    6.2 mma7660操作流程

    6.2.1 初始化

    6.2.2 探测设备

     

    6.2.3 移除设备

     

    6.2.4 采集数据

     

    6.2.5 睡眠和唤醒

    Suspend处理:关闭mma7660模组;
    Resume处理:使能mma7660模组;
     
    [cpp] view plaincopy
     
     
    1. static int mma7660_suspend(struct i2c_client *client, pm_message_t mesg)  
    2. {  
    3.     int result;  
    4. result = i2c_smbus_write_byte_data(client, MMA7660_MODE,   
    5.                                MK_MMA7660_MODE(0, 0, 0, 0, 0, 0, 0));  
    6.     assert(result==0);  
    7.     return result;  
    8. }  
    9.   
    10. static int mma7660_resume(struct i2c_client *client)  
    11. {  
    12.     int result;  
    13. result = i2c_smbus_write_byte_data(client, MMA7660_MODE,   
    14.                                 MK_MMA7660_MODE(0, 1, 0, 0, 0, 0, 1));  
    15.     assert(result==0);  
    16.     return result;  
    17. }  
    18.   
    19. static struct i2c_driver mma7660_driver = {  
    20.     .driver = {  
    21.         .name = MMA7660_DRV_NAME,  
    22.         .owner = THIS_MODULE,  
    23.     },  
    24.     .class = I2C_CLASS_HWMON,  
    25.     .suspend = mma7660_suspend,  
    26.     .resume = mma7660_resume,  
    27.     .probe = mma7660_probe,  
    28.     .detect = mma7660_detect,  
    29. //  .address_data = &addr_data,  
    30.     .remove = __devexit_p(mma7660_remove),  
    31.     .id_table = mma7660_id,  
    32. };  

    6.3 命令行调试

    6.3.1 sysfs调试接口

    (1) 定义sysfs attribute相关数据结构;
     
    [cpp] view plaincopy
     
     
    1. static SENSOR_DEVICE_ATTR(all_axis_force, S_IRUGO, show_xyz_force, NULL, 0);  
    2. static SENSOR_DEVICE_ATTR(x_axis_force, S_IRUGO, show_axis_force, NULL, 0);  
    3. static SENSOR_DEVICE_ATTR(y_axis_force, S_IRUGO, show_axis_force, NULL, 1);  
    4. static SENSOR_DEVICE_ATTR(z_axis_force, S_IRUGO, show_axis_force, NULL, 2);  
    5. static SENSOR_DEVICE_ATTR(orientation, S_IRUGO, show_orientation, NULL, 0);  
    6.   
    7. static struct attribute* mma7660_attrs[] =  
    8. {  
    9.     &sensor_dev_attr_all_axis_force.dev_attr.attr,  
    10.     &sensor_dev_attr_x_axis_force.dev_attr.attr,  
    11.     &sensor_dev_attr_y_axis_force.dev_attr.attr,  
    12.     &sensor_dev_attr_z_axis_force.dev_attr.attr,  
    13.     &sensor_dev_attr_orientation.dev_attr.attr,  
    14.     NULL  
    15. };  
    16.   
    17. static const struct attribute_group mma7660_group =  
    18. {  
    19.     .attrs = mma7660_attrs,  
    20. };  


    (2) 在probe函数中创建sysfs文件系统;
     
    [cpp] view plaincopy
     
     
    1. result = sysfs_create_group(&client->dev.kobj, &mma7660_group);  
    2. if (result != 0) {  
    3.     ERR("sysfs_create_group err ");  
    4.     goto exit_sysfs_creat_failed;  
    5. }  


    (3) 实现sysfs属性相关的读写函数;
    [cpp] view plaincopy
     
     
    1. ssize_t show_orientation(struct device *dev, struct device_attribute *attr, char *buf)  
    2. {  
    3.     int result;  
    4. u8 tilt, new_orientation;  
    5.   
    6.     mma7660_read_tilt(&tilt);  
    7.     DBG("tilt [0x%x] ", tilt);  
    8.     new_orientation = tilt & 0x1f;  
    9.     if (orientation!=new_orientation)  
    10.         orientation = new_orientation;  
    11.   
    12.     switch ((orientation>>2)&0x07) {  
    13.         case 1:  
    14.             result = sprintf(buf, "Left ");  
    15.             break;  
    16.         case 2:  
    17.             result = sprintf(buf, "Right ");  
    18.             break;  
    19.         case 5:  
    20.             result = sprintf(buf, "Downward ");  
    21.             break;  
    22.         case 6:  
    23.             result = sprintf(buf, "Upward ");  
    24.             break;  
    25.         default:  
    26.             switch(orientation & 0x03) {  
    27.                 case 1:  
    28.                     result = sprintf(buf, "Front ");  
    29.                     break;  
    30.                 case 2:  
    31.                     result = sprintf(buf, "Back ");  
    32.                     break;  
    33.                 default:  
    34.                     result = sprintf(buf, "Unknown ");  
    35.         }  
    36.     }  
    37.     return result;  
    38. }  
    [cpp] view plaincopy
     
     
    1. ssize_t show_xyz_force(struct device *dev, struct device_attribute *attr, char *buf)  
    2. {  
    3.     int i;  
    4.     s8 xyz[3];  
    5.   
    6.     for (i=0; i<3; i++)  
    7.         mma7660_read_xyz(i, &xyz[i]);  
    8.   
    9.     return sprintf(buf, "(%d,%d,%d) ", xyz[0], xyz[1], xyz[2]);  
    10. }  
    11.   
    12. ssize_t show_axis_force(struct device *dev, struct device_attribute *attr, char *buf)  
    13. {  
    14.     s8 force;  
    15.     int n = to_sensor_dev_attr(attr)->index;  
    16.   
    17. mma7660_read_xyz(n, &force);  
    18.   
    19.     return sprintf(buf, "%d ", force);  
    20. }  

     6.3.2 Gsensor调试实例
    [plain] view plaincopy
     
     
    1. /sys/devices/platform/gl5201-i2c.1/i2c-1/1-004c # ls  
    2. uevent  
    3. name  
    4. modalias  
    5. subsystem  
    6. power  
    7. driver  
    8. all_axis_force  
    9. x_axis_force  
    10. y_axis_force  
    11. z_axis_force  
    12. orientation  
    13. input  
    14. /sys/devices/platform/gl5201-i2c.1/i2c-1/1-004c # cat all_axis_force   
    15. (-1,0,22)  
     

    7 Hardware

    7.1 mma7660模组

    7.2 关键特性
    • Sampling Resolution: 6bit
    • Digital Output (I2C)
    • 3mm x 3mm x 0.9mm DFN Package
    • Low Power Current Consumption: 
        Off Mode: 0.4 μA,
        Standby Mode: 2 μA, 
        Active Mode: 47 μA at 1 ODR
    • Configurable Samples per Second from 1 to 120 samples
    • Low Voltage Operation:
        Analog Voltage: 2.4 V - 3.6 V
        Digital Voltage: 1.71 V - 3.6 V
    • Auto-Wake/Sleep Feature for Low Power Consumption
    • Tilt Orientation Detection for Portrait/Landscape Capability
    • Gesture Detection Including Shake Detection and Tap Detection

    7.2.1 功能模块图

    7.2.2 硬件连接图

    7.2.3 运动检测原理

    mma7660是一种电容式3轴g-sensor,其技术原理是在wafer的表面做出梳状结构,当产生动作时,由侦测电容差来判断变形量,反推出加速度的值。
    简单物理模型如下图:

    7.2.4 I2C读写时序

    7.2.5 工作状态机

    7.2.6 寄存器定义

    7.2.7 事件检测

    • 方向和摇动检测 
    • 轻拍或倾斜检测
     
  • 相关阅读:
    WinForm的Chart控件画条形图
    WinForm的Chart控件画折线图
    自定义控件
    左侧收缩菜单
    数组
    C#生成随机数的三种方法
    WinForm之GDI手动双缓冲技术
    WinForm之GDI画图步骤
    WinForm GDI编程:Graphics画布类
    翻译:《实用的Python编程》08_02_Logging
  • 原文地址:https://www.cnblogs.com/zzb-Dream-90Time/p/6489778.html
Copyright © 2020-2023  润新知