i’m Watch code to read the accelerometer

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;

    }
};

3 thoughts on “i’m Watch code to read the accelerometer

  1. Thank you so much! This is what I want to know. đŸ™‚
    It’s really helpful article and you wrote very clear code.
    Again, thank you so much.

    BTW, what is the SeismoVector class?
    Do I need to declare like below in my code?

    class SeismoVector
    {
    long timeStamp;
    float x, y, z;
    }

    where I can find that class?
    cls = (*env)->FindClass(env, “ca/akkea/seismoimwatch/SeismoVector”);

  2. Hi Sungjae Hwang, Thanks for Angus providing the code. I used same code aswell but I am only getting 20 HZ. May be you can help me with this. I dont know how to use native code at all. could you please share your code. This is what I have done so far. My app is just simple to display accelerometer code. May be using your code I could figure out my mistake. This is what I have done so far. I wrote an app to display sensor values which display till 10 HZ. then in same app I copied native prototypes and constants to your android code out side on create method. created a class, class SeismoVector and package ca/akkea/seismoimwatch/SeismoVector. as yours
    {
    long timeStamp;
    float x, y, z;
    }
    then I copied public boolean openI2C() method and sensorTask class outside on create method but in my class.

    But it doesnt seem helping me.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.