4
votes

I am trying to get the magnetic field data from my iphone 6 by using CoreMotion.

I had no problems accessing the raw data with the following code:

if available {
        motionMangager.magnetometerUpdateInterval = updateInterval
        motionMangager.startMagnetometerUpdatesToQueue(queue, withHandler: {
            (data, error: NSError!) -> Void in
            println("x: \(data.magneticField.x), y: \(data.magneticField.y), z: \(data.magneticField.z)")
        })
    }

BUT: I need the derived data by using an device motion instance.

So I did the following:

if motionMangager.deviceMotionAvailable {
        motionMangager.magnetometerUpdateInterval = updateInterval
        motionMangager.startDeviceMotionUpdatesUsingReferenceFrame(CMAttitudeReferenceFrameXArbitraryZVertical, toQueue: queue, withHandler: {
            (deviceMotion: CMDeviceMotion!, error: NSError!) -> Void in
            // If no device-motion data is available, the value of this property is nil.
            if let motion = deviceMotion {
                println(motion)
                var accuracy = motion.magneticField.accuracy
                var x = motion.magneticField.field.x
                var y = motion.magneticField.field.y
                var z = motion.magneticField.field.z
                println("accuracy: \(accuracy.value), x: \(x), y: \(y), z: \(z)")
            }
            else {
                println("Device motion is nil.")
            }
        })
    }

And here is the problem:

I am always getting zero for the field coordinates x, y and z. The accuracy as well is -1. According to the Apple Documentation an accuracy of -1 means "CMMagneticFieldCalibrationAccuracyUncalibrated" means "the device does not have a magnetometer"... But no! It is an iPhone 6...

So what am I doing wrong? I tried all four CMAttitudeReferenceFrame. Please I need help. Any ideas?

1
Device Motion in console (CMAttitudeReferenceFrameXMagneticNorthZVertical): QuaternionX 0.007901 QuaternionY 0.004146 QuaternionZ 0.000132 QuaternionW 0.999960 UserAccelX 0.000576 UserAccelY -0.000035 UserAccelZ -0.001655 RotationRateX 0.000056 RotationRateY 0.009508 RotationRateZ 0.000458 MagneticFieldX 0.000000 MagneticFieldY 0.000000 MagneticFieldZ 0.000000 MagneticFieldAccuracy -1 @ 203585.926003iSteffi
Are you using the simulator or the actual device?Bill
Update: obviously I get data different from zero when using "CMAttitudeReferenceFrameXTrueNorthZVertical". But not stable with every attempt.. more randomly. I realised that in both cases in the first update rounds the data is 0 (accuracy also -1). I know that it is due to the fact that the magnetometer itself needs some time to produce the first update data. So could it be that during the attempts where I only get zeros, the magnetometer is just distracted or not yet ready?iSteffi

1 Answers

2
votes

Ok.. I solved it.

The reason for the zeros were an uncalibrated magnetometer! But that does not mean that there is no magnetometer like stated in the apple docs. Anyway I did never expected that.

I just needed to add the functionality of compass calibration. And that is fairly easy to add:

motionMangager.showsDeviceMovementDisplay = true

(See: https://developer.apple.com/library/ios/documentation/CoreMotion/Reference/CMMotionManager_Class/)

So now it is like: When I am getting zeros and -1 for accuracy than the alert asking for calibration pops up. After a move it vanishes and I am getting proper values.