Pebble: акселерометр, пример использования

e66c399d05334f2f910aedae9df2cc5b.pngАкселорометр, который используется в Pebble откалиброван для измерения ускорения в пределах ± 4G, через API возможно получение ускорения по трем осям x, y и z в тысячных долях G. Таким образом диапазон возможных значений для каждой оси от -4000 до 4000.Есть возможность установить частоту обновления данных акселерометром в: 10, 25 (по умолчанию), 50 и 100 Hz.Ниже о том, как получать данные встроенного в Pebble акселерометра и экстремальное применение приобретенных знаний.Разработчики предлагают три обособленных способа использования акселерометра [1]:

Tap Event Service — реакция приложения на резкое движение часов. [2] Data Event Service — получение всех данных акселерометра. [3] Service Peek — интерактивное получение данных.[4] Tap Event ServiceИспользуетя когда приложению нужно отследить факт того, что пользователь потряс часами или постучал по ним.Обработчик события в общем случае будет выглядеть, как: static void tap_handler (AccelAxisType axis, int32_t direction) { } AccelAxisType axis — ось по которой произошел «тычек», возможные значения ACCEL_AXIS_X, ACCEL_AXIS_Y, ACCEL_AXIS_Z.int32_t direction — направление «тычка» (-1 или +1). Для оси X положительное направление к правой части часов, для Y — движение к верхней части, для Z — вертикально вверх.Подписка на события, обработчик tap_handler вызывается при каждом tap’е:

accel_tap_service_subscribe (tap_handler); Data Event Service Используется для накопления и анализа данных акселерометра, определение конкретного жеста или движения пользователя.Обработчик события в общем случае будет выглядеть, как:

static void data_handler (AccelData *data, uint32_t num_samples) {

} AccelData *data — набор данных для всех осей, плюс таймштамп и признак работал ли вибродвигатель при получении набора.uint32_t num_samples — количество наборов в буфере, от 0 до 25.Подписка на события, обработчик data_handler вызывается каждый раз при получении набора данных.

uint32_t num_samples = 3; accel_data_service_subscribe (num_samples, data_handler); И пример из документации обработки данных: 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 Получение последних сохраненных значений показателей акселерометра.N.B. Использование невозможно при подписке на Data Event Service.

В любой момент времени вызов accel_service_peek позволяет прочитать последние данные сохраненные акселерометром.

Типовое использование:

AccelData accel = (AccelData) { .x = 0, .y = 0, .z = 0 }; accel_service_peek (&accel); Определение высоты подбрасывания часов И, как результат, пример приложения, которое определят насколько высоко пользователю не жалко подбросить часы.Идея совершенно не новая, в первый раз я столкнулся с подобным на Nokia n900 [5] — игрушка n900Fly. Потом появилось S.M. T.H (Send Me To Heaven).

Функциональность приложения:

определение состояние полета часов; определение времени полета и расчет высоты; отображение последнего результата подкидывания В данном случае ни определение тапа, ни анализ наборов данных не используем.Не выдумывая нового, спооб определения моментов бросания и приземления из n900Fly: расчитывается средний вектор ускорения, как sqrt (x^2+y^2+z^2); если вектор становится меньше 400 — момент отрыва; если вектор становится больше 500 — момент приземления. Инициализируем акселерометр, устанавливаем частоту обновления в 25Hz и подписываемся на таймер с интервалом обновления 20 милисекунд: #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); } Раз в 20 милисекунд проходит опрос акселерометра, расчитывается среднее значение ускорения и определяется состояние часов:

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); } Если фиксируем приземление, то перерисовываем слой и задерживаем следующие обращение к данным акселерометра на 1 с, иначе даже маленький отскок посчитается как новый бросок.Математические функции в Pebble SDK представлены скудно. Поэтому для вычисления квадратного корня используется целочисленный алгоритм вычисления обратного квадратного корня [6], найденный на просторах Интернета:

#define SQRT_MAGIC_F 0×5f3759df

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); } Для точности расчета времени полета необходимо учитывать милисекунды:

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); } А высоту на которую подлетают часы считаем по формуле G*t^2/2, где g=9.8 м/с^2:

// Высота полета в мм static uint32_t flight_height (uint32_t flightTime) { return (uint32_t)(9.8 * ((flightTime/2)*(flightTime/2))/2 / 100); } Посчитаны flightTime и flightHeight, можно их показать любым удобным для пользователя способом: b571f8bb496a468a928213764d40adcc.png

Кто выше?

Полный код приложения bitbucket/icanfly

1. Pebble Developers // Detection Acceleration2. Pebble Developers // Tap Event Service3. Pebble Developers // Data Event Service4. Pebble Developers // AccelerometerService5. maemo.org — package overview for n900Fly6. Википедия — Быстрый обратный квадратный корень

© Habrahabr.ru