samples: sensor: 6DOF motion DRDY generic sample

It reports IMU 6-axis accelerometer and gyroscope data
using DRDY interrupt.

Signed-off-by: Aurelie Fontaine <aurelie.fontaine@tdk.com>
This commit is contained in:
Aurelie Fontaine 2024-12-05 18:06:06 +01:00 committed by Benjamin Cabé
parent 78c62d495f
commit 0b9b2fbb5e
7 changed files with 293 additions and 0 deletions

View file

@ -0,0 +1,12 @@
#
# Copyright (c) 2024 TDK Invensense
#
# SPDX-License-Identifier: Apache-2.0
#
cmake_minimum_required(VERSION 3.20.0)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(6dof_motion_drdy)
FILE(GLOB app_sources src/*.c)
target_sources(app PRIVATE ${app_sources})

View file

@ -0,0 +1,56 @@
.. zephyr:code-sample:: 6dof_motion_drdy
:name: Generic 6DOF Motion Dataready
:relevant-api: sensor_interface
Get 6-Axis accelerometer and gyroscope data from a sensor (data ready interrupt mode).
Overview
********
This sample application periodically (100 Hz) measures the 6-axis IMU sensor with
temperature, acceleration, and angular velocity, displaying the
values on the console along with a timestamp since startup.
Trigger options could be configured through KConfig.
Wiring
******
This sample uses an external breakout for the sensor. A devicetree
overlay must be provided to identify the 6-axis motion sensor, the SPI or I2C bus interface and the interrupt
sensor GPIO.
Building and Running
********************
This sample supports up to 6-Axis IMU devices. Each device needs
to be aliased as ``6dof-motion-drdyN`` where ``N`` goes from ``0`` to ``9``. For example:
.. code-block:: devicetree
/ {
aliases {
6dof-motion-drdy0 = &icm42670p;
};
};
Make sure the aliases are in devicetree, then build and run with:
.. zephyr-app-commands::
:zephyr-app: samples/sensor/6dof_motion_drdy
:board: nrf52dk/nrf52832
:goals: build flash
Sample Output
=============
.. code-block:: console
Found device "icm42670p@68", getting sensor data
[0:00:01.716]: temp 23.00 Cel accel 0.150839 -0.140065 9.994899 m/s/s gyro -0.001597 0.005859 0.001597 rad/s
[0:00:01.726]: temp 23.00 Cel accel 0.140065 -0.146050 9.988914 m/s/s gyro -0.002663 0.005859 0.003195 rad/s
[0:00:01.736]: temp 23.50 Cel accel 0.146050 -0.130487 9.988914 m/s/s gyro -0.001597 0.006391 0.003195 rad/s
[0:00:01.746]: temp 23.00 Cel accel 0.149642 -0.136473 9.990111 m/s/s gyro -0.002663 0.004261 0.002663 rad/s
[0:00:01.756]: temp 23.00 Cel accel 0.146050 -0.136473 9.979337 m/s/s gyro -0.002130 0.005326 0.001597 rad/s
[0:00:01.766]: temp 23.00 Cel accel 0.136473 -0.147247 9.986519 m/s/s gyro -0.001065 0.005859 0.002663 rad/s
<repeats endlessly>

View file

@ -0,0 +1,43 @@
/*
* Copyright (c) 2024, TDK Invensense
*
* SPDX-License-Identifier: Apache-2.0
*/
/*
* Get a node identifier for 6-axis IMU sensor.
*/
/ {
aliases {
6dof-motion-drdy0 = &icm42670p;
};
};
/*
* Example configuration of a ICM42670-P device on i2c0 compatible with an Arduino I2C bus.
*
* Device address 0x68 is assumed. Your device may have a different
* address; check your device documentation if unsure.
*
* Configure 100Hz IMU data reporting
*/
&arduino_i2c {
status = "okay";
icm42670p: icm42670p@68 {
compatible = "invensense,icm42670p";
reg = <0x68>;
int-gpios = <&arduino_header 8 GPIO_ACTIVE_HIGH>; /* D2 */
accel-hz = <100>;
gyro-hz = <100>;
accel-fs = <16>;
gyro-fs = <2000>;
};
};
/*
* Increase native UART speed to report all IMU data at 100Hz.
*/
&uart0 {
compatible = "nordic,nrf-uarte";
current-speed = <1000000>;
};

View file

@ -0,0 +1,41 @@
/*
* Copyright (c) 2024, TDK Invensense
*
* SPDX-License-Identifier: Apache-2.0
*/
/*
* Get a node identifier for 6-axis IMU sensor.
*/
/ {
aliases {
6dof-motion-drdy0 = &icm42670p;
};
};
/* Example configuration of a ICM42670-P device on spi2 compatible with an Arduino SPI bus.
*
* Configure 100Hz IMU data reporting
*/
&arduino_spi {
status = "okay";
cs-gpios = <&arduino_header 14 GPIO_ACTIVE_LOW>; /* D8 */
icm42670p: icm42670p@0 {
compatible = "invensense,icm42670p";
reg = <0>;
spi-max-frequency = <1000000>; /* conservatively set to 1MHz */
int-gpios = <&arduino_header 8 GPIO_ACTIVE_HIGH>; /* D2 */
accel-hz = <100>;
gyro-hz = <100>;
accel-fs = <16>;
gyro-fs = <2000>;
};
};
/*
* Increase native UART speed to report all IMU data at 100Hz.
*/
&uart0 {
compatible = "nordic,nrf-uarte";
current-speed = <1000000>;
};

View file

@ -0,0 +1,19 @@
#
# Copyright (c) 2024 TDK Invensense
#
# SPDX-License-Identifier: Apache-2.0
#
CONFIG_SENSOR=y
CONFIG_LOG=y
CONFIG_SENSOR_LOG_LEVEL_DBG=n
# Floating point format support
# Selecting this increases stack size requirements slightly, but increases code size significantly.
CONFIG_CBPRINTF_FP_SUPPORT=y
# nrf52dk/nrf52832 specific
CONFIG_USE_SEGGER_RTT=n
# Trigger mode: sample is using interrupt triggering
CONFIG_ICM42670_TRIGGER_OWN_THREAD=y

View file

@ -0,0 +1,9 @@
sample:
name: 6DOF Motion dataready sample
tests:
sample.sensor.6dof_motion_drdy:
build_only: true
tags: sensors
filter: dt_alias_exists("6dof_motion_drdy0")
integration_platforms:
- nrf52dk/nrf52832

View file

@ -0,0 +1,113 @@
/*
* Copyright (c) 2024 TDK Invensense
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/devicetree.h>
#include <zephyr/drivers/sensor.h>
#include <stdio.h>
static struct sensor_trigger data_trigger;
/* Flag set from IMU device irq handler */
static volatile int irq_from_device;
/*
* Get a device structure from a devicetree node from alias
* "6dof_motion_drdy0".
*/
static const struct device *get_6dof_motion_device(void)
{
const struct device *const dev = DEVICE_DT_GET(DT_ALIAS(6dof_motion_drdy0));
if (!device_is_ready(dev)) {
printk("\nError: Device \"%s\" is not ready; "
"check the driver initialization logs for errors.\n",
dev->name);
return NULL;
}
printk("Found device \"%s\", getting sensor data\n", dev->name);
return dev;
}
static const char *now_str(void)
{
static char buf[16]; /* ...HH:MM:SS.MMM */
uint32_t now = k_uptime_get_32();
unsigned int ms = now % MSEC_PER_SEC;
unsigned int s;
unsigned int min;
unsigned int h;
now /= MSEC_PER_SEC;
s = now % 60U;
now /= 60U;
min = now % 60U;
now /= 60U;
h = now;
snprintf(buf, sizeof(buf), "%u:%02u:%02u.%03u", h, min, s, ms);
return buf;
}
static void handle_6dof_motion_drdy(const struct device *dev, const struct sensor_trigger *trig)
{
if (trig->type == SENSOR_TRIG_DATA_READY) {
int rc = sensor_sample_fetch_chan(dev, trig->chan);
if (rc < 0) {
printf("sample fetch failed: %d\n", rc);
printf("cancelling trigger due to failure: %d\n", rc);
(void)sensor_trigger_set(dev, trig, NULL);
return;
} else if (rc == 0) {
irq_from_device = 1;
}
}
}
int main(void)
{
const struct device *dev = get_6dof_motion_device();
struct sensor_value accel[3];
struct sensor_value gyro[3];
struct sensor_value temperature;
if (dev == NULL) {
return 0;
}
data_trigger = (struct sensor_trigger){
.type = SENSOR_TRIG_DATA_READY,
.chan = SENSOR_CHAN_ALL,
};
if (sensor_trigger_set(dev, &data_trigger, handle_6dof_motion_drdy) < 0) {
printf("Cannot configure data trigger!!!\n");
return 0;
}
k_sleep(K_MSEC(1000));
while (1) {
if (irq_from_device) {
sensor_channel_get(dev, SENSOR_CHAN_ACCEL_XYZ, accel);
sensor_channel_get(dev, SENSOR_CHAN_GYRO_XYZ, gyro);
sensor_channel_get(dev, SENSOR_CHAN_DIE_TEMP, &temperature);
printf("[%s]: temp %.2f Cel "
" accel %f %f %f m/s/s "
" gyro %f %f %f rad/s\n",
now_str(), sensor_value_to_double(&temperature),
sensor_value_to_double(&accel[0]), sensor_value_to_double(&accel[1]),
sensor_value_to_double(&accel[2]), sensor_value_to_double(&gyro[0]),
sensor_value_to_double(&gyro[1]), sensor_value_to_double(&gyro[2]));
irq_from_device = 0;
}
}
return 0;
}