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
  • After much confusion and life interruptions it would seem that I do have this working, via the LSM6DSL sample out of the box, or so I think.

    I was having much trouble with different things, in one case the app would crash without writing to the UART unless I stepped through the initialization with the debugger, in another case it would not flash due to some obscure overflow error.

    So, maybe this is all just a figment of my imagination.

    My setup is:
    - running within a Docker image
    - using VSCode via its remote container connected to the Docker image
    - nRFConnect VSCode extension
    - Xiao board on a Seeed Xiao expansion board
    - Uploading via Segger J-Link EDU
    - On Linux

    At the time of the above weirdness I had changed the nrfConnect tools version number, for some silly reason, from 2.5.2 to 2.6.0.
    I don't know if that's when things fell apart or not. But, I did hear on a webcast today that the presenter was having some issues with the later 2.6.0 version of the tools, so perhaps it did have some impact??

    At the same time I was trying to implement a version of LSM6DS3 as seen here: https://iwasz.pl/electronics/2021-06-18-out-of-tree-zephyr-module.md/     Got nowhere except the above debug problem.

    Then I changed the nRFConnect tool version back to 2.5.2 and went way for a few days, then things started working, don't ask why though. (Perhaps the local total eclipse fixed it)

    The versions I believe I'm currently using, and were I found the version info:

    Seeed Xiao bootloader: (double click Xiao reset button)
    ------------------------
    UF2 Bootloader 0.6.1 lib/nrfx (v2.0.0) lib/tinyusb (0.10.1-293-gaf8e5a90) lib/uf2 (remotes/origin/configupdate-9-gadbb8c7)
    Model: Seeed XIAO nRF52840
    Board-ID: Seeed_XIAO_nRF52840_Sense
    SoftDevice: S140 version 7.3.0
    Date: Nov 12 2021

    OS/SDKs
    ----------
    Zephyr
    --------
    source: github.com/.../sdk-zephyr
    3.4.99.0 (VERSION file) A Nordic downstream version I'm pretty sure
    git HEAD: 2e2523efe52a7ac89f0567b8798fd857b1e71ae3"


    nRF Connect SDK
    ----------------
    source: github.com/.../sdk-nrf
    2.5.0 (VERSION file)
    git HEAD: 1fae141fc6713dd331b797fc96c90dc84552242d

    nRFX Common Libraries (nRFxlib)
    ---------------------------------
    github.com/.../sdk-nrfxlib
    2.5.0 (.git/FETCH_HEAD)
    git HEAD: 78cc07ed7c9f168c3d6316db5af969ac5f7c977a

    nRF Tool Chain
    ---------------
    loaded via VSCode nRFConnect extension
    nRFConnect SDK ToolChain: 2.5.20231017.513615545433 (From build output)


    Versions reported from build output:
    ------------------------------------------
    -- CMake version: 3.20.5
    -- Using NCS Toolchain 2.5.20231017.513615545433 for building.
    -- Found Python3: ~/ncs/toolchains/7795df4459/usr/local/bin/python3 (found suitable version "3.8.2")
    -- Found west (found suitable version "1.1.0")
    -- Board: xiao_ble_sense
    -- Found host-tools: zephyr 0.16.1 (~/ncs/toolchains/7795df4459/opt/zephyr-sdk)
    -- Found toolchain: zephyr 0.16.1 (~/ncs/toolchains/7795df4459/opt/zephyr-sdk)
    -- Found Dtc: ~/ncs/toolchains/7795df4459/usr/local/bin/dtc (found suitable version "1.4.7", minimum required is "1.4.6")
    -- Found BOARD.dts: ~/ncs/v2.5.0/zephyr/boards/arm/xiao_ble/xiao_ble_sense.dts
    -- The C compiler identification is GNU 12.2.0
    -- The CXX compiler identification is GNU 12.2.0
    -- The ASM compiler identification is GNU
    -- Found assembler: ~/ncs/toolchains/7795df4459/opt/zephyr-sdk/arm-zephyr-eabi/bin/arm-zephyr-eabi-gcc
    -- Zephyr version: 3.4.99 (~/ncs/v2.5.0/zephyr), build: 2e2523efe52a

    I suppose when the moon comes around again it will fall apart again...

  • Thank you for your input !

    This is wild, what do you think is causing this shaky operation?

    Oh and I also followed the out of tree zephyr module repo but then I realized that all that changes is the I2C address and that is defined in the configuration in the recent versions of Zephyr.

  • Ughh, my message to you has been marked as spam by the mods, can you please help at least with un-marking the message as spam, thank you!

  • That's really strange!

    My setup:
    Seeed XIAO nrf52840 Sense running UF2 Bootloader 0.6.1 lib/nrfx (v2.0.0) lib/tinyusb (0.10.1-293-gaf8e5a90) lib/uf2 (remotes/origin/configupdate-9-gadbb8c7)
    SoftDevice: S140 version 7.3.0
    NCS 2.6.1
    nRF Connect SDK v3.5.99-ncs1-1
    CMake 3.26.4
    MacOS Ventura 13.6.6

    I am flashing manually by copying the UF2 or using a custom west script for automated flashing via USB. My XIAO board is not connected to anything (not even breadboard).

    I have uploaded the source and complied binaries here. If this binary works in your device then issue can be somewhere in upload, otherwise there is some hidden variable as you stated previously.

    Would be great if can share your working UF2, hex and DTS file from build/zephyr/. Then I can diff with my files and lookup the variables. I am assuming you are using the same C code as mentioned by mentarus or this example.

    I did check the device status and not sure if this is correct. The LSM6 address is correct though.

    You can compare by adding the following flags to prj.conf and running the commands over serial terminal.

    CONFIG_SHELL=y
    CONFIG_I2C_SHELL=y
    CONFIG_SENSOR_SHELL=y

    PS:  Still not working, but going all in to fix this once and for all.

    I will try tomorrow on Ubuntu and update here if it works or not.

Reply Children
No Data
Related