The akmd daemon in the HTC phones is responsible for controlling the compass and the accelerometer (if it is seperate). The daemon is loaded as a child process of "init" during startup. (That is the reason why it cannot be killed without killing the init first.) Once it is loaded, it performs the following tasks:
- Reads data from the sensors via ioctl (no interrupt is used in the kernel and no polling is used in the user space)
- Calibrates them
- Sends the calibrated data to the akm89XX driver which generates an input event for the framework. (framework polls these input events)
The android framework only polls the input node (/dev/input/event4) to get the sensor data. Therefore, framework does not have any access to the real/raw sensor data other than provided by the daemon.
The original akmd daemon is a closed source program. Basically, on an android phone users does not have any control on the sensors.
This open source version of the akmd can be used instead of the original daemon to get the complete control on the accelerometers and the compass. As the sensor structure of the android framework is very limited, such a direct control of sensors is quite essential to develop inertial algorithms (e.g. Motion controllers) for android phones.
Development Notes:- This open version (akmf) has exactly the same ioctl footprint with the original version. (can be checked with strace)
- The akm compass has a saturation problem. To eliminate this problem both the akmd (original daemon) and akmf (open source version) utilize an automatic DAC offset adjustment at the beginning. However, such an adjustment introduces a huge random bias in body frame. This random bias must be later estimated and removed by the daemon itself.
- For automatic removal of the bias I implemented a self calibration method for the compass based on a circle fit algorithm. However, the results that I obtained with this automatic calibration are not satisfactory. Anyone who has more experience on compasses than me had better revise that part of the daemon.
- Another way of dealing with this saturation problem could be to use smaller gain values than the ones stored in the eeprom of compass (which is claimed to be computed in the factory). Such an approach would definitely simply the internal calibration problem. However, using a smaller gain might also decrease the SNR of the output. A further laboratory test is necessary to determine the akm error characteristics under different gains. If the effect of the gain on SNR is negligible, then adjusting gains rather than the DAC offset should be preferred.
- I originally developed this code to use calibration matrices provided externally. When the daemon can open the external calibration parameter files (check the code for their names and locations), it uses those parameters directly without ever calling the internal calibration algorithm. Therefore, an android application which can be used to calibrate the sensors (such as the bubble application for accelerometers and a planar rotation method for compass) and write these computed calibration parameters to the files can be quite useful.
- The thread structure of akmf is a little different from the original version. Akmd waits for the suspension and resume in the main thread and uses a second thread for the data measuring. However, I implemented the data measurement in the main thread and used the second thread for the suspension/resume control.
- I wrote and tested this daemon for the HTC - Hero. However, all HTC models that I had seen before use a similar daemon architecture. Therefore, it is quite easy to modify this daemon for other HTC models. (For instance, in htc magic, akm8976 is used which contains both accelerometer and compass together. Therefore, to port this daemon for the magic, it is sufficient to just remove the bma150 control statements and use the accelerometer data provided by the akm via ioctl.)
- Akmd uses signals to restart itself when anything unexpeced happens. For now, I did not implement the signal handlers.