- PVSM.RU - https://www.pvsm.ru -
Акселорометр, который используется в Pebble откалиброван для измерения ускорения в пределах ± 4G, через API возможно получение ускорения по трем осям x, y и z в тысячных долях G. Таким образом диапазон возможных значений для каждой оси от -4000 до 4000.
Есть возможность установить частоту обновления данных акселерометром в: 10, 25 (по умолчанию), 50 и 100 Hz.
Ниже о том, как получать данные встроенного в Pebble акселерометра и экстремальное применение приобретенных знаний.
Разработчики предлагают три обособленных способа использования акселерометра [1] [1]:
Используетя когда приложению нужно отследить факт того, что пользователь потряс часами или постучал по ним.
Обработчик события в общем случае будет выглядеть, как:
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);
Используется для накопления и анализа данных акселерометра, определение конкретного жеста или движения пользователя.
Обработчик события в общем случае будет выглядеть, как:
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,Zn0 %d,%d,%dn1 %d,%d,%dn2 %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);
}
Получение последних сохраненных значений показателей акселерометра.
N.B. Использование невозможно при подписке на Data Event Service.
В любой момент времени вызов accel_service_peek позволяет прочитать последние данные сохраненные акселерометром.
Типовое использование:
AccelData accel = (AccelData) { .x = 0, .y = 0, .z = 0 };
accel_service_peek(&accel);
И, как результат, пример приложения, которое определят насколько высоко пользователю не жалко подбросить часы.
Идея совершенно не новая, в первый раз я столкнулся с подобным на Nokia n900 [5] [4] — игрушка n900Fly. Потом появилось S.M.T.H (Send Me To Heaven) [5].
Функциональность приложения:
В данном случае ни определение тапа, ни анализ наборов данных не используем.
Не выдумывая нового, спооб определения моментов бросания и приземления из n900Fly:
Инициализируем акселерометр, устанавливаем частоту обновления в 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] [6], найденный на просторах Интернета:
#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);
}
Для точности расчета времени полета необходимо учитывать милисекунды:
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, можно их показать любым удобным для пользователя способом:
Кто выше?
Полный код приложения bitbucket/icanfly [7]
1. Pebble Developers // Detection Acceleration [8]
2. Pebble Developers // Tap Event Service [9]
3. Pebble Developers // Data Event Service [10]
4. Pebble Developers // AccelerometerService [11]
5. maemo.org — package overview for n900Fly [12]
6. Википедия — Быстрый обратный квадратный корень [13]
Автор: tmnhy
Источник [14]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/tutorial/83249
Ссылки в тексте:
[1] [1]: #Anchor1
[2] [2]: #Anchor2
[3] [4]: #Anchor4
[4] [5]: #Anchor5
[5] S.M.T.H (Send Me To Heaven): https://play.google.com/store/apps/details?id=com.carrotpop.www.smth&hl=ru
[6] [6]: #Anchor6
[7] bitbucket/icanfly: https://bitbucket.org/tmnhy/icanfly/src/e5276da115dccfd6a40da75c5f003f51585b651f?at=master
[8] 1. Pebble Developers // Detection Acceleration: http://developer.getpebble.com/guides/pebble-apps/sensors/accelerometer/
[9] 2. Pebble Developers // Tap Event Service: http://developer.getpebble.com/guides/pebble-apps/sensors/accelerometer/#tap-event-service
[10] 3. Pebble Developers // Data Event Service: http://developer.getpebble.com/guides/pebble-apps/sensors/accelerometer/#data-event-service
[11] 4. Pebble Developers // AccelerometerService: http://developer.getpebble.com/docs/c/group___accelerometer_service.html
[12] 5. maemo.org — package overview for n900Fly: http://maemo.org/packages/view/n900fly/
[13] 6. Википедия — Быстрый обратный квадратный корень: http://ru.wikipedia.org/wiki/Быстрый_обратный_квадратный_корень
[14] Источник: http://habrahabr.ru/post/250823/
Нажмите здесь для печати.