mirror of
https://github.com/google/pebble.git
synced 2025-03-22 03:32:20 +00:00
195 lines
7 KiB
Markdown
195 lines
7 KiB
Markdown
---
|
||
# Copyright 2025 Google LLC
|
||
#
|
||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||
# you may not use this file except in compliance with the License.
|
||
# You may obtain a copy of the License at
|
||
#
|
||
# http://www.apache.org/licenses/LICENSE-2.0
|
||
#
|
||
# Unless required by applicable law or agreed to in writing, software
|
||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
# See the License for the specific language governing permissions and
|
||
# limitations under the License.
|
||
|
||
title: Compass
|
||
description: |
|
||
How to use data from the Compass API to determine direction.
|
||
guide_group: events-and-services
|
||
order: 3
|
||
related_docs:
|
||
- CompassService
|
||
related_examples:
|
||
- title: Feature Compass
|
||
url: https://github.com/pebble-examples/feature-compass
|
||
- title: Official Compass Watchapp
|
||
url: https://github.com/pebble-hacks/pebble-compass
|
||
---
|
||
|
||
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`](``CompassHeadingData``) 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]({{site.links.examples_org}}/feature-compass) 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](http://maps.ngdc.noaa.gov/viewers/historical_declination/).
|
||
|
||
|
||
## 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:
|
||
|
||
```c
|
||
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()`:
|
||
|
||
```c
|
||
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``:
|
||
|
||
```c
|
||
// 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:
|
||
|
||
```c
|
||
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:
|
||
|
||
```c
|
||
// 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:
|
||
|
||
```c
|
||
compass_service_unsubscribe();
|
||
```
|
||
|
||
|
||
## Peeking at Compass Data
|
||
|
||
To fetch a compass heading without subscribing, simply peek to get a single
|
||
sample:
|
||
|
||
```c
|
||
// 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).
|