Running the LSM6DLS (IMU) zephyr example with nrf52840 based Xiao BLE Sense

Hi all,

I've been trying to get the samples/sensor/lsm6dsl example working with the nrf52840-based Xiao BLE Sense and have had no luck.

I guess that it's due to the power line for the sensor being connected to the P1.08

I dug into the xiao_ble_sense.dts and I can indeed see:

	lsm6ds3tr-c-en {
		compatible = "regulator-fixed-sync", "regulator-fixed";
		enable-gpios = <&gpio1 8 (NRF_GPIO_DRIVE_S0H1 | GPIO_ACTIVE_HIGH)>;
		regulator-name = "LSM6DS3TR_C_EN";
		regulator-boot-on;
		startup-delay-us = <3000>;
	};

However no matter how I try and drive it from the code the sensor refuses to initialize with the console output:

[00:00:00.794,647] <dbg> LSM6DSL: lsm6dsl_init_chip: failed to reboot device
[00:00:00.794,677] <err> LSM6DSL: Failed to initialize chip
*** Booting nRF Connect SDK d96769faceca ***
Begin init of lsm6ds3tr and regulator 
sensor: device not ready.

My code to run is based of the sample code for the sensor with the lsm6ds3tr_c_en modifications:

/*
 * Copyright (c) 2018 STMicroelectronics
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/drivers/sensor.h>
#include <stdio.h>
#include <zephyr/sys/util.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/drivers/regulator.h>

static const struct device *lsm6ds3tr_c_en;

static inline float out_ev(struct sensor_value *val)
{
	return (val->val1 + (float)val->val2 / 1000000);
}

static int print_samples;
static int lsm6dsl_trig_cnt;

static struct sensor_value accel_x_out, accel_y_out, accel_z_out;
static struct sensor_value gyro_x_out, gyro_y_out, gyro_z_out;
#if defined(CONFIG_LSM6DSL_EXT0_LIS2MDL)
static struct sensor_value magn_x_out, magn_y_out, magn_z_out;
#endif
#if defined(CONFIG_LSM6DSL_EXT0_LPS22HB)
static struct sensor_value press_out, temp_out;
#endif

#ifdef CONFIG_LSM6DSL_TRIGGER
static void lsm6dsl_trigger_handler(const struct device *dev,
				    const struct sensor_trigger *trig)
{
	static struct sensor_value accel_x, accel_y, accel_z;
	static struct sensor_value gyro_x, gyro_y, gyro_z;
#if defined(CONFIG_LSM6DSL_EXT0_LIS2MDL)
	static struct sensor_value magn_x, magn_y, magn_z;
#endif
#if defined(CONFIG_LSM6DSL_EXT0_LPS22HB)
	static struct sensor_value press, temp;
#endif
	lsm6dsl_trig_cnt++;

	sensor_sample_fetch_chan(dev, SENSOR_CHAN_ACCEL_XYZ);
	sensor_channel_get(dev, SENSOR_CHAN_ACCEL_X, &accel_x);
	sensor_channel_get(dev, SENSOR_CHAN_ACCEL_Y, &accel_y);
	sensor_channel_get(dev, SENSOR_CHAN_ACCEL_Z, &accel_z);

	/* lsm6dsl gyro */
	sensor_sample_fetch_chan(dev, SENSOR_CHAN_GYRO_XYZ);
	sensor_channel_get(dev, SENSOR_CHAN_GYRO_X, &gyro_x);
	sensor_channel_get(dev, SENSOR_CHAN_GYRO_Y, &gyro_y);
	sensor_channel_get(dev, SENSOR_CHAN_GYRO_Z, &gyro_z);

#if defined(CONFIG_LSM6DSL_EXT0_LIS2MDL)
	/* lsm6dsl external magn */
	sensor_sample_fetch_chan(dev, SENSOR_CHAN_MAGN_XYZ);
	sensor_channel_get(dev, SENSOR_CHAN_MAGN_X, &magn_x);
	sensor_channel_get(dev, SENSOR_CHAN_MAGN_Y, &magn_y);
	sensor_channel_get(dev, SENSOR_CHAN_MAGN_Z, &magn_z);
#endif

#if defined(CONFIG_LSM6DSL_EXT0_LPS22HB)
	/* lsm6dsl external press/temp */
	sensor_sample_fetch_chan(dev, SENSOR_CHAN_PRESS);
	sensor_channel_get(dev, SENSOR_CHAN_PRESS, &press);

	sensor_sample_fetch_chan(dev, SENSOR_CHAN_AMBIENT_TEMP);
	sensor_channel_get(dev, SENSOR_CHAN_AMBIENT_TEMP, &temp);
#endif

	if (print_samples) {
		print_samples = 0;

		accel_x_out = accel_x;
		accel_y_out = accel_y;
		accel_z_out = accel_z;

		gyro_x_out = gyro_x;
		gyro_y_out = gyro_y;
		gyro_z_out = gyro_z;

#if defined(CONFIG_LSM6DSL_EXT0_LIS2MDL)
		magn_x_out = magn_x;
		magn_y_out = magn_y;
		magn_z_out = magn_z;
#endif

#if defined(CONFIG_LSM6DSL_EXT0_LPS22HB)
		press_out = press;
		temp_out = temp;
#endif
	}

}
#endif

int main(void)
{
	int cnt = 0;
	char out_str[64];
	struct sensor_value odr_attr;
    const struct device *const lsm6dsl_dev = DEVICE_DT_GET_ONE(st_lsm6dsl);

	printk("Begin init of lsm6ds3tr and regulator \n");
    /* Initialize the regulator device */
	lsm6ds3tr_c_en = DEVICE_DT_GET(DT_PATH(lsm6ds3tr_c_en));
    if (!device_is_ready(lsm6ds3tr_c_en)) {
        printk("Regulator device not ready\n");
        return 0;
    }

    /* Enable the regulator */
    if (regulator_enable(lsm6ds3tr_c_en) < 0) {
        printk("Failed to enable regulator\n");
        return 0;
    }

	 k_sleep(K_MSEC(10000));

	
	if (!device_is_ready(lsm6dsl_dev)) {
		printk("sensor: device not ready.\n");
		return 0;
	}

	/* set accel/gyro sampling frequency to 104 Hz */
	odr_attr.val1 = 104;
	odr_attr.val2 = 0;

	if (sensor_attr_set(lsm6dsl_dev, SENSOR_CHAN_ACCEL_XYZ,
			    SENSOR_ATTR_SAMPLING_FREQUENCY, &odr_attr) < 0) {
		printk("Cannot set sampling frequency for accelerometer.\n");
		return 0;
	}

	if (sensor_attr_set(lsm6dsl_dev, SENSOR_CHAN_GYRO_XYZ,
			    SENSOR_ATTR_SAMPLING_FREQUENCY, &odr_attr) < 0) {
		printk("Cannot set sampling frequency for gyro.\n");
		return 0;
	}

#ifdef CONFIG_LSM6DSL_TRIGGER
	struct sensor_trigger trig;

	trig.type = SENSOR_TRIG_DATA_READY;
	trig.chan = SENSOR_CHAN_ACCEL_XYZ;

	if (sensor_trigger_set(lsm6dsl_dev, &trig, lsm6dsl_trigger_handler) != 0) {
		printk("Could not set sensor type and channel\n");
		return 0;
	}
#endif

	if (sensor_sample_fetch(lsm6dsl_dev) < 0) {
		printk("Sensor sample update error\n");
		return 0;
	}

	while (1) {
		/* Erase previous */
		printk("\0033\014");
		printf("LSM6DSL sensor samples:\n\n");

		/* lsm6dsl accel */
		sprintf(out_str, "accel x:%f ms/2 y:%f ms/2 z:%f ms/2",
							  out_ev(&accel_x_out),
							  out_ev(&accel_y_out),
							  out_ev(&accel_z_out));
		printk("%s\n", out_str);

		/* lsm6dsl gyro */
		sprintf(out_str, "gyro x:%f dps y:%f dps z:%f dps",
							   out_ev(&gyro_x_out),
							   out_ev(&gyro_y_out),
							   out_ev(&gyro_z_out));
		printk("%s\n", out_str);

#if defined(CONFIG_LSM6DSL_EXT0_LIS2MDL)
		/* lsm6dsl external magn */
		sprintf(out_str, "magn x:%f gauss y:%f gauss z:%f gauss",
							   out_ev(&magn_x_out),
							   out_ev(&magn_y_out),
							   out_ev(&magn_z_out));
		printk("%s\n", out_str);
#endif

#if defined(CONFIG_LSM6DSL_EXT0_LPS22HB)
		/* lsm6dsl external press/temp */
		sprintf(out_str, "press: %f kPa - temp: %f deg",
			out_ev(&press_out), out_ev(&temp_out));
		printk("%s\n", out_str);
#endif

		printk("loop:%d trig_cnt:%d\n\n", ++cnt, lsm6dsl_trig_cnt);

		print_samples = 1;
		k_sleep(K_MSEC(2000));
	}
}


And my prj.conf:
CONFIG_STDOUT_CONSOLE=y
CONFIG_I2C=y
CONFIG_SPI=n
CONFIG_SENSOR=y
CONFIG_LSM6DSL_TRIGGER_GLOBAL_THREAD=y
CONFIG_CBPRINTF_FP_SUPPORT=y

CONFIG_LOG=y
CONFIG_LOG_DEFAULT_LEVEL=3
CONFIG_SENSOR_LOG_LEVEL_DBG=y

CONFIG_UART_CONSOLE=y
CONFIG_UART_INTERRUPT_DRIVEN=y
CONFIG_UART_LINE_CTRL=y

I am trying to drive this the proper way but am I missing something obvious?

Should I just ignore the config and drive P1.08 manually?

Thanks for taking a look!
I'm using nRF Connect SDK v2.6.0 (latest available at the time of posting)

Parents
  • Hello All,

    I have gotten the IMU to work.

    There is one thing that changes form the sample code vs what the new driver needs.

    I think with the zephyr toolchain/version being updated the driver must have changed.

    You can not change the sampling rate in code instead you have to use the following project config lines:

    CONFIG_LSM6DSL_GYRO_ODR=1
    CONFIG_LSM6DSL_ACCEL_ODR=1
    I found that after this I just use the following functions to check if the device is working and to pull the accleration data:
    ```
    #include "IMU.h"

    LOG_MODULE_REGISTER(imu, LOG_LEVEL_INF);

    int IMUSetup(){
        int err = 0;
        if (!device_is_ready(IMU_DEVICE)) {
                    LOG_ERR("IMU device is not ready");
                    return -1;
            } else {
                    LOG_INF("IMU DEVICE IS READY");
            }

        return 0;
    };

    int readIMUData(){
        int err = 0;

        static struct sensor_value accel_x, accel_y, accel_z;
        static struct sensor_value gyro_x, gyro_y, gyro_z;


        // Fetch accelerometer data
        err = sensor_sample_fetch_chan(IMU_DEVICE, SENSOR_CHAN_ACCEL_XYZ);
        if (err < 0) {
            LOG_ERR("Error fetching accelerometer data: %d", err);
            return;  // Exit or handle the error appropriately
        }

        // Get accelerometer channels
        err = sensor_channel_get(IMU_DEVICE, SENSOR_CHAN_ACCEL_X, &accel_x);
        if (err < 0) {
            LOG_ERR("Error getting accelerometer X channel: %d", err);
        }

        err = sensor_channel_get(IMU_DEVICE, SENSOR_CHAN_ACCEL_Y, &accel_y);
        if (err < 0) {
            LOG_ERR("Error getting accelerometer Y channel: %d", err);
        }

        err = sensor_channel_get(IMU_DEVICE, SENSOR_CHAN_ACCEL_Z, &accel_z);
        if (err < 0) {
            LOG_ERR("Error getting accelerometer Z channel: %d", err);
        }

        // Fetch gyroscope data
        err = sensor_sample_fetch_chan(IMU_DEVICE, SENSOR_CHAN_GYRO_XYZ);
        if (err < 0) {
            LOG_ERR("Error fetching gyroscope data: %d", err);
            return;  // Exit or handle the error appropriately
        }

        // Get gyroscope channels
        err = sensor_channel_get(IMU_DEVICE, SENSOR_CHAN_GYRO_X, &gyro_x);
        if (err < 0) {
            LOG_ERR("Error getting gyroscope X channel: %d", err);
        }

        err = sensor_channel_get(IMU_DEVICE, SENSOR_CHAN_GYRO_Y, &gyro_y);
        if (err < 0) {
            LOG_ERR("Error getting gyroscope Y channel: %d", err);
        }

        err = sensor_channel_get(IMU_DEVICE, SENSOR_CHAN_GYRO_Z, &gyro_z);
        if (err < 0) {
            LOG_ERR("Error getting gyroscope Z channel: %d", err);
        }

        // Print accelerometer data
        LOG_INF("Accelerometer (m/s^2):\n\tX: %d.%06d\n\tY: %d.%06d\n\tZ: %d.%06d",
                accel_x.val1, accel_x.val2,
                accel_y.val1, accel_y.val2,
                accel_z.val1, accel_z.val2);

        // Print gyroscope data
        LOG_INF("Gyroscope (rad/s):\n\tX: %d.%06d\n\tY: %d.%06d\n\tZ: %d.%06d",
                gyro_x.val1, gyro_x.val2,
                gyro_y.val1, gyro_y.val2,
                gyro_z.val1, gyro_z.val2);
    }
    ```
    The I used the default device tree items and have this overlay done to increase the startup delay as recommended by other posts.

    ```

    / {
        lsm6ds3tr-c-en {
            startup-delay-us = <10000>;
        };
    };

    ```

    I am using 2.7 toolchain and the 2.7 SDK.

    Let me know if you have more questions, I think these were the most important points to consider

    #include "IMU.h"
    
    LOG_MODULE_REGISTER(imu, LOG_LEVEL_INF);
    
    int IMUSetup(){
        int err = 0; 
        if (!device_is_ready(IMU_DEVICE)) {
                    LOG_ERR("IMU device is not ready");
                    return -1;
            } else {
                    LOG_INF("IMU DEVICE IS READY");
            }
    
        return 0; 
    };
    
    int readIMUData(){
        int err = 0; 
    
        static struct sensor_value accel_x, accel_y, accel_z;
    	static struct sensor_value gyro_x, gyro_y, gyro_z;
    
    
        // Fetch accelerometer data
        err = sensor_sample_fetch_chan(IMU_DEVICE, SENSOR_CHAN_ACCEL_XYZ);
        if (err < 0) {
            LOG_ERR("Error fetching accelerometer data: %d", err);
            return;  // Exit or handle the error appropriately
        }
    
        // Get accelerometer channels
        err = sensor_channel_get(IMU_DEVICE, SENSOR_CHAN_ACCEL_X, &accel_x);
        if (err < 0) {
            LOG_ERR("Error getting accelerometer X channel: %d", err);
        }
    
        err = sensor_channel_get(IMU_DEVICE, SENSOR_CHAN_ACCEL_Y, &accel_y);
        if (err < 0) {
            LOG_ERR("Error getting accelerometer Y channel: %d", err);
        }
    
        err = sensor_channel_get(IMU_DEVICE, SENSOR_CHAN_ACCEL_Z, &accel_z);
        if (err < 0) {
            LOG_ERR("Error getting accelerometer Z channel: %d", err);
        }
    
        // Fetch gyroscope data
        err = sensor_sample_fetch_chan(IMU_DEVICE, SENSOR_CHAN_GYRO_XYZ);
        if (err < 0) {
            LOG_ERR("Error fetching gyroscope data: %d", err);
            return;  // Exit or handle the error appropriately
        }
    
        // Get gyroscope channels
        err = sensor_channel_get(IMU_DEVICE, SENSOR_CHAN_GYRO_X, &gyro_x);
        if (err < 0) {
            LOG_ERR("Error getting gyroscope X channel: %d", err);
        }
    
        err = sensor_channel_get(IMU_DEVICE, SENSOR_CHAN_GYRO_Y, &gyro_y);
        if (err < 0) {
            LOG_ERR("Error getting gyroscope Y channel: %d", err);
        }
    
        err = sensor_channel_get(IMU_DEVICE, SENSOR_CHAN_GYRO_Z, &gyro_z);
        if (err < 0) {
            LOG_ERR("Error getting gyroscope Z channel: %d", err);
        }
    
        // Print accelerometer data
        LOG_INF("Accelerometer (m/s^2):\n\tX: %d.%06d\n\tY: %d.%06d\n\tZ: %d.%06d",
                accel_x.val1, accel_x.val2, 
                accel_y.val1, accel_y.val2, 
                accel_z.val1, accel_z.val2);
    
        // Print gyroscope data
        LOG_INF("Gyroscope (rad/s):\n\tX: %d.%06d\n\tY: %d.%06d\n\tZ: %d.%06d",
                gyro_x.val1, gyro_x.val2, 
                gyro_y.val1, gyro_y.val2, 
                gyro_z.val1, gyro_z.val2);
    }

Reply
  • Hello All,

    I have gotten the IMU to work.

    There is one thing that changes form the sample code vs what the new driver needs.

    I think with the zephyr toolchain/version being updated the driver must have changed.

    You can not change the sampling rate in code instead you have to use the following project config lines:

    CONFIG_LSM6DSL_GYRO_ODR=1
    CONFIG_LSM6DSL_ACCEL_ODR=1
    I found that after this I just use the following functions to check if the device is working and to pull the accleration data:
    ```
    #include "IMU.h"

    LOG_MODULE_REGISTER(imu, LOG_LEVEL_INF);

    int IMUSetup(){
        int err = 0;
        if (!device_is_ready(IMU_DEVICE)) {
                    LOG_ERR("IMU device is not ready");
                    return -1;
            } else {
                    LOG_INF("IMU DEVICE IS READY");
            }

        return 0;
    };

    int readIMUData(){
        int err = 0;

        static struct sensor_value accel_x, accel_y, accel_z;
        static struct sensor_value gyro_x, gyro_y, gyro_z;


        // Fetch accelerometer data
        err = sensor_sample_fetch_chan(IMU_DEVICE, SENSOR_CHAN_ACCEL_XYZ);
        if (err < 0) {
            LOG_ERR("Error fetching accelerometer data: %d", err);
            return;  // Exit or handle the error appropriately
        }

        // Get accelerometer channels
        err = sensor_channel_get(IMU_DEVICE, SENSOR_CHAN_ACCEL_X, &accel_x);
        if (err < 0) {
            LOG_ERR("Error getting accelerometer X channel: %d", err);
        }

        err = sensor_channel_get(IMU_DEVICE, SENSOR_CHAN_ACCEL_Y, &accel_y);
        if (err < 0) {
            LOG_ERR("Error getting accelerometer Y channel: %d", err);
        }

        err = sensor_channel_get(IMU_DEVICE, SENSOR_CHAN_ACCEL_Z, &accel_z);
        if (err < 0) {
            LOG_ERR("Error getting accelerometer Z channel: %d", err);
        }

        // Fetch gyroscope data
        err = sensor_sample_fetch_chan(IMU_DEVICE, SENSOR_CHAN_GYRO_XYZ);
        if (err < 0) {
            LOG_ERR("Error fetching gyroscope data: %d", err);
            return;  // Exit or handle the error appropriately
        }

        // Get gyroscope channels
        err = sensor_channel_get(IMU_DEVICE, SENSOR_CHAN_GYRO_X, &gyro_x);
        if (err < 0) {
            LOG_ERR("Error getting gyroscope X channel: %d", err);
        }

        err = sensor_channel_get(IMU_DEVICE, SENSOR_CHAN_GYRO_Y, &gyro_y);
        if (err < 0) {
            LOG_ERR("Error getting gyroscope Y channel: %d", err);
        }

        err = sensor_channel_get(IMU_DEVICE, SENSOR_CHAN_GYRO_Z, &gyro_z);
        if (err < 0) {
            LOG_ERR("Error getting gyroscope Z channel: %d", err);
        }

        // Print accelerometer data
        LOG_INF("Accelerometer (m/s^2):\n\tX: %d.%06d\n\tY: %d.%06d\n\tZ: %d.%06d",
                accel_x.val1, accel_x.val2,
                accel_y.val1, accel_y.val2,
                accel_z.val1, accel_z.val2);

        // Print gyroscope data
        LOG_INF("Gyroscope (rad/s):\n\tX: %d.%06d\n\tY: %d.%06d\n\tZ: %d.%06d",
                gyro_x.val1, gyro_x.val2,
                gyro_y.val1, gyro_y.val2,
                gyro_z.val1, gyro_z.val2);
    }
    ```
    The I used the default device tree items and have this overlay done to increase the startup delay as recommended by other posts.

    ```

    / {
        lsm6ds3tr-c-en {
            startup-delay-us = <10000>;
        };
    };

    ```

    I am using 2.7 toolchain and the 2.7 SDK.

    Let me know if you have more questions, I think these were the most important points to consider

    #include "IMU.h"
    
    LOG_MODULE_REGISTER(imu, LOG_LEVEL_INF);
    
    int IMUSetup(){
        int err = 0; 
        if (!device_is_ready(IMU_DEVICE)) {
                    LOG_ERR("IMU device is not ready");
                    return -1;
            } else {
                    LOG_INF("IMU DEVICE IS READY");
            }
    
        return 0; 
    };
    
    int readIMUData(){
        int err = 0; 
    
        static struct sensor_value accel_x, accel_y, accel_z;
    	static struct sensor_value gyro_x, gyro_y, gyro_z;
    
    
        // Fetch accelerometer data
        err = sensor_sample_fetch_chan(IMU_DEVICE, SENSOR_CHAN_ACCEL_XYZ);
        if (err < 0) {
            LOG_ERR("Error fetching accelerometer data: %d", err);
            return;  // Exit or handle the error appropriately
        }
    
        // Get accelerometer channels
        err = sensor_channel_get(IMU_DEVICE, SENSOR_CHAN_ACCEL_X, &accel_x);
        if (err < 0) {
            LOG_ERR("Error getting accelerometer X channel: %d", err);
        }
    
        err = sensor_channel_get(IMU_DEVICE, SENSOR_CHAN_ACCEL_Y, &accel_y);
        if (err < 0) {
            LOG_ERR("Error getting accelerometer Y channel: %d", err);
        }
    
        err = sensor_channel_get(IMU_DEVICE, SENSOR_CHAN_ACCEL_Z, &accel_z);
        if (err < 0) {
            LOG_ERR("Error getting accelerometer Z channel: %d", err);
        }
    
        // Fetch gyroscope data
        err = sensor_sample_fetch_chan(IMU_DEVICE, SENSOR_CHAN_GYRO_XYZ);
        if (err < 0) {
            LOG_ERR("Error fetching gyroscope data: %d", err);
            return;  // Exit or handle the error appropriately
        }
    
        // Get gyroscope channels
        err = sensor_channel_get(IMU_DEVICE, SENSOR_CHAN_GYRO_X, &gyro_x);
        if (err < 0) {
            LOG_ERR("Error getting gyroscope X channel: %d", err);
        }
    
        err = sensor_channel_get(IMU_DEVICE, SENSOR_CHAN_GYRO_Y, &gyro_y);
        if (err < 0) {
            LOG_ERR("Error getting gyroscope Y channel: %d", err);
        }
    
        err = sensor_channel_get(IMU_DEVICE, SENSOR_CHAN_GYRO_Z, &gyro_z);
        if (err < 0) {
            LOG_ERR("Error getting gyroscope Z channel: %d", err);
        }
    
        // Print accelerometer data
        LOG_INF("Accelerometer (m/s^2):\n\tX: %d.%06d\n\tY: %d.%06d\n\tZ: %d.%06d",
                accel_x.val1, accel_x.val2, 
                accel_y.val1, accel_y.val2, 
                accel_z.val1, accel_z.val2);
    
        // Print gyroscope data
        LOG_INF("Gyroscope (rad/s):\n\tX: %d.%06d\n\tY: %d.%06d\n\tZ: %d.%06d",
                gyro_x.val1, gyro_x.val2, 
                gyro_y.val1, gyro_y.val2, 
                gyro_z.val1, gyro_z.val2);
    }

Children
No Data
Related