pebble/devsite/source/_guides/events-and-services/accelerometer.md
2025-02-24 18:58:29 -08:00

5.5 KiB

title description guide_group order related_docs related_examples
Accelerometer How to use data and simple tap gestures from the onboard accelerometer. events-and-services 0
AccelerometerService
title url
Feature Accel Discs https://github.com/pebble-examples/feature-accel-discs

The acceleromter sensor is included in every Pebble watch, and allows collection of acceleration and orientation data in watchapps and watchfaces. Data is available in two ways, each suitable to different types of watchapp:

  • Taps events - Fires an event whenever a significant tap or shake of the watch occurs. Useful to 'shake to view' features.

  • Data batches - Allows collection of data in batches at specific intervals. Useful for general accelerometer data colleciton.

As a significant source of regular callbacks, the accelerometer should be used as sparingly as possible to allow the watch to sleep and conserve power. For example, receiving data in batches once per second is more power efficient than receiving a single sample 25 times per second.

About the Pebble Accelerometer

The Pebble accelerometer is oriented according to the diagram below, showing the direction of each of the x, y, and z axes.

accel-axes

In the API, each axis value contained in an AccelData sample is measured in milli-Gs. The accelerometer is calibrated to measure a maximum acceleration of ±4G. Therefore, the range of possible values for each axis is -4000 to +4000.

The AccelData sample object also contains a did_vibrate field, set to true if the vibration motor was active during the sample collection. This could possibly contaminate those samples due to onboard vibration, so they should be discarded. Lastly, the timestamp field allows tracking of obtained accelerometer data over time.

Using Taps

Adding a subscription to tap events allows a developer to react to any time the watch is tapped or experiences a shake along one of three axes. Tap events are received by registering an AccelTapHandler function, such as the one below:

static void accel_tap_handler(AccelAxisType axis, int32_t direction) {
  // A tap event occured

}

The axis parameter describes which axis the tap was detected along. The direction parameter is set to 1 for the positive direction, and -1 for the negative direction.

A subscription can be added or removed at any time. While subscribed, accel_tap_handler will be called whenever a tap event is fired by the accelerometer. Adding a subscription is simple:

// Subscribe to tap events
accel_tap_service_subscribe(accel_tap_handler);
// Unsubscribe from tap events
accel_tap_service_unsubscribe();

Using Data Batches

Accelerometer data can be received in batches at a chosen sampling rate by subscribing to the Accelerometer Data Service at any time:

uint32_t num_samples = 3;  // Number of samples per batch/callback

// Subscribe to batched data events
accel_data_service_subscribe(num_samples, accel_data_handler);

The AccelDataHandler function (called accel_data_handler in the example above) is called when a new batch of data is ready for consumption by the watchapp. The rate at which these occur is dictated by two things:

  • The sampling rate - The number of samples the accelerometer device measures per second. One value chosen from the AccelSamplingRate enum.

  • The number of samples per batch.

Some simple math will determine how often the callback will occur. For example, at the ACCEL_SAMPLING_50HZ sampling rate, and specifying 10 samples per batch will result in five calls per second.

When an event occurs, the acceleromater data can be read from the AccelData pointer provided in the callback. An example reading the first set of values is shown below:

static void accel_data_handler(AccelData *data, uint32_t num_samples) {
  // Read sample 0's x, y, and z values
  int16_t x = data[0].x;
  int16_t y = data[0].y;
  int16_t z = data[0].z;

  // Determine if the sample occured during vibration, and when it occured
  bool did_vibrate = data[0].did_vibrate;
  uint64_t timestamp = data[0].timestamp;

  if(!did_vibrate) {
    // Print it out
    APP_LOG(APP_LOG_LEVEL_INFO, "t: %llu, x: %d, y: %d, z: %d",
                                                          timestamp, x, y, z);
  } else {
    // Discard with a warning
    APP_LOG(APP_LOG_LEVEL_WARNING, "Vibration occured during collection");
  }
}

The code above will output the first sample in each batch to app logs, which will look similar to the following:

[15:33:18] -data-service.c:21> t: 1449012797098, x: -111, y: -280, z: -1153
[15:33:18] -data-service.c:21> t: 1449012797305, x: -77, y: 40, z: -1014
[15:33:18] -data-service.c:21> t: 1449012797507, x: -60, y: 4, z: -1080
[15:33:19] -data-service.c:21> t: 1449012797710, x: -119, y: -55, z: -921
[15:33:19] -data-service.c:21> t: 1449012797914, x: 628, y: 64, z: -506