Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lis2de12 sensor driver giving 0 values #83794

Open
narangmayank opened this issue Jan 10, 2025 · 3 comments
Open

lis2de12 sensor driver giving 0 values #83794

narangmayank opened this issue Jan 10, 2025 · 3 comments
Assignees
Labels
area: Sensors Sensors bug The issue is a bug, or the PR is fixing a bug

Comments

@narangmayank
Copy link

narangmayank commented Jan 10, 2025

Describe the bug

Lis2de12 sensor is connected to nRF52840 DK via SPI interface. Chip ID is being read successfully verifies SPI bus is okay and config setting (odr, g-value) is also set successfully i.e (see below I read the register manually to cross check) but after that when you call sensor_sample_fetch() api it will give 0 values always.

To Reproduce

Connect the LIS2DE12 sensor to the nRF52840 kit via SPI_1 and build the sample attached below and run or alternatively change the host and SPI setting and build for that.

Expected behavior

IMU values should print on the console

Impact

showstopper

Logs and console output

DTS

&i2c0 {	status = "disabled";};
&spi0 {	status = "disabled";};
&i2c1 {	status = "disabled";};
	
&spi1 {
    compatible = "nordic,nrf-spim";
	status = "okay";
	pinctrl-0 = <&spi1_default>;
	pinctrl-1 = <&spi1_sleep>;
	pinctrl-names = "default", "sleep";
	cs-gpios = <&gpio0 30 GPIO_ACTIVE_LOW>;
	lis2de12: lis2de12@0 {
		compatible = "st,lis2de12";
		reg = <0>;
		accel-range = <0>;
		accel-odr = <6>;
		spi-max-frequency = <1000000>; 
	};
};

&pinctrl {
	spi1_default: spi1_default {
		group1 {
				psels = <NRF_PSEL(SPIM_SCK, 0, 28)>,
						<NRF_PSEL(SPIM_MOSI, 0, 29)>,
						<NRF_PSEL(SPIM_MISO, 0, 31)>;
		};
	};

	spi1_sleep: spi1_sleep {
		group1 {
				psels = <NRF_PSEL(SPIM_SCK, 0, 28)>,
						<NRF_PSEL(SPIM_MOSI, 0, 29)>,
						<NRF_PSEL(SPIM_MISO, 0, 31)>;
				low-power-enable;
		};
	};
};

Code

/*
 * Copyright (c) 2016 Intel Corporation
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <stdio.h>
#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/logging/log.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/drivers/sensor.h>
#include <zephyr/drivers/spi.h>
#include "ble_app.h"

LOG_MODULE_REGISTER(MAIN, LOG_LEVEL_INF);

/* 1000 msec = 1 sec */
#define SLEEP_TIME_MS   1000

/* The devicetree node identifier for the "led0" alias. */
#define LED0_NODE DT_ALIAS(led0)
// #define LED1_NODE DT_ALIAS(led1)
// #define LED2_NODE DT_ALIAS(led2)
// #define LED3_NODE DT_ALIAS(led3)

/*
 * A build error on this line means your board is unsupported.
 * See the sample documentation for information on how to fix this.
 */
static const struct gpio_dt_spec led0 = GPIO_DT_SPEC_GET(LED0_NODE, gpios);

void gpio_task(void) 
{
	int ret;
	bool led_state = true;

	while(1) {
		ret = gpio_pin_toggle_dt(&led0);
		if (ret < 0) {
			LOG_INF("Toggle Error!");
		}

		led_state = !led_state;
		LOG_INF("LED state: %s", led_state ? "ON" : "OFF");
		k_msleep(1000);
	}
}

#define SPIOP	SPI_WORD_SET(8) | SPI_TRANSFER_MSB
struct spi_dt_spec spispec = SPI_DT_SPEC_GET(DT_NODELABEL(lis2de12), SPIOP, 0);

void lis2de12_spi_test()
{
	int err = spi_is_ready_dt(&spispec);
	if (!err) {
		LOG_ERR("Error: SPI device is not ready, err: %d", err);
		return;
	}

	LOG_INF("SPI device is ready");

	uint8_t tx_buffer[8] = {0x00};
	uint8_t rx_buffer[8] = {0x00};
	
	struct spi_buf tx_spi_buf		= {.buf = tx_buffer, .len = 8};
	struct spi_buf_set tx_spi_buf_set 	= {.buffers = &tx_spi_buf, .count = 1};
	struct spi_buf rx_spi_bufs 		= {.buf = rx_buffer, .len = 8};
	struct spi_buf_set rx_spi_buf_set	= {.buffers = &rx_spi_bufs, .count = 1};

	LOG_INF("Reading Chip ID");

	tx_buffer[0] = 0x0F | 0x80; // single spi read command: chip id
	err = spi_transceive_dt(&spispec, &tx_spi_buf_set, &rx_spi_buf_set);
	if (err < 0) {
		LOG_ERR("spi_transceive_dt() failed, err: %d", err);
		return;
	}

	LOG_INF("tx_buffer[0]: %X, tx_buffer[1]: %X", tx_buffer[0], tx_buffer[1]);
	LOG_INF("rx_buffer[0]: %X, rx_buffer[1]: %X", rx_buffer[0], rx_buffer[1]);

	if (rx_buffer[1] == 0x33)
        {
            LOG_INF("LIS2DE12 IMU detected.");
        }

	LOG_INF("Reading CNTR_REG_1");

	tx_buffer[0] = 0x20 | 0x80; // single spi read command: freq
	err = spi_transceive_dt(&spispec, &tx_spi_buf_set, &rx_spi_buf_set);
	if (err < 0) {
		LOG_ERR("spi_transceive_dt() failed, err: %d", err);
		return;
	}

	LOG_INF("tx_buffer[0]: %X, tx_buffer[1]: %X", tx_buffer[0], tx_buffer[1]);
	LOG_INF("rx_buffer[0]: %X, rx_buffer[1]: %X", rx_buffer[0], rx_buffer[1]);

	LOG_INF("Reading CNTR_REG_4");

	tx_buffer[0] = 0x23 | 0x80; // single spi read command: g-value
	err = spi_transceive_dt(&spispec, &tx_spi_buf_set, &rx_spi_buf_set);
	if (err < 0) {
		LOG_ERR("spi_transceive_dt() failed, err: %d", err);
		return;
	}

	LOG_INF("tx_buffer[0]: %X, tx_buffer[1]: %X", tx_buffer[0], tx_buffer[1]);
	LOG_INF("rx_buffer[0]: %X, rx_buffer[1]: %X", rx_buffer[0], rx_buffer[1]);
}

#ifdef CONFIG_LIS2DE12_TRIGGER
static int lis2de12_trig_cnt;

static void lis2de12_trigger_handler(const struct device *dev,
				    const struct sensor_trigger *trig)
{
	sensor_sample_fetch_chan(dev, SENSOR_CHAN_ALL);
	lis2de12_trig_cnt++;
}
#endif

static void lis2de12_config(const struct device *lis2de12)
{
	struct sensor_value odr_attr, fs_attr;

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

	if (sensor_attr_set(lis2de12, SENSOR_CHAN_ACCEL_XYZ,
			    SENSOR_ATTR_SAMPLING_FREQUENCY, &odr_attr) < 0) {
		LOG_ERR("Cannot set sampling frequency for LIS2DE12 accel\n");
		return;
	}

	sensor_g_to_ms2(2, &fs_attr);

	if (sensor_attr_set(lis2de12, SENSOR_CHAN_ACCEL_XYZ,
			    SENSOR_ATTR_FULL_SCALE, &fs_attr) < 0) {
		LOG_ERR("Cannot set sampling frequency for LIS2DE12 gyro\n");
		return;
	}

#ifdef CONFIG_LIS2DE12_TRIGGER
	struct sensor_trigger trig;

	trig.type = SENSOR_TRIG_DATA_READY;
	trig.chan = SENSOR_CHAN_ACCEL_XYZ;
	sensor_trigger_set(lis2de12, &trig, lis2de12_trigger_handler);
#endif

	LOG_INF("LIS2DE12 config done.");
}

struct sensor_value lis2de12_xl[3];

#ifdef CONFIG_LIS2DE12_ENABLE_TEMP
	struct sensor_value lis2de12_die_temp;
#endif

const struct device *const lis2de12 = DEVICE_DT_GET_ANY(st_lis2de12);

void get_imu_data()
{
	static int cnt = 1;

	#ifndef CONFIG_LIS2DE12_TRIGGER
		LOG_INF("Calling sensor_sample_fetch()");
		if (sensor_sample_fetch(lis2de12) < 0) {
			printf("LIS2DE12 Sensor sample update error\n");
			return;
		}
	#endif

	sensor_channel_get(lis2de12, SENSOR_CHAN_ACCEL_XYZ, lis2de12_xl);

	#ifdef CONFIG_LIS2DE12_ENABLE_TEMP
			sensor_channel_get(lis2de12, SENSOR_CHAN_DIE_TEMP, &lis2de12_die_temp);
	#endif

	LOG_INF("lis2de12_xl[0]: %d, lis2de12_xl[1]: %d, lis2de12_xl[2]:%d", 
			lis2de12_xl[0].val1, lis2de12_xl[1].val1, lis2de12_xl[2].val1);

	LOG_INF("LIS2DE12: Accel (m.s-2): x: %.3f, y: %.3f, z: %.3f\n",
				sensor_value_to_double(&lis2de12_xl[0]),
				sensor_value_to_double(&lis2de12_xl[1]),
				sensor_value_to_double(&lis2de12_xl[2]));
	
	#ifdef CONFIG_LIS2DE12_ENABLE_TEMP
			/* temperature */
			printf("LIS2DE12: Temperature: %.1f C\n",
			    sensor_value_to_double(&lis2de12_die_temp));
	#endif

	#ifdef CONFIG_LIS2DE12_TRIGGER
		printk("%d:: lis2de12 acc trig %d\n", cnt, lis2de12_trig_cnt);
	#endif

	cnt++;
}

void imu_init()
{
	if (!device_is_ready(lis2de12)) {
		LOG_INF("%s: device not ready", lis2de12->name);
		return;
	}

	LOG_INF("%s: Device is ready", lis2de12->name);

	lis2de12_config(lis2de12);
}

int lis2de12_status_check()
{
	uint8_t tx_buffer[8] = {0x00};
	uint8_t rx_buffer[8] = {0x00};
	
	struct spi_buf tx_spi_buf		= {.buf = tx_buffer, .len = 8};
	struct spi_buf_set tx_spi_buf_set 	= {.buffers = &tx_spi_buf, .count = 1};
	struct spi_buf rx_spi_bufs 		= {.buf = rx_buffer, .len = 8};
	struct spi_buf_set rx_spi_buf_set	= {.buffers = &rx_spi_bufs, .count = 1};

	tx_buffer[0] = 0x27 | 0x80; // single spi read command
	int err = spi_transceive_dt(&spispec, &tx_spi_buf_set, &rx_spi_buf_set);
	if (err < 0) {
		LOG_ERR("spi_transceive_dt() failed, err: %d", err);
		return 0;
	}

	LOG_INF("tx_buffer[0]: %X, tx_buffer[1]: %X", tx_buffer[0], tx_buffer[1]);
	LOG_INF("rx_buffer[0]: %X, rx_buffer[1]: %X", rx_buffer[0], rx_buffer[1]);

	return rx_buffer[1];
}

int main(void)
{
	int ret;

	LOG_INF("Staring App...\n");

	if (!gpio_is_ready_dt(&led0)) {
		return 0;
	}

	ret = gpio_pin_configure_dt(&led0, GPIO_OUTPUT_ACTIVE);
	if (ret < 0) {
		return 0;
	}

	// initialize imu
	imu_init();
	lis2de12_spi_test();

	// initialize ble
	// ble_init();

	while (1) {
		// LOG_INF("Hello World");
		get_imu_data();

		#if 0
		int status = lis2de12_status_check();

		if(status & 0x08 == 0x08)
		{
			LOG_INF("Reading IMU data");
			get_imu_data();
		}
		#endif

		k_msleep(1000);
	}
	
	return 0;
}

K_THREAD_DEFINE(gpio_task_id, 1024, gpio_task, NULL, NULL, NULL, 7, 0, 0);

Serial Log

[00:00:00.001,403] <inf> MAIN: Staring App...

[00:00:00.001,464] <inf> MAIN: lis2de12@0: Device is ready
[00:00:00.002,380] <inf> MAIN: LED state: OFF
[00:00:00.001,861] <inf> MAIN: LIS2DE12 config done.
[00:00:00.001,861] <inf> MAIN: SPI device is ready
[00:00:00.001,892] <inf> MAIN: Reading Chip ID
[00:00:00.002,441] <inf> MAIN: tx_buffer[0]: 8F, tx_buffer[1]: 0
[00:00:00.002,441] <inf> MAIN: rx_buffer[0]: FF, rx_buffer[1]: 33
[00:00:00.002,471] <inf> MAIN: LIS2DE12 IMU detected.
[00:00:00.002,471] <inf> MAIN: Reading CNTR_REG_1
[00:00:00.002,593] <inf> MAIN: tx_buffer[0]: A0, tx_buffer[1]: 0
[00:00:00.002,593] <inf> MAIN: rx_buffer[0]: FF, rx_buffer[1]: 6F
[00:00:00.002,593] <inf> MAIN: Reading CNTR_REG_4
[00:00:00.002,716] <inf> MAIN: tx_buffer[0]: A3, tx_buffer[1]: 0
[00:00:00.002,746] <inf> MAIN: rx_buffer[0]: FF, rx_buffer[1]: 80
[00:00:00.002,746] <inf> MAIN: Calling sensor_sample_fetch()
[00:00:00.003,509] <inf> MAIN: lis2de12_xl[0]: 0, lis2de12_xl[1]: 0, lis2de12_xl[2]:0
[00:00:00.003,540] <inf> MAIN: LIS2DE12: Accel (m.s-2): x: 0.000, y: 0.000, z: 0.000

LIS2DE12: Temperature: 25.0 C
[00:00:01.002,502] <inf> MAIN: LED state: ON
IS2DE12: Temperature: 25.0 C
0m<inf> MAIN: Calling sensor_sample_fetch()
[00:00:01.006,591] <inf> MAIN: lis2de12_xl[0]: 0, lis2de12_xl[1]: 0, lis2de12_xl[2]:0
[00:00:01.006,622] <inf> MAIN: LIS2DE12: Accel (m.s-2): x: 0.000, y: 0.000, z: 0.000

[00:00:02.002,593] <inf> MAIN: LED state: OFF
[00:00:02.009,307] <inf> MAIN: Calling sensor_sample_fetch()
[00:00:02.009,643] <inf> MAIN: lis2de12_xl[0]: 0, lis2de12_xl[1]: 0, lis2de12_xl[2]:0
[00:00:02.009,674] <inf> MAIN: LIS2DE12: Accel (m.s-2): x: 0.000, y: 0.000, z: 0.000

LIS2DE12: Temperature: 25.0 C
[00:00:03.002,685] <inf> MAIN: LED state: ON
[00:00:03.012,359] <inf> MAIN: Calling sensor_sample_fetch()
[00:00:03.012,725LIS2DE12: Temperature: 25.0 C
] <inf> MAIN: lis2de12_xl[0]: 0, lis2de12_xl[1]: 0, lis2de12_xl[2]:0
[00:00:03.012,756] <inf> MAIN: LIS2DE12: Accel (m.s-2): x: 0.000, y: 0.000, z: 0.000

Environment (please complete the following information):

  • OS: (e.g. Linux, MacOS, Windows): Windows 11
  • Toolchain (e.g Zephyr SDK, ...): nrf Connect SDK v2.8.0
  • Commit SHA or Version used: Not sure how to check

Additional context

I tried reading CNTR_REG_1 and CNTR_REG_4 for checking ODR & g-value respectively that is getting set correctly as you can see in the logs. The next was to just read IMU values which is not working.

@narangmayank narangmayank added the bug The issue is a bug, or the PR is fixing a bug label Jan 10, 2025
Copy link

Hi @narangmayank! We appreciate you submitting your first issue for our open-source project. 🌟

Even though I'm a bot, I can assure you that the whole community is genuinely grateful for your time and effort. 🤖💙

@narangmayank
Copy link
Author

narangmayank commented Jan 10, 2025

Update 1:

When I try to read XYZ registers manually (i.e 6 bytes from FIFO_READ_START register) it gives me value.

Code Snippet Added

void read_imu_xyz_register()
{
	uint8_t tx_buffer[8] = {0x00};
	uint8_t rx_buffer[8] = {0x00};
	
	struct spi_buf tx_spi_buf		= {.buf = tx_buffer, .len = 8};
	struct spi_buf_set tx_spi_buf_set 	= {.buffers = &tx_spi_buf, .count = 1};
	struct spi_buf rx_spi_bufs 		= {.buf = rx_buffer, .len = 8};
	struct spi_buf_set rx_spi_buf_set	= {.buffers = &rx_spi_bufs, .count = 1};

	LOG_INF("Reading IMU registers");

	tx_buffer[0] = 0x28 | 0xC0; // multiple spi read command
	int err = spi_transceive_dt(&spispec, &tx_spi_buf_set, &rx_spi_buf_set);
	if (err < 0) {
		LOG_ERR("spi_transceive_dt() failed, err: %d", err);
		return;
	}

	LOG_INF("tx_buffer[0]: %X, tx_buffer[1]: %X", tx_buffer[0], tx_buffer[1]);

	printk("<------------ rx_buffer: ");
	for(int i=0; i<8; i++)
	{
		printk("%X ", rx_buffer[i]);
	}
	printk("------------>\n");
}

// In the main loop added the call to manual read fun as well
while (1) 
{
        // LOG_INF("Hello World");
        get_imu_data();
        read_imu_xyz_register();
        
        #if 0
        int status = lis2de12_status_check();
        
        if(status & 0x08 == 0x08)
        {
	        LOG_INF("Reading IMU data");
	        get_imu_data();
        }
        #endif
        
        k_msleep(1000);
}

Serial Logs

[00:01:55.518,737] <inf> MAIN: Reading IMU registers
[00:01:55.519,317] <inf> MAIN: tx_buffer[0]: E8, tx_buffer[1]: 0
<------------ rx_buffer: FF 0 FC 0 C7 0 E6 0 ------------>
LIS2DE12: Temperature: -102.5 C
[00:01:56.013,031] <inf> MAIN: LED state: OFF
[00:01:56.519,561] <inf> MAIN: Calling sensor_sample_fetch()
[00:01:56.520,355] <inf> MAIN: lis2de12_xl[0]: 0, lis2de12_xl[1]: 0, lis2de12_xl[2]:0
[00:01:56.520,385] <inf> MAIN: LIS2DE12: Accel (m.s-2): x: 0.000, y: 0.000, z: 0.000

[00:01:56.523,193] <inf> MAIN: Reading IMU registers
[00:01:56.523,742] <inf> MAIN: tx_buffer[0]: E8, tx_buffer[1]: 0
<------------ rx_buffer: FF 0 FC 0 C7 0 E6 0 ------------>

@narangmayank
Copy link
Author

narangmayank commented Jan 10, 2025

@teburd @MaureenHelm Found out the issue. The issue was with SPI multi byte read even if application calls to read out more than 1 bytes the addr auto increment bit was not setting up.

PFA Git diff

diff --git a/drivers/sensor/st/stmemsc/stmemsc_spi.c b/drivers/sensor/st/stmemsc/stmemsc_spi.c
index 3d728c78d8b..4b8c2fd8847 100644
--- a/drivers/sensor/st/stmemsc/stmemsc_spi.c
+++ b/drivers/sensor/st/stmemsc/stmemsc_spi.c
@@ -63,7 +63,10 @@ int stmemsc_spi_write(const struct spi_dt_spec *stmemsc,
 int stmemsc_spi_read_incr(const struct spi_dt_spec *stmemsc,
                          uint8_t reg_addr, uint8_t *value, uint8_t len)
 {
-       reg_addr |= STMEMSC_SPI_ADDR_AUTO_INCR;
+       if(len > 1) {
+               reg_addr |= STMEMSC_SPI_ADDR_AUTO_INCR;
+       }
+
        return stmemsc_spi_read(stmemsc, reg_addr, value, len);
 }

diff --git a/drivers/sensor/st/lis2de12/lis2de12.c b/drivers/sensor/st/lis2de12/lis2de12.c
index 9cceccdeb20..b417bccda39 100644
--- a/drivers/sensor/st/lis2de12/lis2de12.c
+++ b/drivers/sensor/st/lis2de12/lis2de12.c
@@ -435,7 +435,7 @@ static int lis2de12_init(const struct device *dev)

 #define LIS2DE12_CONFIG_SPI(inst)                                              \
        {                                                                       \
-               STMEMSC_CTX_SPI(&lis2de12_config_##inst.stmemsc_cfg),           \
+               STMEMSC_CTX_SPI_INCR(&lis2de12_config_##inst.stmemsc_cfg),              \
                .stmemsc_cfg = {                                                \
                        .spi = SPI_DT_SPEC_INST_GET(inst, LIS2DE12_SPI_OP, 0),  \
                },                                                              \

Getting IMU values after changing above 2 files.
Should I raise a PR against the issue?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: Sensors Sensors bug The issue is a bug, or the PR is fixing a bug
Projects
None yet
Development

No branches or pull requests

4 participants