Data from HTC Desire sensors

Introduction


Hi habrasobschestveto! I have long wanted to write an article about how one day I had to work with the data received from the sensors of HTC Desire, which is running Android.
image
The goal was: determining the movement of an object. That is, according to the data from the sensors, it was possible to obtain the values ​​of accelerations and times of these measurements. Further processing the data already calculate the speed, and then move.

Work with data


First, I had to tinker with the development environment for the android. Earlier, I had no programming experience in the middle of Eclipse in Java, I had to learn the basics. But in the end, an application was written that collected data in the SQLite database on a microSD card. Here are the first data that we managed to get:

This is a graph of the acceleration (Y axis) versus time (X axis), in this experiment, the phone was simply pushed on the table to slip. Then all kinds of tests went on, I wanted to check for example the saturation value of the sensors (the maximum measurable acceleration value). The phone moved in a circular path with gradual acceleration. The data graph below:

Saturation of the sensors occurred at a value of approximately 18.35 m / s ^ 2.
Then I wanted to try to process the received data already:

Here you can see an example of sliding the phone around the table: the blue line is the acceleration, the red line is the speed and the green line is the movement. This is not very successful, one of the first examples. Here the displacement was never determined.
Here is a more ideal example of such an experience:

Here, after processing the data, a plausible value was obtained for moving the phone around the table.
In the future, I wanted to see how the data would look when walking with the phone:

As well as when running with the phone:

On the example of walking and running, it is already clearly visible how various errors from sensors accumulate; for their further exclusion, a detailed study of the processes of obtaining all these data is required. In particular, there is data from only one X axis, there is no consideration of the effect on gravity acceleration sensors (rotation in the phone’s space is not taken into account). Here is an example in which this rotation, therefore, the influence of gravity was excluded from one of the axes:

in this experiment, the phone was on the table, and one of its sides rose to the ghost of the phone’s perpendicular position to the table. Here, the red line is the angle (obtained from the compass), the green is the value on the acceleration sensor (in fact, the value = acceleration + gravity), the violet is the acceleration value (adjusted for the angle values). That is, in this example, it was possible to exclude the influence of gravity.

Conclusion


This question is very interesting, and the given examples are just a small manifestation of my curiosity. As it turned out, the frequency of measurements from these sensors is not enough to obtain really high-quality data, but I think when it will be time to do a more detailed study of this issue.

UPD: I dug up all the same the source code of one of the program options, I ask you not to scold it very much only for acquaintance with Java for android:

package com.dimond.acc;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Timer;
import java.util.TimerTask;
import android.app.Activity;
import android.hardware.SensorListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.os.Environment;
import android.os.SystemClock;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.database.sqlite.SQLiteDatabase;

public class acc extends Activity implements SensorListener {

  public class AXYZTdata
  {
    float ax;
    float ay;
    float az;
    long time;    
    public AXYZTdata(float in_ax, float in_ay, float in_az, long in_time)
    {
      ax = in_ax;
      ay = in_ay;
      az = in_az;
      time = in_time;
    }
  }  
  SensorManager sm = null;
  final String tag = "logging";
  private EditText MassivN;
  TextView DataText;
  String TimeNowtmp;
  int N, sec, stroka=0;
  AXYZTdata[] mass = new AXYZTdata[10000];
  float acc_x, acc_y, acc_z, acc_time = 0;
  SQLiteDatabase mDatabase = SQLiteDatabase.openOrCreateDatabase("/mnt/sdcard/DB/"+String.valueOf(System.currentTimeMillis())+".db", null);
  int onoff=0;  
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    sm = (SensorManager) getSystemService(SENSOR_SERVICE);
    Button start = (Button) findViewById(R.id.Start);
    Button stop = (Button) findViewById(R.id.Stop);
    Button write = (Button) findViewById(R.id.Write);
    DataText = (TextView) findViewById(R.id.data);
    //строка создания баы данных
    String DATABASE_CREATE =
      "create table accdb" +
      "(_id integer primary key autoincrement, " +
           "acc_x text not null," +
           "acc_y text not null," +
           "acc_z text not null," +
           "time_h_m_s text not null);";    
    mDatabase.execSQL(DATABASE_CREATE);   
    //подпись на событие нажатия на Старт
    start.setOnClickListener(new OnClickListener() {
        public void onClick(View arg0)
          {
            startwrite();
          }
        });
    //подпись на событие нажатия на Стоп   
    stop.setOnClickListener(new OnClickListener() {
      public void onClick(View arg0)
          {
            stopwrite();
          }
        });
    //подпись на событие нажатия на Запись  
    write.setOnClickListener(new OnClickListener() {
      public void onClick(View arg0)
          {
            masstosql();
            DataText.setText("Writed!!!");
          }
        });    
  }
  

  public void startwrite()
  {
    onoff=1;
    return;
  }
  public void stopwrite()
  {
    onoff=0;
    DataText.setText(String.valueOf(stroka));
    return;
  }
  public void masstosql()
  {
    long StartTime = mass[0].time;
    for(int i=0; i     {
      mDatabase.execSQL(String.format("INSERT INTO accdb (acc_x, acc_y, acc_z, time_h_m_s) VALUES ('%s','%s','%s','%s');",
          mass[i].ax, mass[i].ay, mass[i].az, mass[i].time-StartTime));
    }
    return;
  }
  
  public void onSensorChanged(int sensor, float[] values) {
    synchronized (this) {
      Log.d(tag, "onSensorChanged: " + sensor + ", x: " + values[0] + ", y: " + values[1] + ", z: " + values[2]);
      if (sensor == SensorManager.SENSOR_ACCELEROMETER && onoff==1) {
        AXYZTdata tmp;
        tmp = new AXYZTdata(values[0], values[1],values[2], System.currentTimeMillis());
        mass[stroka] = tmp;
        stroka++;
      }      
    }
  }
  public void onAccuracyChanged(int sensor, int accuracy) {
    Log.d(tag,"onAccuracyChanged: " + sensor + ", accuracy: " + accuracy);
  }
  @Override
  protected void onResume() {
    super.onResume();
    sm.registerListener(this, SensorManager.SENSOR_ACCELEROMETER, SensorManager.SENSOR_DELAY_FASTEST);
  }
  
  @Override
  protected void onStop() {
    sm.unregisterListener(this);
    super.onStop();
  }  
  
  
}

* This source code was highlighted with Source Code Highlighter.


Who cares about the application project here .

Also popular now: