Search This Blog

Sunday, June 17, 2012

Telemetry logger android app


In order to make some augmented reality apps, and some other cool robot and telemetry apps, I decided to make a small app that reads out all the accelerometer, gyroscope, compass, etc sensors and logs the values to the SD card.   From there I can analyze the data and see what sort of performance to expect.

Here are some links with information I found,
http://www.sensorplatforms.com/native-sampling
http://www.sensorplatforms.com/smartphone-performance-fundamentals-sensor-sampling
http://developer.android.com/reference/android/hardware/SensorManager.html

Hard to tell what are real sensors and what are virtual.  this was the best article I found on what is actually in the phone.
http://www.mobiledevmag.com/2011/07/using-available-sensors-in-the-android-platform-current-limitations-and-expected-improvements%E2%80%A8/

Here is how to dump the sensors on the phone


SensorManager myManager = (SensorManager)getSystemService(SENSOR_SERVICE);
        List<Sensor> sensorList = myManager.getSensorList(Sensor.TYPE_ALL);
        StringBuilder sensorString = new StringBuilder("");
        for(int i=0; i<sensorList.size(); i++) {
            sensorString.append("Type: "+sensorList.get(i).getType()).append(" ---------\n");
            sensorString.append(sensorList.get(i).getVendor()).append("\n");
            sensorString.append(sensorList.get(i).getName()).append("\nResolution: ");
            sensorString.append(sensorList.get(i).getResolution() ).append("\n");
        }


That gives me this data on my motorola droid 2 global


SiFish Android Sensor Log
Android Sensors Found:
Type: 1 ---------
Kionix
KXTF9 3-axis Accelerometer
Resolution: 0.009810001
Type: 2 ---------
Asahi Kasei
AK8975 3-axis Magnetic field sensor
Resolution: 0.0625
Type: 8 ---------
Intersil
ISL29030 Proximity sensor
Resolution: 100.0
Type: 3 ---------
Asahi Kasei
AK8975 Orientation sensor
Resolution: 0.015625
Type: 5 ---------
Intersil
ISL29030 Light sensor
Resolution: 1.0
Type: 9 ---------
Google Inc.
Gravity Sensor
Resolution: 0.009810001
Type: 10 ---------
Google Inc.
Linear Acceleration Sensor
Resolution: 0.009810001
Type: 11 ---------
Google Inc.
Rotation Vector Sensor
Resolution: 5.9604645E-8

The key code is pretty simple to access the sensors.  This may not be the most efficient or fastest code yet, it is my starting point

In your onCreate do this:


mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);       mSensorManager.registerListener(mSensorListener1, mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_FASTEST);  
private final SensorEventListener mSensorListener1 = new SensorEventListener() {
   public void onSensorChanged(SensorEvent se) {
     text1.setText(se.sensor.getName());      Ax = se.values[0];      Ay = se.values[1];      Az = se.values[2];      long timestamp = se.timestamp;      aXProgress.setProgress((int) Ax + 50);      aYProgress.setProgress((int) Ay + 50);      aZProgress.setProgress((int) Az + 50);
                            if (sdcard.sd_ok & logging) {     sdlog(timestamp);     }    }
 public void onAccuracyChanged(Sensor sensor, int accuracy) {  }};



Writing to the SD card turned out to be more work than I thought.  It really is pretty easy, but I got hung up on a couple things.
  • AndroidManifest.xml has to have this line in it, or it will not throw errors, it just won't work.     android:name="android.permission.WRITE_EXTERNAL_STORAGE"
  • File names should avoid  "." and ":"    I was trying to time stamp the file names and put in a ":".  Failed.
  • When the phone is plugged into the PC, the SD card is shared and you can't write to it.  You have to load your app, then unplug, and run it again to make it work.
  • I used buffered stream to keep the app from waiting for the SD card, but if you don't do a flush() it doesn't write until the buffer is full.
  • If you get exceptions like "Permission Denied"  you have to collect them and find a way to view them or display them back to the user


This is the class I wrote to handle the SD card communication


public class SDcard { File sdCard = Environment.getExternalStorageDirectory(); File dir = new File (sdCard.getAbsolutePath() + "/sifish"); File destinationFile; BufferedOutputStream buffer; public String messages; public boolean sd_ok = false; public boolean checkSD() { sd_ok = false; messages = "SD card is ".concat(Environment.getExternalStorageState()).concat("\n"); if (Environment.getExternalStorageState().equalsIgnoreCase("mounted")) { sd_ok = true; } return sd_ok; } public boolean openSDFile(String filename) { boolean success = true; //messages = "SD card is ".concat(Environment.getExternalStorageState()).concat("\n"); sdCard = Environment.getExternalStorageDirectory(); dir = new File (sdCard.getAbsolutePath() + "/sifish");  dir.mkdirs(); success = dir.canWrite(); sd_ok = success; if (!success) { messages = messages.concat("Error - Can't write to "+dir.getAbsolutePath()+" directory on SD card\n"); sd_ok=false; }
try { destinationFile = new File(dir, filename.concat((String) android.text.format.DateFormat.format("_yyyyMMdd_hhmmss", new java.util.Date())).concat(".csv")); buffer = new BufferedOutputStream(new FileOutputStream(destinationFile)); messages = messages.concat("Opened "+destinationFile.getName()+"\n"); } catch (Exception e) {   messages = messages.concat("Error - Can't open file "+destinationFile.getName()+" on SD card\n");   //messages = messages.concat(e.getMessage());   messages = messages.concat(e.toString()).concat("\n");   success = false;   sd_ok = false; } return success; } public boolean closeSDFile() { boolean success = true; try { buffer.flush(); //buffer.close(); } catch (Exception e) {   messages = messages.concat("Error - Can't close file on SD card\n");   messages = messages.concat(e.toString()).concat("\n");   //messages = messages.concat(e.getMessage());   success = false; } sd_ok = false; return success;
//destinationFile.close(); } public boolean writeSDFile(String data) { boolean success = true; try { //byte[] dataByte = Base64.decode(data, Base64.DEFAULT); char[] dataChar = data.toCharArray(); for (int i=0; i<data.length(); i++) { buffer.write(dataChar[i]);   } //buffer.flush();   //doesn't write until buffer is flushed } catch (Exception e) { messages = messages.concat("Error - Can't write to SD card file "); messages = messages.concat(e.toString()).concat("\n"); success = false; sd_ok = false; } return success; } public void dirSD() { sdCard.listFiles(); }

I'm going to clean this up and publish it to android market, but meanwhile I posted the apk file to my download page.   The data is saved to your sdcard when you run a log, under the "sifish" directory.  It creates a csv file with all the data from all the sensors on the phone.

The screenshots from the emulator don't do it justice, since the emulator has no sensors and no data shows up.




Just surf your android phone to this page:
http://code.google.com/p/arduino-java-xyzcnc/downloads/list

and download
AccelerationLogger.apk

Then look on your SD card for the output files.








No comments:

Post a Comment