7 KiB
title | description | guide_group | order | related_docs | related_examples | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Compass | How to use data from the Compass API to determine direction. | events-and-services | 3 |
|
|
The CompassService
combines data from Pebble's accelerometer and
magnetometer to automatically calibrate the compass and produce a
CompassHeading
, containing an angle measured relative to magnetic north.
The compass service provides magnetic north and information about its status
and accuracy through the CompassHeadingData
structure.
Calibration
The compass service requires an initial calibration before it can return
accurate results. Calibration is performed automatically by the system when
first required. The compass_status
field indicates
whether the compass service is calibrating. To help the calibration process, the
app should show a message to the user asking them to move their wrists in
different directions.
Refer to the compass example for an example of how to implement this screen.
Magnetic North and True North
Depending on the user's location on Earth, the measured heading towards magnetic north and true north can significantly differ. This is due to magnetic variation, also known as 'declination'.
Pebble does not automatically correct the magnetic heading to return a true heading, but the API is designed so that this feature can be added in the future and the app will be able to automatically take advantage of it.
For a more precise heading, use the magnetic_heading
field of
CompassHeadingData
and use a webservice to retrieve the declination at the
user's current location. Otherwise, use the true_heading
field. This field
will contain the magnetic_heading
if declination is not available, or the true
heading if declination is available. The field is_declination_valid
will be
true when declination is available. Use this information to tell the user
whether the app is showing magnetic north or true north.
To see the true extent of declination, see how declination has changed over time.
Battery Considerations
Using the compass will turn on both Pebble's magnetometer and accelerometer. Those two devices will have a slight impact on battery life. A much more significant battery impact will be caused by redrawing the screen too often or performing CPU-intensive work every time the compass heading is updated.
Use compass_service_subscribe()
if the app only needs to update its UI when
new compass data is available, or else use compass_service_peek()
if this
happens much less frequently.
Defining "Up" on Pebble
Compass readings are always relative to the current orientation of Pebble. Using the accelerometer, the compass service figures out which direction the user is facing.
The best orientation to encourage users to adopt while using a compass-enabled watchapp is with the top of the watch parallel to the ground. If the watch is raised so that the screen is facing the user, the plane will now be perpedicular to the screen, but still parallel to the ground.
Angles and Degrees
The magnetic heading value is presented as a number between 0 and TRIG_MAX_ANGLE (65536). This range is used to give a higher level of precision for drawing commands, which is preferable to using only 360 degrees.
If you imagine an analogue clock face on your Pebble, the angle 0 is always at the 12 o'clock position, and the magnetic heading angle is calculated in a counter clockwise direction from 0.
This can be confusing to grasp at first, as it’s opposite of how direction is measured on a compass, but it's simple to convert the values into a clockwise direction:
int clockwise_angle = TRIG_MAX_ANGLE - heading_data.magnetic_heading;
Once you have an angle relative to North, you can convert that to degrees using
the helper function TRIGANGLE_TO_DEG()
:
int degrees = TRIGANGLE_TO_DEG(TRIG_MAX_ANGLE - heading_data.magnetic_heading);
Subscribing to Compass Data
Compass heading events can be received in a watchapp by subscribing to the
CompassService
:
// Subscribe to compass heading updates
compass_service_subscribe(compass_heading_handler);
The provided CompassHeadingHandler
function (called
compass_heading_handler
above) can be used to read the state of the compass,
and the current heading if it is available. This value is given in the range of
0
to TRIG_MAX_ANGLE
to preserve precision, and so it can be converted
using the TRIGANGLE_TO_DEG()
macro:
static void compass_heading_handler(CompassHeadingData heading_data) {
// Is the compass calibrated?
switch(heading_data.compass_status) {
case CompassStatusDataInvalid:
APP_LOG(APP_LOG_LEVEL_INFO, "Not yet calibrated.");
break;
case CompassStatusCalibrating:
APP_LOG(APP_LOG_LEVEL_INFO, "Calibration in progress. Heading is %ld",
TRIGANGLE_TO_DEG(TRIG_MAX_ANGLE - heading_data.magnetic_heading));
break;
case CompassStatusCalibrated:
APP_LOG(APP_LOG_LEVEL_INFO, "Calibrated! Heading is %ld",
TRIGANGLE_TO_DEG(TRIG_MAX_ANGLE - heading_data.magnetic_heading));
break;
}
}
By default, the callback will be triggered whenever the heading changes by one degree. To reduce the frequency of updates, change the threshold for heading changes by setting a heading filter:
// Only notify me when the heading has changed by more than 5 degrees.
compass_service_set_heading_filter(DEG_TO_TRIGANGLE(5));
Unsubscribing From Compass Data
When the app is done using the compass, stop receiving callbacks by unsubscribing:
compass_service_unsubscribe();
Peeking at Compass Data
To fetch a compass heading without subscribing, simply peek to get a single sample:
// Peek to get data
CompassHeadingData data;
compass_service_peek(&data);
Similar to the subscription-provided data, the app should examine the peeked
CompassHeadingData
to determine if it is valid (i.e. the compass is calibrated).