The hardware sensor used in a mobile device to find magnetic north usually
needs to be calibrated before it will provide accurate data. Use the Magnetic
North sensor channel (KSensrvChannelTypeIdMagneticNorthData
) to retrieve
the relation of the device to magnetic north. However, only the Magnetometer
sensor channel (KSensrvChannelTypeIdMagnetometerXYZAxisData
) maintains the
calibration level of the data in the property KSensrvPropCalibrationLevel
. This means you need
to open both channels, one for reading the data and the other for checking
the calibration.
CSensrvChannel::GetPropertyL()
.TInt iMagnetometerCalibrationLevel; CSensrvChannel* iMagnetometerSensor; CSensrvChannel* iMagneticNorthSensor; ... TSensrvProperty property; iMagnetometerSensor->GetPropertyL(KSensrvPropCalibrationLevel, KSensrvItemIndexNone, property); property.GetValue(iMagnetometerCalibrationLevel);The calibration level will be one of the following values:
The Magnetic North sensor is auto-calibrating, but first you need to enable
the auto calibration. Do this by setting the KSensrvPropAutoCalibrationActive
property of the
sensor.
iMagnetometerSensor->GetPropertyL(KSensrvPropAutoCalibrationActive, KSensrvItemIndexNone, property); property.SetValue(1); // set auto-calibration on. Note, do SetValue(0) to disable auto-calibration iMagnetometerSensor->SetProperty(property);
It takes some time to calibrate the Magnetic North sensor and, even after
being calibrated, it can become uncalibrated. So, for an application to be
sure the data coming from the Magnetic North sensor channel is accurate, you
must monitor changes in the calibration property and inform the user if something
needs to be done to recalibrate the sensor. Monitor the calibration property
by setting the property listener and implementing the MSensrvPropertyListener::PropertyChanged()
method.
... iMagnetometerSensor->SetPropertyListenerL(this); // where "this" is CMagneticNorthSensorChannelApp ...
void CMagneticNorthSensorChannelApp::PropertyChanged( CSensrvChannel& aChannel, const TSensrvProperty& aChangedProperty ) { TSensrvChannelInfo info = aChannel.GetChannelInfo(); if (info.iChannelType == KSensrvChannelTypeIdMagnetometerXYZAxisData) { if(aChangedProperty.GetPropertyId()==KSensrvPropCalibrationLevel) { aChangedProperty.GetValue(iMagnetometerCalibrationLevel); // Test iMagnetometerCalibrationLevel here to make sure it is still acceptable. If not, // then notify the UI. } } }
Your MSensrvDataListener::DataReceived()
implementation
should take note of the calibration level before using the data that has been
received. In the code example above, the calibration level is stored in the
instance variable iMagnetometerCalibrationLevel
so that it
is easily accessible from other parts of the application.
TInt iAngleFromMagneticNorth; TTime iAngleFromMagneticNorthTimeStamp; ... void CMagneticNorthSensorChannelApp::DataReceived(CSensrvChannel& aChannel, TInt /* aCount */, TInt /* aDataLost */) { TSensrvChannelInfo info = aChannel.GetChannelInfo(); if (info.iChannelType == KSensrvChannelTypeIdMagneticNorthData) { TSensrvMagneticNorthData magNorthData; TPckg<TSensrvMagneticNorthData> magNorthPackage(magNorthData); aChannel.GetData(magNorthPackage); if(iMagnetometerCalibrationLevel >= 2) { // Store the data iAngleFromMagneticNorth = magNorthData.iAngleFromMagneticNorth; iAngleFromMagneticNorthTimeStamp = magNorthData.iTimeStamp; // Inform owner about the new data // ... } else { // Don't use the data. // Maybe inform the owner that the sensor is uncalibrated and therefore inaccurate // ... } } }