Hello, I am using the LIS2DH sample (and the st,lis2dh driver, which is compatible with the LIS3DH accelerometer) to test out a LIS3DH IC attached to a custom board. However I keep getting the following error:
SEGGER J-Link V8.96 - Real time terminal output SEGGER J-Link V12.0, SN=822000525 Process: JLinkExe [00:00:00.265,258] <err> lis2dh: Failed to read chip id. *** Booting nRF Connect SDK v3.2.1-d8887f6f32df *** *** Using Zephyr OS v4.2.99-ec78104f1569 *** Device LIS3DH is not ready
In our board (snippets from the schematic attached), the SDA and SCL lines are wired to GPIO P0.12 and P0.11 respectively. INT1, INT2 are wired to P0.07 and P0.08. SD0 is connected to P0.04. CS' is pulled high and I am not asserting it because he datasheet says that it must be tied high for I2C.
My goal is to get the sample running (reading data via the zephyr/drivers/sensor.h API). I am using the default dts for nrf52dk_nrf52832 with a device tree overlay:
&i2c0 {
status = "okay";
pinctrl-0 = <&i2c0_default>;
pinctrl-1 = <&i2c0_sleep>;
pinctrl-names = "default", "sleep";
lis2dh@19 {
compatible = "st,lis2dh";
reg = <0x19>;
label = "LIS3DH";
irq-gpios = <&gpio0 7 GPIO_ACTIVE_LOW>, <&gpio0 8 GPIO_ACTIVE_LOW>; /* INT1 -> P0.07, INT2 -> P0.08 */
};
};
&pinctrl {
i2c0_default {
group1 {
psels = <NRF_PSEL(TWIM_SDA, 0, 12)>, /* SDA -> P0.12 */
<NRF_PSEL(TWIM_SCL, 0, 11)>; /* SCL -> P0.11 */
};
};
i2c0_sleep {
group1 {
psels = <NRF_PSEL(TWIM_SDA, 0, 12)>,
<NRF_PSEL(TWIM_SCL, 0, 11)>;
};
};
};
With the following prj.conf:
CONFIG_STDOUT_CONSOLE=y CONFIG_I2C=y CONFIG_SENSOR=y CONFIG_CBPRINTF_FP_SUPPORT=y CONFIG_REBOOT=y CONFIG_LOG=y CONFIG_LOG_PRINTK=y CONFIG_USE_SEGGER_RTT=y CONFIG_RTT_CONSOLE=y
and my main.c is:
/*
* Copyright (c) 2019 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdio.h>
#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/drivers/sensor.h>
#include <inttypes.h>
#include <zephyr/logging/log.h>
#include <zephyr/sys/reboot.h>
LOG_MODULE_REGISTER(generallogs,LOG_LEVEL_DBG);
static void fetch_and_display(const struct device *sensor)
{
static unsigned int count;
struct sensor_value accel[3];
struct sensor_value temperature;
const char *overrun = "";
int rc = sensor_sample_fetch(sensor);
++count;
if (rc == -EBADMSG) {
/* Sample overrun. Ignore in polled mode. */
if (IS_ENABLED(CONFIG_LIS2DH_TRIGGER)) {
overrun = "[OVERRUN] ";
}
rc = 0;
}
if (rc == 0) {
rc = sensor_channel_get(sensor,
SENSOR_CHAN_ACCEL_XYZ,
accel);
}
if (rc < 0) {
printk("ERROR: Update failed: %d\n", rc);
} else {
printk("#%u @ %u ms: %sx %f , y %f , z %f",
count, k_uptime_get_32(), overrun,
sensor_value_to_double(&accel[0]),
sensor_value_to_double(&accel[1]),
sensor_value_to_double(&accel[2]));
}
if (IS_ENABLED(CONFIG_LIS2DH_MEASURE_TEMPERATURE)) {
if (rc == 0) {
rc = sensor_channel_get(sensor, SENSOR_CHAN_DIE_TEMP, &temperature);
if (rc < 0) {
printk("\nERROR: Unable to read temperature:%d\n", rc);
} else {
printk(", t %f\n", sensor_value_to_double(&temperature));
}
}
} else {
printk("\n");
}
}
#ifdef CONFIG_LIS2DH_TRIGGER
static void trigger_handler(const struct device *dev,
const struct sensor_trigger *trig)
{
fetch_and_display(dev);
}
#endif
int main(void)
{
const struct device *const sensor = DEVICE_DT_GET_ANY(st_lis2dh);
if (sensor == NULL) {
printk("No device found\n");
return 0;
}
if (!device_is_ready(sensor)) {
printk("Device %s is not ready\n", sensor->name);
k_msleep(2000); /* Reboot if fails. */
sys_reboot(SYS_REBOOT_WARM);
}
#if CONFIG_LIS2DH_TRIGGER
{
struct sensor_trigger trig;
int rc;
trig.type = SENSOR_TRIG_DATA_READY;
trig.chan = SENSOR_CHAN_ACCEL_XYZ;
if (IS_ENABLED(CONFIG_LIS2DH_ODR_RUNTIME)) {
struct sensor_value odr = {
.val1 = 1,
};
rc = sensor_attr_set(sensor, trig.chan,
SENSOR_ATTR_SAMPLING_FREQUENCY,
&odr);
if (rc != 0) {
printk("Failed to set odr: %d\n", rc);
return 0;
}
printk("Sampling at %u Hz\n", odr.val1);
}
rc = sensor_trigger_set(sensor, &trig, trigger_handler);
if (rc != 0) {
printk("Failed to set trigger: %d\n", rc);
return 0;
}
printk("Waiting for triggers\n");
while (true) {
k_sleep(K_MSEC(2000));
}
}
#else /* CONFIG_LIS2DH_TRIGGER */
printk("Polling at 0.5 Hz\n");
while (true) {
fetch_and_display(sensor);
k_sleep(K_MSEC(2000));
}
#endif /* CONFIG_LIS2DH_TRIGGER */
}
based on a similar problem posed in another ticket I have added a reset command in the block where the device driver is not ready. The user reported that this approach worked for him but it keeps on failing in a loop for me.
If there is anything wrong that stands out in the above snippets, it would be great to know. Thank you for your time!

