I figured out how to read and write the i2c bus on the imWatch so I can now sample at whatever rate I’d like. This tarball includes code that should work upto 200Hz without overloading the processor.
Faster rates should be possible but it would mean getting the FIFO in the accelerometer working and then backdating the samples.
Building the JNI
I’m not going to detail how to use a JNI within an Android project. there are plenty of other tutorials out there.
From the tarball put “akkea-jni.c” and “Android.mk” into the jni directory of your android >project. Then run
ndk-build
You should get output similar to below.
Compile thumb : akkea-jni <= akkea-jni.c SharedLibrary : libakkea-jni.so Install : libakkea-jni.so => libs/armeabi/libakkea-jni.so
Using the Accelerometer JNI code
Add these native prototypes and constants to your android code.
public native int readAccel( SeismoVector vector, int fd, long startTime ); public native int openI2c( String path ); public native void closeI2c( int fileHandle ); public native int i2cReadReg( int file, int addr, int reg); public native int i2cWriteReg( int file, int addr, int reg, int val); int i2cHandle; final byte ACCEL_I2C_ADDR = 25; final int ACCEL_RATE_OFF = 0; final int ACCEL_RATE_1HZ = 1 << 4; final int ACCEL_RATE_10HZ = 2 << 4; final int ACCEL_RATE_25HZ = 3 << 4; final int ACCEL_RATE_50HZ = 4 << 4; final int ACCEL_RATE_100HZ = 5 << 4; final int ACCEL_RATE_200HZ = 6 << 4; final int ACCEL_RATE_400HZ = 7 << 4; final int ACCEL_RATE_1_6KHZ = 8 << 4; final int ACCEL_RATE_5KHZ = 9 << 4;
The I2C bus and accelerometer need to be setup
public boolean openI2C() { try { Runtime.getRuntime().exec("chmod 777 /dev/i2c-0"); } catch (IOException e) { e.printStackTrace(); } i2cHandle = openI2c( "/dev/i2c-0" ); if( i2cHandle <= 0 ) return false; int[] arr = new int[4]; for( int i=0; i<128; i++ ) { arr[0] = i2cReadReg( i2cHandle, ACCEL_I2C_ADDR, i ); if( arr[0] != 0 ) Log.d(TAG, "Register " + String.valueOf( i ) + " = " + String.valueOf( arr[0] )); } int val; val = i2cReadReg( i2cHandle, ACCEL_I2C_ADDR, 0x20 ); val = ( val & 0x0F ); switch( HZ ) { case 1: val |= ACCEL_RATE_1HZ; break; case 10: val |= ACCEL_RATE_10HZ; break; case 25: val |= ACCEL_RATE_25HZ; break; case 100: val |= ACCEL_RATE_100HZ; break; case 200: val |= ACCEL_RATE_200HZ; break; case 400: val |= ACCEL_RATE_400HZ; break; case 1600: val |= ACCEL_RATE_1_6KHZ; break; } i2cWriteReg( i2cHandle, ACCEL_I2C_ADDR, 0x20, val ); val = i2cReadReg( i2cHandle, ACCEL_I2C_ADDR, 0x20 ); Log.d(TAG, "Register Rate " + String.valueOf( val )); return true; }
I then use a TimerTask to read the accelerometer at whatever rate I want.
class sensorTask extends TimerTask { @Override public void run() { long time; if( index >= totalSamples ) { Log.d(TAG, "index past end of array"); return; } SeismoVector vector = new SeismoVector(); time = readAccel( vector, i2cHandle, startTime ); if( startTime == 0 ) startTime = time; vectors[index++] = vector; } };