Pebble: Accelerometer Case Study
- Tutorial

It is possible to set accelerometer data refresh rate at: 10, 25 (default), 50 and 100 Hz.
Below is how to get data from Pebble’s built-in accelerometer and the extreme application of acquired knowledge.
The developers offer three separate ways to use the accelerometer [1] :
- Tap Event Service - the reaction of the application to the sharp movement of the clock. [2]
- Data Event Service - receiving all accelerometer data. [3]
- Service Peek - interactive data acquisition. [4]
Tap event service
Used when the application needs to track the fact that the user shook the clock or knocked on it.
An event handler will generally look like:
static void tap_handler(AccelAxisType axis, int32_t direction) {
}
AccelAxisType axis - the axis along which the “poke” occurred, the possible values are ACCEL_AXIS_X , ACCEL_AXIS_Y , ACCEL_AXIS_Z .
int32_t direction - the direction of the "poke" (-1 or +1). For the X axis, the positive direction to the right of the watch, for Y - movement to the top, for Z - vertically up.
Subscribing to events, the tap_handler handler is called on every tap:
accel_tap_service_subscribe(tap_handler);
Data Event Service
It is used to accumulate and analyze accelerometer data, to determine a specific gesture or movement of the user.
An event handler will generally look like:
static void data_handler(AccelData *data, uint32_t num_samples) {
}
AccelData * data - a data set for all axes, plus a time stamp and a sign whether the vibration motor worked when receiving the set.
uint32_t num_samples - the number of sets in the buffer, from 0 to 25.
Subscribing to events, the data_handler handler is called every time a data set is received.
uint32_t num_samples = 3;
accel_data_service_subscribe(num_samples, data_handler);
And an example from the data processing documentation:
static void data_handler(AccelData *data, uint32_t num_samples) {
// Long lived buffer
static char s_buffer[128];
// Compose string of all data for 3 samples
snprintf(s_buffer, sizeof(s_buffer),
"N X,Y,Z\n0 %d,%d,%d\n1 %d,%d,%d\n2 %d,%d,%d",
data[0].x, data[0].y, data[0].z,
data[1].x, data[1].y, data[1].z,
data[2].x, data[2].y, data[2].z
);
//Show the data
text_layer_set_text(s_output_layer, s_buffer);
}
Service peek
Getting the last saved values of accelerometer indicators.
NB Use is not possible when subscribing to the Data Event Service .
At any time, calling accel_service_peek allows you to read the latest data saved by the accelerometer.
Typical use:
AccelData accel = (AccelData) { .x = 0, .y = 0, .z = 0 };
accel_service_peek(&accel);
Determining the height of the tossing hours
And, as a result, an example of an application that will determine how high the user is not sorry to toss the clock.
The idea is not new at all, for the first time I came across a n900Fly toy similar to Nokia n900 [5] . Then came SMTH (Send Me To Heaven) .
Application Functionality:
- determining the flight status of the watch;
- determination of flight time and altitude calculation;
- display last toss result
In this case, we do not use either the definition of tapas or the analysis of data sets.
Without inventing a new way to determine the moments of throwing and landing from n900Fly:
- the average acceleration vector is calculated as sqrt (x ^ 2 + y ^ 2 + z ^ 2) ;
- if the vector becomes less than 400 - the moment of separation;
- if the vector becomes greater than 500 - the moment of landing.
We initialize the accelerometer, set the update frequency to 25Hz and subscribe to the timer with an update interval of 20 milliseconds:
#define ACCEL_STEP_MS 20
static void init(void) {
/* ... */
accel_service_set_sampling_rate(ACCEL_SAMPLING_25HZ);
accel_data_service_subscribe(0, NULL);
timer = app_timer_register(ACCEL_STEP_MS, accel_callback, NULL);
}
Once every 20 milliseconds, the accelerometer is polled, the average acceleration value is calculated and the state of the clock is determined:
static void accel_callback(void *data) {
AccelData accel = (AccelData) { .x = 0, .y = 0, .z = 0 };
accel_service_peek(&accel);
// Полетели
if (( accel_abs(accel) < 400 ) && ( !iFlying)) {
time_ms(&start.sec, &start.ms);
iFlying = true;
};
// Приземлилиись
if ( (accel_abs(accel) > 500) && (iFlying) ) {
time_ms(&end.sec, &end.ms);
flightTime = flight_time(start, end);
flightHeight = flight_height(flightTime);
iFlying = false;
layer_mark_dirty(s_layer);
timer = app_timer_register(1000, accel_callback, NULL);
return;
}
timer = app_timer_register(ACCEL_STEP_MS, accel_callback, NULL);
}
If we fix the landing, then redraw the layer and delay the next access to the accelerometer data for 1 s, otherwise even a small rebound will be counted as a new throw.
The math functions in the Pebble SDK are sparse. Therefore, to calculate the square root, an integer algorithm for calculating the inverse square root [6] , found on the Internet, is used:
#define SQRT_MAGIC_F 0x5f3759df
float my_sqrt(const float x) {
const float xhalf = 0.5f*x;
union {
float x;
int i;
} u;
u.x = x;
u.i = SQRT_MAGIC_F - (u.i >> 1);
return x*u.x*(1.5f - xhalf*u.x*u.x);
}
For the accuracy of calculating the flight time, it is necessary to take into account the milliseconds:
typedef struct time_with_ms {
time_t sec;
uint16_t ms;
} time_with_ms;
static time_with_ms start;
static time_with_ms end;
/* ... */
time_ms(&end.sec, &end.ms);
/* ... */
time_ms(&start.sec, &start.ms);
/* ... */
// Время полета в мс
static uint32_t flight_time(time_with_ms start, time_with_ms end) {
return ( (end.sec - start.sec)*1000 + end.ms - start.ms );
}
And we consider the height at which the clock flies up according to the formula G * t ^ 2/2, where g = 9.8 m / s ^ 2:
// Высота полета в мм
static uint32_t flight_height(uint32_t flightTime) {
return (uint32_t)( 9.8 * ((flightTime/2)*(flightTime/2))/2 / 100 );
}
FlightTime and flightHeight are calculated, you can show them in any way convenient for the user:

Who is higher?
Full bitbucket / icanfly Pebble App Store app code
: I can fly
1. Pebble Developers // Detection Acceleration
2. Pebble Developers // Tap Event Service
3. Pebble Developers // Data Event Service
4. Pebble Developers // AccelerometerService
5. maemo.org - package overview for n900Fly
6. Wikipedia - Fast reverse square root