I have been working on a small compass app the past couple of days, and have gotten the code up and running, but it seems that the compass reading is not accurate. After calibrating both phones, my first test that i found this in what that i simply held the phone against and flat surface looked at the reading then flipped it horizontally and put it against the same flat surface (a 180* turn) and the value did not change 180* it was closer to 240*.
I then tested the reading vs a compass, at times the reading seemed to be close but at other points it was more than 50* off. I even tried to put my phone and compass on the floor to keep the compasses away from any magnetic interference with the same results (note i also keep the compass and phone apart keeping them in the same direction by lining up with edges of a book).
I then put the sample application on another phone (first was nexus S, second was Motorola droid 1). Between the two phones the difference ranges from being equal at some points but at most points being between 50 and 15 degrees off.
I have looked through the documentation and also looked through many different forum posts and I do not see anyone with the same results. There may be some small error in my code that is causing my reading to come out incorrectly, or some documented bug that I am not seeing.
Any insight or suggestions would be greatly appreciated!!
Heres my on sensor changed code in my SensorEventListener class
public void onSensorChanged(SensorEvent event)
{
// If the sensor data is unreliable return
if (event.accuracy == SensorManager.SENSOR_STATUS_UNRELIABLE)
{
Toast.makeText(main.this, "Sensor Status Unreliable",Toast.LENGTH_SHORT).show();
}
// Gets the value of the sensor that has been changed
switch (event.sensor.getType())
{
case Sensor.TYPE_ACCELEROMETER:
m_vfgravity = event.values.clone();
break;
case Sensor.TYPE_MAGNETIC_FIELD:
m_vfgeomag = event.values.clone();
break;
}
if (m_vfgravity != null && m_vfgeomag != null)
{
if(SensorManager.getRotationMatrix(m_vfinR, m_vfI, m_vfgravity, m_vfgeomag))
{
SensorManager.getOrientation(m_vfinR, m_vforientVals);
m_fCompBearing = (float) Math.round((Math.toDegrees(m_vforientVals[0])) *2)/2;
//convert to 0-360 from -180-180
if(m_fCompBearing < 0.0)
{
m_fCompBearing = 360 + m_fCompBearing;
}
mCompHead.setText("" + (int)m_fCompBearing);
}
calcOffset();
rotateCmp();
}
}
And code in on create of my activity
mSMngr = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mSListener = new cSensorListener();
mSMngr.registerListener(mSListener,
mSMngr.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD),
SensorManager.SENSOR_DELAY_UI);
mSMngr.registerListener(mSListener,
mSMngr.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_UI);
Thanks in advance!
Edit: also tried it with the droid X with the worst results yet... When the phone is rolled around 45 degrees (rotated around z axis a computer coordinate system) the compass heading returned can change over 180 degrees, in fact the heading value goes in the opposite direction of the other phones when spun in the same direction. This is the only phone that produces this result even after calibrating in the settings. Also their is a compass live wallpaper i test against that doesnt have the same issue. So I would assume there would be something i can do in software to avoid this.