Reputation: 102454
I'm working from Apple's Event Handling Guide for iOS. I'm using the pull method described near startAccelerometerUpdates
. The pull method is fine for my purposes since I only need to read from the sensor once.
I'm getting a nil from the calls to accelerometerData
, gyroData
and magnetometerData
in the code below on an iPhone 4, iPad Mini, and iPad Retina. isAccelerometerAvailable,
isGyroAvailable, and
isMagnetometerAvailableeach return
YES`. Two questions:
How does one determine the result from startAccelerometerUpdates
and startGyroUpdates
? They are void
functions, so can I assume it can never fail? (Otherwise, it would throw or return a BOOL
).
How does one get the last error from the call to accelerometerData
, gyroData
and magnetometerData
?
EDIT: I had to call [NSThread sleepForTimeInterval:0.150f]
to get data out of the sensor. Anything less and the sensor does not produce valid data.
The sleep adds a third question: how long does one need to pause to ensure the data arrives when the hardware is present?
Thanks in advance.
static CryptoPP::RandomPool pool;
static dispatch_once_t once = 0;
dispatch_once(&once, ^{
CryptoPP::SecByteBlock seed(32);
CryptoPP::OS_GenerateRandomBlock(true, seed.data(), seed.size());
pool.IncorporateEntropy(seed.data(), seed.size());
});
// First, send in all the uninitialized data. Then:
// sesnors[0,1,2] use accelerometer, if available
// sesnors[3,4,5] use gyroscope, if available
// sesnors[6,7,8] use magnetometer, if available
CryptoPP::SecBlock<double> sensors(3 * 3);
pool.IncorporateEntropy(sensors.BytePtr(), sensors.SizeInBytes());
CMMotionManager* mgr = [[CMMotionManager alloc] init];
if(mgr) {
[mgr startAccelerometerUpdates];
[mgr startGyroUpdates];
[mgr startMagnetometerUpdates];
[NSThread sleepForTimeInterval:0.150f];
if([mgr isAccelerometerAvailable]) {
CMAccelerometerData* accelData = [mgr accelerometerData];
if(accelData) {
sensors[0] = [accelData acceleration].x;
sensors[1] = [accelData acceleration].y;
sensors[2] = [accelData acceleration].z;
}
}
if([mgr isGyroAvailable]) {
CMGyroData* gyroData = [mgr gyroData];
if(gyroData) {
sensors[3] = [gyroData rotationRate].x;
sensors[4] = [gyroData rotationRate].y;
sensors[5] = [gyroData rotationRate].z;
}
}
if([mgr isMagnetometerAvailable]) {
CMMagnetometerData* magnetData = [mgr magnetometerData];
if(magnetData) {
sensors[6] = [magnetData magneticField].x;
sensors[7] = [magnetData magneticField].y;
sensors[8] = [magnetData magneticField].z;
}
}
pool.IncorporateEntropy(sensors.BytePtr(), sensors.SizeInBytes());
[mgr stopMagnetometerUpdates];
[mgr stopGyroUpdates];
[mgr stopAccelerometerUpdates];
[mgr release], mgr = nil;
}
Upvotes: 0
Views: 680
Reputation: 33389
When you do this:
mgr startAccelerometerUpdates];
[mgr setAccelerometerUpdateInterval:0.01f];
That means you will not start receiving information until 0.01 seconds later, and even then you'll only receive updates if the main thread is idle.
You are not waiting 0.01 seconds before checking for data, you're actually waiting about 0.00000000001 seconds. And I'm not sure, but I think your main thread might need to be idle even if you do wait longer.
I think you should go back to the documentation and have a look how you're supposed to read information from the sensors.
I recommend using blocks to process the motion data:
[mManager startAccelerometerUpdatesToQueue:[NSOperationQueue mainQueue] withHandler:^(CMAccelerometerData *accelerometerData, NSError *error) {
// process data
}];
You could tell the accelerometer to stop immediately after receiving the first value, if you only want it once.
Upvotes: 1