Skip to main content

Accelerometer Sample

Introduction

The Accelerometer sample reads acceleration data from the on-board LIS2DH12 accelerometer and prints the X, Y, and Z values to the console. The accelerometer is accessed using Zephyr's sensor API and device tree. This sample is compatible with the following boards:

Download

AccelerometerNCS v3.2.1

Project configuration

The application is configured in the prj.conf file:

CONFIG_NEWLIB_LIBC=y
CONFIG_NEWLIB_LIBC_FLOAT_PRINTF=y

CONFIG_I2C=y

CONFIG_SENSOR=y
CONFIG_LIS2DH=y
CONFIG_LIS2DH_ACCEL_RANGE_8G=y
CONFIG_LIS2DH_ODR_2=y

CONFIG_NEWLIB_LIBC and CONFIG_NEWLIB_LIBC_FLOAT_PRINTF enable the Newlib C library with floating-point printf support, needed to print the acceleration values.

CONFIG_I2C enables the I2C bus driver, which is needed for the sensor library to communicate with the accelerometer.

CONFIG_SENSOR enables the sensor subsystem. This is a dependency of the CONFIG_LIS2DH option.

CONFIG_LIS2DH enables the LIS2DH driver. The LIS2DH12 on the Icarus boards is compatible with this driver.

CONFIG_LIS2DH_ACCEL_RANGE_8G sets the measuring range to +/- 8G. This can be configured from +/- 2G up to +/- 16G.

CONFIG_LIS2DH_ODR_2 sets the output data rate to 10 Hz.

The full list of available options can be found by searching "LIS2DH" at Zephyr's Kconfig Search.

The sysbuild.conf file enables MCUBoot so the sample can be flashed over USB:

SB_CONFIG_BOOTLOADER_MCUBOOT=y

Code explanation

This sample contains two source files: accelerometer.c and main.c. The sensor logic is contained in accelerometer.c.

Device tree reference

The accelerometer is accessed through its device tree alias. A reference is obtained in the init_accelerometer function:

#define ACCEL_NODE DT_ALIAS(accel0)

static const struct device *accel;

bool init_accelerometer(void)
{
accel = DEVICE_DT_GET(ACCEL_NODE);

if (!device_is_ready(accel)) {
printk("Error: accelerometer device not ready\n");
return false;
}

return true;
}

DEVICE_DT_GET returns a pointer to the device with the alias accel0 from the device tree. The device_is_ready check ensures the driver initialized successfully.

Reading sensor data

The get_accelerometer_data function fetches a sample and reads each axis channel, converting the values to doubles:

void get_accelerometer_data(double *x_accel, double *y_accel, double *z_accel)
{
struct sensor_value value_x, value_y, value_z;

sensor_sample_fetch(accel);

sensor_channel_get(accel, SENSOR_CHAN_ACCEL_X, &value_x);
*x_accel = sensor_value_to_double(&value_x);

sensor_channel_get(accel, SENSOR_CHAN_ACCEL_Y, &value_y);
*y_accel = sensor_value_to_double(&value_y);

sensor_channel_get(accel, SENSOR_CHAN_ACCEL_Z, &value_z);
*z_accel = sensor_value_to_double(&value_z);
}

sensor_sample_fetch triggers a new measurement. sensor_channel_get retrieves the value for each axis, and sensor_value_to_double converts the sensor_value struct to a double.

Main loop

In main.c, the accelerometer is initialized and then read in a loop. The acceleration values are printed to the console in m/s²:

if (!init_accelerometer()) {
return -1;
}

while (1) {
double x_accel = 0;
double y_accel = 0;
double z_accel = 0;

get_accelerometer_data(&x_accel, &y_accel, &z_accel);

printk("Acceleration values:\n");
printk("-------------------------------------------------------------------------------\n");
printf("X: %lf (m/s^2), Y: %lf (m/s^2), Z: %lf (m/s^2)\n",
x_accel, y_accel, z_accel);
printk("-------------------------------------------------------------------------------\n");

k_sleep(K_MSEC(200));
}
Was this page helpful?