Android2.3.4陀螺仪移植

来源:互联网 发布:excel数据拟合曲线 编辑:程序博客网 时间:2024/05/16 17:22

一 背景

1.需求

   陀螺仪硬件并非接在android cpu上,所以不存在陀螺仪驱动,而陀螺仪数据是通过用户空间的一个c程序传过来。

2.思路

   修改陀螺仪hal层,在hal层构建socket客户端,在数据源的c程序上构建socket服务端。一旦有数据,c程序通过socket发送数据到陀螺仪hal层,并上报。


二 步骤

1.把device/samsung/crespo/libsensors目录拷贝到hardware/libhardware/modules目录下

2.修改sensors.cpp文件下的传感器数组定义。

因只用到陀螺仪传感器,把其他传感器定义删掉

[cpp] view plaincopy
  1. static const struct sensor_t sSensorList[] = {  
  2. /* 
  3.         { "KR3DM 3-axis Accelerometer", 
  4.           "STMicroelectronics", 
  5.           1, SENSORS_ACCELERATION_HANDLE, 
  6.           SENSOR_TYPE_ACCELEROMETER, RANGE_A, CONVERT_A, 0.23f, 20000, { } }, 
  7.         { "AK8973 3-axis Magnetic field sensor", 
  8.           "Asahi Kasei Microdevices", 
  9.           1, SENSORS_MAGNETIC_FIELD_HANDLE, 
  10.           SENSOR_TYPE_MAGNETIC_FIELD, 2000.0f, CONVERT_M, 6.8f, 16667, { } }, 
  11.         { "AK8973 Orientation sensor", 
  12.           "Asahi Kasei Microdevices", 
  13.           1, SENSORS_ORIENTATION_HANDLE, 
  14.           SENSOR_TYPE_ORIENTATION, 360.0f, CONVERT_O, 7.8f, 16667, { } }, 
  15.         { "GP2A Light sensor", 
  16.           "Sharp", 
  17.           1, SENSORS_LIGHT_HANDLE, 
  18.           SENSOR_TYPE_LIGHT, 3000.0f, 1.0f, 0.75f, 0, { } }, 
  19.         { "GP2A Proximity sensor", 
  20.           "Sharp", 
  21.           1, SENSORS_PROXIMITY_HANDLE, 
  22.           SENSOR_TYPE_PROXIMITY, 5.0f, 5.0f, 0.75f, 0, { } }, 
  23. */  
  24.         { "K3G Gyroscope sensor",  
  25.           "STMicroelectronics",  
  26.           1, SENSORS_GYROSCOPE_HANDLE,  
  27.           SENSOR_TYPE_GYROSCOPE, RANGE_GYRO, CONVERT_GYRO, 6.1f, 1190, { } },  
  28. };  



3.修改sensors.cpp的sensors_poll_context_t结构体,删除其他的传感器定义

[cpp] view plaincopy
  1. struct sensors_poll_context_t {  
  2.     struct sensors_poll_device_t device; // must be first  
  3.   
  4.         sensors_poll_context_t();  
  5.         ~sensors_poll_context_t();  
  6.     int activate(int handle, int enabled);  
  7.     int setDelay(int handle, int64_t ns);  
  8.     int pollEvents(sensors_event_t* data, int count);  
  9.   
  10. private:  
  11.     enum {  
  12.         //light           = 0,  
  13.         //proximity       = 1,  
  14.         //akm             = 2,  
  15.         //gyro            = 3,  
  16.         gyro        = 0,  
  17.         numSensorDrivers,  
  18.         numFds,  
  19.     };  
  20.   
  21.     static const size_t wake = numFds - 1; //wake = 1  
  22.     static const char WAKE_MESSAGE = 'W';  
  23.     struct pollfd mPollFds[numFds];//2  
  24.     int mWritePipeFd;  
  25.     SensorBase* mSensors[numSensorDrivers];// 2  
  26.   
  27.     int handleToDriver(int handle) const {  
  28.         switch (handle) {  
  29.             /* 
  30.             case ID_A: 
  31.             case ID_M: 
  32.             case ID_O: 
  33.                 return akm; 
  34.             case ID_P: 
  35.                 return proximity; 
  36.             case ID_L: 
  37.                 return light; 
  38.             */  
  39.             case ID_GY:  
  40.                 return gyro;  
  41.         }  
  42.         return -EINVAL;  
  43.     }  
  44. };  


包括构造函数:

[cpp] view plaincopy
  1. sensors_poll_context_t::sensors_poll_context_t()  
  2. {  
  3. /* 
  4.     mSensors[light] = new LightSensor(); 
  5.     mPollFds[light].fd = mSensors[light]->getFd(); 
  6.     mPollFds[light].events = POLLIN; 
  7.     mPollFds[light].revents = 0; 
  8.  
  9.     mSensors[proximity] = new ProximitySensor(); 
  10.     mPollFds[proximity].fd = mSensors[proximity]->getFd(); 
  11.     mPollFds[proximity].events = POLLIN; 
  12.     mPollFds[proximity].revents = 0; 
  13.  
  14.     mSensors[akm] = new AkmSensor(); 
  15.     mPollFds[akm].fd = mSensors[akm]->getFd(); 
  16.     mPollFds[akm].events = POLLIN; 
  17.     mPollFds[akm].revents = 0; 
  18.  
  19. */  
  20.     //LOGD("sensors_poll_context_t");  
  21.     mSensors[gyro] = new GyroSensor();  
  22.     mPollFds[gyro].fd = mSensors[gyro]->getFd();  
  23.     mPollFds[gyro].events = POLLIN;  
  24.     mPollFds[gyro].revents = 0;  
  25.   
  26.     int wakeFds[2];  
  27.     int result = pipe(wakeFds);  
  28.     LOGE_IF(result<0, "error creating wake pipe (%s)", strerror(errno));  
  29.     fcntl(wakeFds[0], F_SETFL, O_NONBLOCK);  
  30.     fcntl(wakeFds[1], F_SETFL, O_NONBLOCK);  
  31.     mWritePipeFd = wakeFds[1];  
  32.   
  33.     //wake equals 1  
  34.     mPollFds[wake].fd = wakeFds[0];//store the reading fd of the pipe  
  35.     mPollFds[wake].events = POLLIN;  
  36.     mPollFds[wake].revents = 0;  
  37. }  




3.修改GyroSensor.cpp的getFd()函数,把原来的返回gyro设备驱动的文件描述符,改为返回socket的文件描述符。

[cpp] view plaincopy
  1.  int GyroSensor::getFd()  
  2. {  
  3.     if(mSocketFd == -1){  
  4.         socket_connect();  
  5.     }  
  6.   
  7.     return mSocketFd;  
  8. }  



其中,mSocketFd是在GyroSensor.h中新定义的socket文件描述符,socket_connect()函数实现连接socket服务端。

我们回过头看sensors.cpp文件的sensors_poll_context_t构造函数:

[cpp] view plaincopy
  1. mSensors[gyro] = new GyroSensor();  
  2.     mPollFds[gyro].fd = mSensors[gyro]->getFd();  
  3.     mPollFds[gyro].events = POLLIN;  
  4.     mPollFds[gyro].revents = 0;  



这里初始化gyro类后,通过getFd()获取socket文件描述符,然后就可以通过poll函数对文件描述符进行读取数据,poll的读取在sensors_poll_context_t::pollEvents函数中,代码都不用改变,像这样:


[cpp] view plaincopy
  1. int sensors_poll_context_t::pollEvents(sensors_event_t* data, int count)  
  2. {  
  3.     //what does parameter count mean ? fuck   
  4.     int nbEvents = 0;  
  5.     int n = 0;  
  6.     //LOGD("sensors_poll_context_t::pollEvents");  
  7.     //LOGD("count=%d",count);  
  8.   
  9.     do {  
  10.         // see if we have some leftover from the last poll()  
  11.         for (int i=0 ; count && i<numSensorDrivers ; i++) {  
  12.             SensorBase* const sensor(mSensors[i]);  
  13.             if ((mPollFds[i].revents & POLLIN) || (sensor->hasPendingEvents())) {  
  14.                 int nb = sensor->readEvents(data, count);  
  15.                 if (nb < count) {  
  16.                     // no more data for this sensor  
  17.                     mPollFds[i].revents = 0;  
  18.                 }  
  19.                 count -= nb;  
  20.                 nbEvents += nb;  
  21.                 data += nb;  
  22.             }  
  23.         }  
  24.   
  25.         if (count) {  
  26.             // we still have some room, so try to see if we can get  
  27.             // some events immediately or just wait if we don't have  
  28.             // anything to return  
  29.             n = poll(mPollFds, numFds, nbEvents ? 0 : -1);  
  30.             if (n<0) {  
  31.                 LOGE("poll() failed (%s)", strerror(errno));  
  32.                 return -errno;  
  33.             }  
  34.             //read data from pipe  
  35.             if (mPollFds[wake].revents & POLLIN) {  
  36.                 char msg;  
  37.                 int result = read(mPollFds[wake].fd, &msg, 1);  
  38.                 LOGE_IF(result<0, "error reading from wake pipe (%s)", strerror(errno));  
  39.                 LOGE_IF(msg != WAKE_MESSAGE, "unknown message on wake queue (0x%02x)"int(msg));  
  40.                 mPollFds[wake].revents = 0;  
  41.             }  
  42.         }  
  43.         // if we have events and space, go read them  
  44.     } while (n && count);  
  45.   
  46.       
  47.   
  48.     return nbEvents;  
  49. }  



4.修改gyro类的构造函数,把与设备驱动相关的那一段代码删除:


[cpp] view plaincopy
  1. GyroSensor::GyroSensor()  
  2.     : SensorBase(NULL, "gyro"),  
  3.       mEnabled(0),  
  4.       mInputReader(4),  
  5.       mHasPendingEvent(false),  
  6.       mEnabledTime(0),  
  7.       mSocketFd(-1)  
  8. {  
  9.     //LOGD("GyroSensor::GyroSensor");  
  10.     mPendingEvent.version = sizeof(sensors_event_t);  
  11.     mPendingEvent.sensor = ID_GY;  
  12.     mPendingEvent.type = SENSOR_TYPE_GYROSCOPE;  
  13.     memset(mPendingEvent.data, 0, sizeof(mPendingEvent.data));  
  14.   
  15.   
  16.     /* 
  17.     if (data_fd) { 
  18.         strcpy(input_sysfs_path, "/sys/class/input/"); 
  19.         strcat(input_sysfs_path, input_name); 
  20.         strcat(input_sysfs_path, "/device/"); 
  21.         input_sysfs_path_len = strlen(input_sysfs_path); 
  22.         enable(0, 1); 
  23.     } 
  24.  
  25.     */  
  26. }  


5.修改gyro类的其他成员函数,包括setDelay,enable,setInitialState等函数里面的代码去全部删除:

[cpp] view plaincopy
  1. int GyroSensor::setInitialState() {  
  2.   
  3.     /* 
  4.     struct input_absinfo absinfo_x; 
  5.     struct input_absinfo absinfo_y; 
  6.     struct input_absinfo absinfo_z; 
  7.     float value; 
  8.     if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_GYRO_X), &absinfo_x) && 
  9.         !ioctl(data_fd, EVIOCGABS(EVENT_TYPE_GYRO_X), &absinfo_y) && 
  10.         !ioctl(data_fd, EVIOCGABS(EVENT_TYPE_GYRO_X), &absinfo_z)) { 
  11.         value = absinfo_x.value; 
  12.         mPendingEvent.data[0] = value * CONVERT_GYRO_X; 
  13.         value = absinfo_x.value; 
  14.         mPendingEvent.data[1] = value * CONVERT_GYRO_Y; 
  15.         value = absinfo_x.value; 
  16.         mPendingEvent.data[2] = value * CONVERT_GYRO_Z; 
  17.         mHasPendingEvent = true; 
  18.     } 
  19.  
  20.      
  21.     */  
  22.   
  23.     //LOGD("GyroSensor::setInitialState");  
  24.     return 0;  
  25. }  





[cpp] view plaincopy
  1. int GyroSensor::enable(int32_t, int en) {  
  2.     /* 
  3.     int flags = en ? 1 : 0; 
  4.     if (flags != mEnabled) { 
  5.         int fd; 
  6.         strcpy(&input_sysfs_path[input_sysfs_path_len], "enable"); 
  7.         fd = open(input_sysfs_path, O_RDWR); 
  8.         if (fd >= 0) { 
  9.             char buf[2]; 
  10.             int err; 
  11.             buf[1] = 0; 
  12.             if (flags) { 
  13.                 buf[0] = '1'; 
  14.                 mEnabledTime = getTimestamp() + IGNORE_EVENT_TIME; 
  15.             } else { 
  16.                 buf[0] = '0'; 
  17.             } 
  18.             err = write(fd, buf, sizeof(buf)); 
  19.             close(fd); 
  20.             mEnabled = flags; 
  21.             setInitialState(); 
  22.             return 0; 
  23.         } 
  24.         return -1; 
  25.     } 
  26.     */  
  27.   
  28.     //LOGD("GyroSensor::enable");  
  29.     return 0;  
  30. }  

[cpp] view plaincopy
  1. int GyroSensor::setDelay(int32_t handle, int64_t delay_ns)  
  2. {  
  3. /* 
  4.     int fd; 
  5.     strcpy(&input_sysfs_path[input_sysfs_path_len], "poll_delay"); 
  6.     fd = open(input_sysfs_path, O_RDWR); 
  7.     if (fd >= 0) { 
  8.         char buf[80]; 
  9.         sprintf(buf, "%lld", delay_ns); 
  10.         write(fd, buf, strlen(buf)+1); 
  11.         close(fd); 
  12.         return 0; 
  13.     } 
  14.     return -1; 
  15. */  
  16.     //LOGD("GyroSensor::setDelay");  
  17.     return 0;  
  18.       
  19. }  

6.修改gyro类的readEvents函数,这个函数是最重要的函数,要从socket中读取gyro数据:

[cpp] view plaincopy
  1. float value = 0;  
  2.     char buf[2];  
  3.     int nread = 0;  
  4.   
  5.     nread = read(mSocketFd, buf, 2);  
  6.     if(nread <= 0){  
  7.         LOGE("GyroSensor::readEvents read error.");  
  8.         return 0;  
  9.     }  
  10.       
  11.     float value = (float)((buf[0] << 8) + buf[1]);  
  12.     //LOGD("gyro_msg_handle, value=%f",value);  
  13.     value *= CONVERT_GYRO_X;  
  14.   
  15.       
  16.     mPendingEvent.data[0] = value;  
  17.     mPendingEvent.data[1] = value;  
  18.     mPendingEvent.data[2] = value;  
  19.   
  20.     *data = *mPendingEvent;  
  21.   
  22.     return 1;  


sokcet服务端每次发送2个字节数据,因是单轴陀螺仪,所以只有1个数据,把mPendingEvent的data数据3个字节都填充同一数据,然后赋值给*data,最后返回1,表述读到1个数据。


7.修改libsensors下的Android.mk文件的:


[cpp] view plaincopy
  1. LOCAL_MODULE := sensors.default  


8.编译后,生成sensors.default.so文件到lib/hw目录,把hw目录下其他有sensors文字的so文件删除,只留sensors.default.so文件,然后就可以在模拟器或设备上进行测试了,App层的Java测试程序如下:


[java] view plaincopy
  1. package com.hase.ng102.sensors;  
  2.   
  3. import android.R.string;  
  4. import android.app.Activity;  
  5. import android.content.Context;  
  6. import android.hardware.Sensor;  
  7. import android.hardware.SensorEvent;  
  8. import android.hardware.SensorEventListener;  
  9. import android.hardware.SensorManager;  
  10. import android.os.Bundle;  
  11. import android.util.Log;  
  12. import android.widget.TextView;  
  13.   
  14. public class SensorDemoActivity extends Activity {  
  15.     //设置LOG标签  
  16.     private static final String TAG = "sensors";  
  17.     private  SensorManager sm;  
  18.     private TextView tv1;  
  19.       
  20.     /** Called when the activity is first created. */  
  21.     @Override  
  22.     public void onCreate(Bundle savedInstanceState) {  
  23.         super.onCreate(savedInstanceState);  
  24.         setContentView(R.layout.main);  
  25.           
  26.         tv1 = (TextView)this.findViewById(R.id.tv1);   
  27.         sm = (SensorManager)getSystemService(Context.SENSOR_SERVICE);  
  28.         Log.d(String.format("getSystemService %s", sm == null ? "sucess":"fail"), TAG);  
  29.         int sensorType = Sensor.TYPE_GYROSCOPE;  
  30.         sm.registerListener(myAccelerometerListener,sm.getDefaultSensor(sensorType),SensorManager.SENSOR_DELAY_NORMAL);  
  31.     }  
  32.       
  33.     /* 
  34.      * SensorEventListener接口的实现,需要实现两个方法 
  35.      * 方法1 onSensorChanged 当数据变化的时候被触发调用 
  36.      * 方法2 onAccuracyChanged 当获得数据的精度发生变化的时候被调用,比如突然无法获得数据时 
  37.      * */  
  38.     final SensorEventListener myAccelerometerListener = new SensorEventListener(){  
  39.           
  40.         //复写onSensorChanged方法//  
  41.         public void onSensorChanged(SensorEvent sensorEvent){  
  42.             if(sensorEvent.sensor.getType() == Sensor.TYPE_GYROSCOPE){  
  43.                 Log.i(TAG,"onSensorChanged");  
  44.                   
  45.                 //图解中已经解释三个值的含义  
  46.                 float x = sensorEvent.values[0];  
  47.                 float y = sensorEvent.values[1];  
  48.                 float z = sensorEvent.values[2];  
  49.                   
  50.                 String msg = String.format("x=%f\n y=%f\n z=%f\n",x,y,z);  
  51.                 tv1.setText(msg);  
  52.                 Log.i(TAG, msg);  
  53.             }  
  54.             else {  
  55.                 String msg = "other sensors data changed";  
  56.                 tv1.setText(msg);  
  57.                 Log.i(TAG, msg);  
  58.             }  
  59.         }  
  60.         //复写onAccuracyChanged方法  
  61.         public void onAccuracyChanged(Sensor sensor , int accuracy){  
  62.             Log.i(TAG, "onAccuracyChanged");  
  63.         }  
  64.     };  
  65.       
  66.     public void onPause(){  
  67.         /* 
  68.          * 很关键的部分:注意,说明文档中提到,即使activity不可见的时候,感应器依然会继续的工作,测试的时候可以发现,没有正常的刷新频率 
  69.          * 也会非常高,所以一定要在onPause方法中关闭触发器,否则讲耗费用户大量电量,很不负责。 
  70.          * */  
  71.         sm.unregisterListener(myAccelerometerListener);  
  72.         super.onPause();  
  73.     }  
  74.       
  75.       
  76.       
  77. }  



原创粉丝点击