You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by pr...@apache.org on 2020/10/22 13:17:47 UTC
[incubator-nuttx] 02/03: sensor/driver: wtgahrs2 by serial
interface follow sensor.c/sensor.h
This is an automated email from the ASF dual-hosted git repository.
protobits pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
commit a3f978da025e91bb44344b89a3026548d8c494eb
Author: dongjiuzhu <do...@xiaomi.com>
AuthorDate: Mon Oct 19 21:30:22 2020 +0800
sensor/driver: wtgahrs2 by serial interface follow sensor.c/sensor.h
Wtgahrs2 integrates multiple sensor: accel, gyro, mag, baro and gps.
Signed-off-by: dongjiuzhu <do...@xiaomi.com>
---
drivers/sensors/Kconfig | 8 +
drivers/sensors/Make.defs | 4 +
drivers/sensors/wtgahrs2.c | 578 +++++++++++++++++++++++++++++++++++++++
include/nuttx/sensors/wtgahrs2.h | 64 +++++
4 files changed, 654 insertions(+)
diff --git a/drivers/sensors/Kconfig b/drivers/sensors/Kconfig
index f9bad12..2a9bac5 100644
--- a/drivers/sensors/Kconfig
+++ b/drivers/sensors/Kconfig
@@ -11,6 +11,14 @@ menuconfig SENSORS
if SENSORS
+config SENSORS_WTGAHRS2
+ bool "Wtgahrs2 Sensor Support"
+ default n
+ ---help---
+ We can read sensor data by serial interface. It need the hardware sensor
+ wtgashrs2(JY901) as data source. This sensor can generate accelerometer,
+ gyroscope, magnetic, barometer and gps data.
+
config SENSORS_APDS9960
bool "Avago APDS-9960 Gesture Sensor support"
default n
diff --git a/drivers/sensors/Make.defs b/drivers/sensors/Make.defs
index bf87397..a22909f 100644
--- a/drivers/sensors/Make.defs
+++ b/drivers/sensors/Make.defs
@@ -39,6 +39,10 @@ ifeq ($(CONFIG_SENSORS),y)
CSRCS += sensor.c
+ifeq ($(CONFIG_SENSORS_WTGAHRS2),y)
+ CSRCS += wtgahrs2.c
+endif
+
ifeq ($(CONFIG_SENSORS_HCSR04),y)
CSRCS += hc_sr04.c
endif
diff --git a/drivers/sensors/wtgahrs2.c b/drivers/sensors/wtgahrs2.c
new file mode 100644
index 0000000..d3311b9
--- /dev/null
+++ b/drivers/sensors/wtgahrs2.c
@@ -0,0 +1,578 @@
+/****************************************************************************
+ * drivers/sensors/wtgahrs2.c
+ * Driver for the Wit-Motion WTGAHRS2 accelerometer, gyroscope, magnetic,
+ * angle, barometer, temperature, gps sensors by serial interface with host
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you 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.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <nuttx/sensors/wtgahrs2.h>
+#include <nuttx/kthread.h>
+#include <nuttx/kmalloc.h>
+
+#include <termios.h>
+#include <math.h>
+#include <fcntl.h>
+#include <stdio.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define WTGAHRS2_ARRAYSIZE(a) (sizeof((a))/sizeof(a[0]))
+
+#define WTGAHRS2_ACCEL_IDX 0
+#define WTGAHRS2_GYRO_IDX 1
+#define WTGAHRS2_MAG_IDX 2
+#define WTGAHRS2_BARO_IDX 3
+#define WTGAHRS2_GPS_IDX 4
+#define WTGAHRS2_MAX_IDX 5
+
+#define WTGAHRS2_GPS0_MASK (1 << 0) /* Time */
+#define WTGAHRS2_GPS1_MASK (1 << 1) /* Longitude, Latitude */
+#define WTGAHRS2_GPS2_MASK (1 << 2) /* Ground speed, Height, Yaw */
+#define WTGAHRS2_GPS_MASK (7 << 0)
+
+#define WTGAHRS2_GPS0_INFO 0x50
+#define WTGAHRS2_ACCEL_INFO 0x51
+#define WTGAHRS2_GYRO_INFO 0x52
+#define WTGAHRS2_MAG_INFO 0x54
+#define WTGAHRS2_BARO_INFO 0x56
+#define WTGAHRS2_GPS1_INFO 0x57
+#define WTGAHRS2_GPS2_INFO 0x58
+
+#define WTGAHRS2_RSP_HEADER 0x55
+#define WTGAHRS2_RSP_LENGTH 11
+#define WTGAHRS2_CMD_LENGTH 5
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct wtgahrs2_sensor_s
+{
+ struct sensor_lowerhalf_s lower;
+ unsigned int interval;
+ unsigned int last_update;
+ bool enable;
+};
+
+struct wtgahrs2_dev_s
+{
+ struct wtgahrs2_sensor_s dev[WTGAHRS2_MAX_IDX];
+ struct file file;
+
+ struct sensor_event_gps gps;
+ unsigned char gps_mask;
+};
+
+/****************************************************************************
+ * Private
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static int wtgahrs2_activate(FAR struct sensor_lowerhalf_s *lower, bool sw);
+static int wtgahrs2_set_interval(FAR struct sensor_lowerhalf_s *lower,
+ FAR unsigned int *interval);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* in microseconds */
+
+static const unsigned int g_wtgahrs2_interval[] =
+{
+ 10000000, /* 0.1 hz */
+ 2000000, /* 0.5 hz */
+ 1000000, /* 1 hz */
+ 500000, /* 2 hz */
+ 200000, /* 5 hz */
+ 100000, /* 10 hz */
+ 50000, /* 20 hz */
+ 20000, /* 50 hz */
+ 10000, /* 100 hz */
+ 5000, /* 200 hz */
+};
+
+static const uint8_t g_wtgahrs2_unlock[] =
+{
+ 0xff, 0xaa, 0x69, 0x88, 0xb5
+};
+
+static const uint8_t g_wtgahrs2_odr_200hz[] =
+{
+ 0xff, 0xaa, 0x03, 0x0b, 0x00
+};
+
+static const uint8_t g_wtgahrs2_enable_sensor[] =
+{
+ 0xff, 0xaa, 0x02, 0xd7, 0x05
+};
+
+static const struct sensor_ops_s g_wtgahrs2_ops =
+{
+ .activate = wtgahrs2_activate,
+ .set_interval = wtgahrs2_set_interval,
+ .batch = NULL,
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static void wtgahrs2_sendcmd(FAR struct wtgahrs2_dev_s *rtdata,
+ const void *cmd)
+{
+ file_write(&rtdata->file, cmd, WTGAHRS2_CMD_LENGTH);
+ usleep(10000);
+}
+
+static int wtgahrs2_activate(FAR struct sensor_lowerhalf_s *lower, bool sw)
+{
+ FAR struct wtgahrs2_sensor_s *dev = (FAR struct wtgahrs2_sensor_s *)lower;
+ dev->enable = sw;
+
+ return 0;
+}
+
+static int wtgahrs2_set_interval(FAR struct sensor_lowerhalf_s *lower,
+ FAR unsigned int *interval)
+{
+ FAR struct wtgahrs2_sensor_s *dev = (FAR struct wtgahrs2_sensor_s *)lower;
+ int idx = 0;
+
+ for (; idx < WTGAHRS2_ARRAYSIZE(g_wtgahrs2_interval) - 1; idx++)
+ {
+ if (*interval >= g_wtgahrs2_interval[idx])
+ {
+ break;
+ }
+ }
+
+ *interval = g_wtgahrs2_interval[idx];
+ dev->interval = *interval;
+
+ return 0;
+}
+
+static void wtgahrs2_accel_data(FAR struct wtgahrs2_dev_s *rtdata,
+ FAR unsigned char *buffer)
+{
+ FAR struct wtgahrs2_sensor_s *dev = &rtdata->dev[WTGAHRS2_ACCEL_IDX];
+ FAR struct sensor_lowerhalf_s *lower = &dev->lower;
+ uint64_t now = sensor_get_timestamp();
+ struct sensor_event_accel accel;
+
+ if (!dev->enable || now - dev->last_update < dev->interval)
+ {
+ return;
+ }
+
+ dev->last_update = now;
+
+ accel.timestamp = now;
+ accel.x = (short)(buffer[1] << 8 | buffer[0]) * (16 * 9.8f / 32768);
+ accel.y = (short)(buffer[3] << 8 | buffer[2]) * (16 * 9.8f / 32768);
+ accel.z = (short)(buffer[5] << 8 | buffer[4]) * (16 * 9.8f / 32768);
+ accel.temperature = (short)(buffer[7] << 8 | buffer[6]) / 100.0f;
+
+ lower->push_event(lower->priv, &accel, sizeof(accel));
+ sninfo("Accel: %.3fm/s^2 %.3fm/s^2 %.3fm/s^2, t:%.1f\r\n",
+ accel.x, accel.y, accel.z, accel.temperature);
+}
+
+static void wtgahrs2_gyro_data(FAR struct wtgahrs2_dev_s *rtdata,
+ FAR unsigned char *buffer)
+{
+ FAR struct wtgahrs2_sensor_s *dev = &rtdata->dev[WTGAHRS2_GYRO_IDX];
+ FAR struct sensor_lowerhalf_s *lower = &dev->lower;
+ uint64_t now = sensor_get_timestamp();
+ struct sensor_event_gyro gyro;
+
+ if (!dev->enable || now - dev->last_update < dev->interval)
+ {
+ return;
+ }
+
+ dev->last_update = now;
+
+ gyro.timestamp = now;
+ gyro.x = (short)(buffer[1] << 8 | buffer[0]) * (2000 * M_PI / 180 / 32768);
+ gyro.y = (short)(buffer[3] << 8 | buffer[2]) * (2000 * M_PI / 180 / 32768);
+ gyro.z = (short)(buffer[5] << 8 | buffer[4]) * (2000 * M_PI / 180 / 32768);
+ gyro.temperature = (short)(buffer[7] << 8 | buffer[6]) / 100.0f;
+
+ lower->push_event(lower->priv, &gyro, sizeof(gyro));
+ sninfo("Gyro: %.3frad/s %.3frad/s %.3frad/s, t:%.1f\r\n",
+ gyro.x, gyro.y, gyro.z, gyro.temperature);
+}
+
+static void wtgahrs2_mag_data(FAR struct wtgahrs2_dev_s *rtdata,
+ FAR unsigned char *buffer)
+{
+ FAR struct wtgahrs2_sensor_s *dev = &rtdata->dev[WTGAHRS2_MAG_IDX];
+ FAR struct sensor_lowerhalf_s *lower = &dev->lower;
+ uint64_t now = sensor_get_timestamp();
+ struct sensor_event_mag mag;
+
+ if (!dev->enable || now - dev->last_update < dev->interval)
+ {
+ return;
+ }
+
+ dev->last_update = now;
+
+ mag.timestamp = now;
+ mag.x = (short)(buffer[1] << 8 | buffer[0]) * 0.16f;
+ mag.y = (short)(buffer[3] << 8 | buffer[2]) * 0.16f;
+ mag.z = (short)(buffer[5] << 8 | buffer[4]) * 0.16f;
+ mag.temperature = (short)(buffer[7] << 8 | buffer[6]) / 100.0f;
+
+ lower->push_event(lower->priv, &mag, sizeof(mag));
+ sninfo("Mag: %.3fuT %.3fuT %.3fuT, t:%.1f\r\n",
+ mag.x, mag.y, mag.z, mag.temperature);
+}
+
+static void wtgahrs2_baro_data(FAR struct wtgahrs2_dev_s *rtdata,
+ FAR unsigned char *buffer)
+{
+ FAR struct wtgahrs2_sensor_s *dev = &rtdata->dev[WTGAHRS2_BARO_IDX];
+ FAR struct sensor_lowerhalf_s *lower = &dev->lower;
+ uint64_t now = sensor_get_timestamp();
+ struct sensor_event_baro baro;
+
+ if (!dev->enable || now - dev->last_update < dev->interval)
+ {
+ return;
+ }
+
+ dev->last_update = now;
+
+ baro.timestamp = now;
+ baro.pressure = (long)(buffer[3] << 24 | buffer[2] << 16 |
+ buffer[1] << 8 | buffer[0]) / 100.0f;
+ baro.temperature = NAN;
+
+ lower->push_event(lower->priv, &baro, sizeof(baro));
+ sninfo("Pressure : %.3fhPa\r\n", baro.pressure);
+}
+
+static void wtgahrs2_gps_data(FAR struct wtgahrs2_dev_s *rtdata,
+ FAR unsigned char *buffer, int info_type)
+{
+ FAR struct wtgahrs2_sensor_s *dev = &rtdata->dev[WTGAHRS2_GPS_IDX];
+ FAR struct sensor_lowerhalf_s *lower = &dev->lower;
+ uint64_t now = sensor_get_timestamp();
+
+ if (!dev->enable || now - dev->last_update < dev->interval)
+ {
+ return;
+ }
+
+ if (rtdata->gps_mask == 0)
+ {
+ dev->last_update = now;
+ }
+
+ switch (info_type)
+ {
+ case WTGAHRS2_GPS0_INFO:
+ rtdata->gps_mask |= WTGAHRS2_GPS0_MASK;
+ rtdata->gps.year = 2000 + buffer[0];
+ rtdata->gps.month = buffer[1];
+ rtdata->gps.day = buffer[2];
+ rtdata->gps.hour = buffer[3];
+ rtdata->gps.min = buffer[4];
+ rtdata->gps.sec = buffer[5];
+ rtdata->gps.msec = (buffer[7] << 8) | buffer[6];
+ break;
+
+ case WTGAHRS2_GPS1_INFO:
+ rtdata->gps_mask |= WTGAHRS2_GPS1_MASK;
+ rtdata->gps.longitude = (long)(buffer[3] << 8
+ | buffer[2] << 8
+ | buffer[1] << 8
+ | buffer[0]) / 10000000.0f;
+ rtdata->gps.latitude = (long)(buffer[7] << 8
+ | buffer[6] << 8
+ | buffer[5] << 8
+ | buffer[4]) / 10000000.0f;
+ break;
+
+ case WTGAHRS2_GPS2_INFO:
+ rtdata->gps_mask |= WTGAHRS2_GPS2_MASK;
+ rtdata->gps.height = (short)(buffer[1] << 8 | buffer[0]) / 10.0f;
+ rtdata->gps.yaw = (short)(buffer[3] << 8 | buffer[2]) / 10.0f;
+ rtdata->gps.speed = (long)(buffer[7] << 8 | buffer[6] << 8
+ | buffer[5] << 8 | buffer[4]) / 3600.0f;
+ break;
+ }
+
+ if (rtdata->gps_mask == WTGAHRS2_GPS_MASK)
+ {
+ rtdata->gps_mask = 0;
+ lower->push_event(lower->priv, &rtdata->gps, sizeof(rtdata->gps));
+ sninfo("Time : %d/%d/%d-%d:%d:%d\r\n", rtdata->gps.year,
+ rtdata->gps.month, rtdata->gps.day, rtdata->gps.hour,
+ rtdata->gps.min, rtdata->gps.sec);
+ sninfo("GPS longitude : %fdegree, latitude:%fdegree\r\n",
+ rtdata->gps.longitude, rtdata->gps.latitude);
+ sninfo("GPS speed: %fm/s, yaw:%fdegrees, height:%fm \r\n",
+ rtdata->gps.speed, rtdata->gps.yaw, rtdata->gps.height);
+ }
+}
+
+static bool wtgahrs2_process_data(FAR struct wtgahrs2_dev_s *rtdata,
+ FAR unsigned char *buffer)
+{
+ unsigned char sum = 0;
+ int i;
+
+ /* calculate sum and verify checksum */
+
+ for (i = 0; i < WTGAHRS2_RSP_LENGTH - 1; i++)
+ {
+ sum += buffer[i];
+ }
+
+ if (sum != buffer[WTGAHRS2_RSP_LENGTH - 1])
+ {
+ return false;
+ }
+
+ switch (buffer[1])
+ {
+ case WTGAHRS2_ACCEL_INFO:
+ wtgahrs2_accel_data(rtdata, &buffer[2]);
+ break;
+
+ case WTGAHRS2_GYRO_INFO:
+ wtgahrs2_gyro_data(rtdata, &buffer[2]);
+ break;
+
+ case WTGAHRS2_MAG_INFO:
+ wtgahrs2_mag_data(rtdata, &buffer[2]);
+ break;
+
+ case WTGAHRS2_BARO_INFO:
+ wtgahrs2_baro_data(rtdata, &buffer[2]);
+ break;
+
+ case WTGAHRS2_GPS0_INFO:
+ case WTGAHRS2_GPS1_INFO:
+ case WTGAHRS2_GPS2_INFO:
+ wtgahrs2_gps_data(rtdata, &buffer[2], buffer[1]);
+ break;
+ }
+
+ return true;
+}
+
+static int wtgahrs2_thread(int argc, FAR char *argv[])
+{
+ FAR struct wtgahrs2_dev_s *rtdata = (FAR struct wtgahrs2_dev_s *)
+ ((uintptr_t)strtoul(argv[1], NULL, 0));
+ unsigned char buffer[8 * WTGAHRS2_RSP_LENGTH];
+ ssize_t count = 0;
+ ssize_t pos;
+
+ while (1)
+ {
+ count += file_read(&rtdata->file, buffer + count,
+ sizeof(buffer) - count);
+ for (pos = 0; pos < count; pos++)
+ {
+ if (buffer[pos] != WTGAHRS2_RSP_HEADER)
+ {
+ continue;
+ }
+
+ if (count - pos < WTGAHRS2_RSP_LENGTH)
+ {
+ memmove(buffer, buffer + pos, count - pos);
+ break;
+ }
+
+ if (wtgahrs2_process_data(rtdata, &buffer[pos]))
+ {
+ pos += WTGAHRS2_RSP_LENGTH - 1;
+ }
+ }
+
+ count -= pos;
+ }
+
+ return 0;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+int wtgahrs2_initialize(FAR const char *path)
+{
+ FAR struct wtgahrs2_dev_s *rtdata;
+ FAR struct wtgahrs2_sensor_s *tmp;
+#if CONFIG_SERIAL_TERMIOS
+ struct termios opt;
+#endif
+ FAR char *argv[2];
+ char arg1[16];
+ int ret;
+
+ if (!path)
+ {
+ snerr("Invaild path for serial interface\n");
+ return -EINVAL;
+ }
+
+ rtdata = kmm_zalloc(sizeof(struct wtgahrs2_dev_s));
+ if (!rtdata)
+ {
+ snerr("Memory cannot be allocated for wtgahrs2\n");
+ return -ENOMEM;
+ }
+
+ /* Open serial tty port and set baud rate */
+
+ ret = file_open(&rtdata->file, path, O_RDWR);
+ if (ret < 0)
+ {
+ snerr("Failed to open wtgahrs2 serial:%s, err:%d", path, ret);
+ goto open_err;
+ }
+
+#if CONFIG_SERIAL_TERMIOS
+ file_ioctl(&rtdata->file, TCGETS, &opt);
+ cfmakeraw(&opt);
+ cfsetispeed(&opt, B115200);
+ cfsetospeed(&opt, B115200);
+ file_ioctl(&rtdata->file, TCSETS, &opt);
+#endif
+
+ /* Accelerometer register */
+
+ tmp = &rtdata->dev[WTGAHRS2_ACCEL_IDX];
+ tmp->lower.ops = &g_wtgahrs2_ops;
+ tmp->lower.type = SENSOR_TYPE_ACCELEROMETER;
+ tmp->lower.buffer_bytes = sizeof(struct sensor_event_accel);
+ ret = sensor_register(&tmp->lower);
+ if (ret < 0)
+ {
+ goto accel_err;
+ }
+
+ /* Gyroscope register */
+
+ tmp = &rtdata->dev[WTGAHRS2_GYRO_IDX];
+ tmp->lower.ops = &g_wtgahrs2_ops;
+ tmp->lower.type = SENSOR_TYPE_GYROSCOPE;
+ tmp->lower.buffer_bytes = sizeof(struct sensor_event_gyro);
+ ret = sensor_register(&tmp->lower);
+ if (ret < 0)
+ {
+ goto gyro_err;
+ }
+
+ /* Magnetic register */
+
+ tmp = &rtdata->dev[WTGAHRS2_MAG_IDX];
+ tmp->lower.ops = &g_wtgahrs2_ops;
+ tmp->lower.type = SENSOR_TYPE_MAGNETIC_FIELD;
+ tmp->lower.buffer_bytes = sizeof(struct sensor_event_mag);
+ ret = sensor_register(&tmp->lower);
+ if (ret < 0)
+ {
+ goto mag_err;
+ }
+
+ /* Barometer register */
+
+ tmp = &rtdata->dev[WTGAHRS2_BARO_IDX];
+ tmp->lower.ops = &g_wtgahrs2_ops;
+ tmp->lower.type = SENSOR_TYPE_BAROMETER;
+ tmp->lower.buffer_bytes = sizeof(struct sensor_event_baro);
+ ret = sensor_register(&tmp->lower);
+ if (ret < 0)
+ {
+ goto baro_err;
+ }
+
+ /* GPS register */
+
+ tmp = &rtdata->dev[WTGAHRS2_GPS_IDX];
+ tmp->lower.ops = &g_wtgahrs2_ops;
+ tmp->lower.type = SENSOR_TYPE_GPS;
+ tmp->lower.buffer_bytes = sizeof(struct sensor_event_gps);
+ ret = sensor_register(&tmp->lower);
+ if (ret < 0)
+ {
+ goto gps_err;
+ }
+
+ /* Set sensor default attributes and enter unlock mode */
+
+ wtgahrs2_sendcmd(rtdata, g_wtgahrs2_unlock);
+
+ /* Set sensor default odr 200hz */
+
+ wtgahrs2_sendcmd(rtdata, g_wtgahrs2_odr_200hz);
+
+ /* Enable all sensor */
+
+ wtgahrs2_sendcmd(rtdata, g_wtgahrs2_enable_sensor);
+
+ snprintf(arg1, 16, "0x%" PRIxPTR, (uintptr_t)rtdata);
+ argv[0] = arg1;
+ argv[1] = NULL;
+
+ ret = kthread_create("wtgahrs2_thread", SCHED_PRIORITY_DEFAULT,
+ CONFIG_DEFAULT_TASK_STACKSIZE,
+ wtgahrs2_thread, argv);
+ if (ret < 0)
+ {
+ goto thr_err;
+ }
+
+ return ret;
+
+thr_err:
+ sensor_unregister(&rtdata->dev[WTGAHRS2_GPS_IDX].lower);
+gps_err:
+ sensor_unregister(&rtdata->dev[WTGAHRS2_BARO_IDX].lower);
+baro_err:
+ sensor_unregister(&rtdata->dev[WTGAHRS2_MAG_IDX].lower);
+mag_err:
+ sensor_unregister(&rtdata->dev[WTGAHRS2_GYRO_IDX].lower);
+gyro_err:
+ sensor_unregister(&rtdata->dev[WTGAHRS2_ACCEL_IDX].lower);
+accel_err:
+ file_close(&rtdata->file);
+open_err:
+ kmm_free(rtdata);
+ return ret;
+}
diff --git a/include/nuttx/sensors/wtgahrs2.h b/include/nuttx/sensors/wtgahrs2.h
new file mode 100644
index 0000000..7d86254
--- /dev/null
+++ b/include/nuttx/sensors/wtgahrs2.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+ * include/nuttx/sensors/wtgahrs2.h
+ * Driver for the Wit-Motion WTGAHRS2 accelerometer, gyroscope, magnetic,
+ * angle, barometer, temperature, gps sensors by serial interface with host
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you 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.
+ *
+ ****************************************************************************/
+
+#ifndef __INCLUDE_NUTTX_SENSORS_WTGAHRS2_H
+#define __INCLUDE_NUTTX_SENSORS_WTGAHRS2_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <nuttx/sensors/sensor.h>
+#include <nuttx/sensors/ioctl.h>
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/****************************************************************************
+ * Name: wtgahrs2_initialize
+ *
+ * Description:
+ * Initialize wrgahrs2 sensor module, it will create accelerometer,
+ * gyroscope, magnetic, barometer, gps character device.
+ *
+ * Input Parameters:
+ * devpath - The full path to the driver to read data source by serial tty.
+ *
+ * Returned Value:
+ * OK if the driver was successfully initialize; A negated errno value is
+ * returned on any failure.
+ ****************************************************************************/
+
+int wtgahrs2_initialize(FAR const char *path);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif