LIS2DH Accelerometer not initializing with nRF5340 DK

Hi, I'm trying to read data from an LIS2DH accelerometer using the nRF5340 DK board. I have been able to build and flash my code to the board, but the terminal outputs, "Device not ready", indicating that the sensor was not initialized properly. The code I am using (shown below) should work as it is based off the sample LIS2DH application. I was wondering if someone could help explain why the sensor is not initializing properly. Thank you!

main:

#include <stdio.h>
#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/drivers/sensor.h>

static void fetch_and_display(const struct device *sensor)
{
	static unsigned int count;
	struct sensor_value accel[3];
	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) {
		printf("ERROR: Update failed: %d\n", rc);
	} else {
		printf("#%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]));
	}

}

int main(void)
{
	const struct device *const sensor = DEVICE_DT_GET_ANY(st_lis2dh);

	if (sensor == NULL) {
		printf("No device found\n");
		return 0;
	}
	if (!device_is_ready(sensor)) {
		printf("Device %s is not ready\n", sensor->name);
		return 0;
	}

	printf("Polling at 0.5 Hz\n");
	while (true) {
		fetch_and_display(sensor);
		k_sleep(K_MSEC(2000));
	}

}

Overlay file:

prj.conf:

Parents
  • Hello,

    roddyb said:
    I was able to run a basic SDK sample without any issues. However, I am still having some trouble reading data from the sensor. Do you know what the issue could be?

    Sorry, I accidentally deleted one of your replies. Could you explain the issue a little more or provide the current status of your development? If there are any error logs or error messages, please share them as they will help in diagnosing the issue.

    Kind regards,

    Abhijith

Reply
  • Hello,

    roddyb said:
    I was able to run a basic SDK sample without any issues. However, I am still having some trouble reading data from the sensor. Do you know what the issue could be?

    Sorry, I accidentally deleted one of your replies. Could you explain the issue a little more or provide the current status of your development? If there are any error logs or error messages, please share them as they will help in diagnosing the issue.

    Kind regards,

    Abhijith

Children
  • No worries! I am trying to read data from an LIS2DH accelerometer using the nRF5340 DK board. I was using to given LIS2DH application as a starting point. However, when I try to run the application the code outputs the message "Device not ready" indicating the sensor was not initialized properly in the code. Here is my code including the changes I made thanks to the previous replies by the community:

    main:

    #include <stdio.h>
    #include <zephyr/kernel.h>
    #include <zephyr/device.h>
    #include <zephyr/drivers/sensor.h>
    
    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) {
    		printf("ERROR: Update failed: %d\n", rc);
    	} else {
    		printf("#%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) {
    				printf("\nERROR: Unable to read temperature:%d\n", rc);
    			} else {
    				printf(", t %f\n", sensor_value_to_double(&temperature));
    			}
    		}
    
    	} else {
    		printf("\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)
    {
    	printf("Hello world!\n");
    	const struct device *sensor = DEVICE_DT_GET_ANY(st_lis2dh);
    
    	if (sensor == NULL) {
    		printf("No device found\n");
    		return 0;
    	}
    	if (!device_is_ready(sensor)) {
    		printf("Device %s is not ready\n", sensor->name);
    		return 0;
    	}
    
    #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) {
    				printf("Failed to set odr: %d\n", rc);
    				return 0;
    			}
    			printf("Sampling at %u Hz\n", odr.val1);
    		}
    
    		rc = sensor_trigger_set(sensor, &trig, trigger_handler);
    		if (rc != 0) {
    			printf("Failed to set trigger: %d\n", rc);
    			return 0;
    		}
    
    		printf("Waiting for triggers\n");
    		while (true) {
    			k_sleep(K_MSEC(2000));
    		}
    	}
    #else /* CONFIG_LIS2DH_TRIGGER */
    	printf("Polling at 0.5 Hz\n");
    	while (true) {
    		fetch_and_display(sensor);
    		k_sleep(K_MSEC(2000));
    	}
    #endif /* CONFIG_LIS2DH_TRIGGER */
    }

    nrf5340dk_nrf5340_cpuapp.overlay:

    &pinctrl {
    	uart0_default: uart0_default {
    		group1 {
    			psels = <NRF_PSEL(UART_TX, 0, 20)>,
    				<NRF_PSEL(UART_RX, 0, 22)>;
    		};
    	};
    
    	uart0_sleep: uart0_sleep {
    		group1 {
    			psels = <NRF_PSEL(UART_TX, 0, 20)>,
    				<NRF_PSEL(UART_RX, 0, 22)>;
    			low-power-enable;
    		};
    	};
    
    	i2c2_default: i2c2_default {
    		group1 {
    			psels = <NRF_PSEL(TWIM_SDA, 0, 8)>,
    				<NRF_PSEL(TWIM_SCL, 0, 7)>;
    		};	
    	};
    
    	i2c2_sleep: i2c2_sleep {
    		group1 {
    			psels = <NRF_PSEL(TWIM_SDA, 0, 8)>,
    				<NRF_PSEL(TWIM_SCL, 0, 7)>;
    			low-power-enable;
    		};
    	};
    
    	pwm0_default: pwm0_default {
    		group1 {
    			psels = <NRF_PSEL(PWM_OUT0, 0, 25)>;
    		};
    	};
    
    	pwm0_sleep: pwm0_sleep {
    		group1 {
    			psels = <NRF_PSEL(PWM_OUT0, 0, 25)>;
    			low-power-enable;
    		};
    	};
    
    	spi3_default: spi3_default {
    		group1 {
    			psels = <NRF_PSEL(SPIM_SCK, 0, 19)>,
    				<NRF_PSEL(SPIM_MISO, 0, 20)>,
    				<NRF_PSEL(SPIM_MOSI, 0, 21)>;
    		};
    	};
    
    	spi3_sleep: spi3_sleep {
    		group1 {
    			psels = <NRF_PSEL(SPIM_SCK, 0, 19)>,
    				<NRF_PSEL(SPIM_MISO, 0, 20)>,
    				<NRF_PSEL(SPIM_MOSI, 0, 21)>;
    			low-power-enable;
    		};
    	};
    };

    nrf5340dk_nrf5340_cpuapp.dts:

    /*
     * Copyright (c) 2020 Nordic Semiconductor ASA
     *
     * SPDX-License-Identifier: Apache-2.0
     */
    
    /dts-v1/;
    #include <nordic/nrf5340_cpuapp_qkaa.dtsi>
    #include "nrf5340_cpuapp_common.dtsi"
    
    / {
    	model = "Nordic NRF5340 DK NRF5340 Application";
    	compatible = "nordic,nrf5340-dk-nrf5340-cpuapp";
    
    	chosen {
    		zephyr,sram = &sram0_image;
    		zephyr,flash = &flash0;
    		zephyr,code-partition = &slot0_partition;
    		zephyr,sram-secure-partition = &sram0_s;
    		zephyr,sram-non-secure-partition = &sram0_ns;
    	};
    };
    
    &uart0 {
    	status = "okay";
    	current-speed = <115200>;
    	pinctrl-0 = <&uart0_default>;
    	pinctrl-1 = <&uart0_sleep>;
    	pinctrl-names = "default", "sleep";
    };
    
    &i2c2 {
    	compatible = "nordic,nrf-twim";
    	status = "okay";
    	pinctrl-0 = <&i2c2_default>;
    	pinctrl-1 = <&i2c2_sleep>;
    	pinctrl-names = "default", "sleep";
    	clock-frequency = <I2C_BITRATE_FAST>;
    
    	pmic_main: npm1300@6b {
    		compatible = "nordic,npm1300";
    		reg = <0x6b>;
    		pmic_charger: charger {
    			compatible = "nordic,npm1300-charger";
    			term-microvolt = <4150000>;
    			term-warm-microvolt = <4000000>;
    			current-microamp = <150000>;
    			dischg-limit-microamp = <1000000>;
    			vbus-limit-microamp = <500000>;
    			thermistor-ohms = <10000>;
    			thermistor-beta = <3380>;
    			charging-enable;
    		};
    		regulators {
    			compatible = "nordic,npm1300-regulator";
    			BUCK1 {
    				regulator-min-microvolt = <1800000>;
    				regulator-max-microvolt = <1800000>;
    				regulator-boot-on;
    			};
    			BUCK2 {
    				regulator-min-microvolt = <3300000>;
    				regulator-max-microvolt = <3300000>;
    				regulator-boot-on;
    			};
    		};
    	};
    
    	lis2dh: lis2dh@18 {
    		compatible = "st,lis2dh";
    		reg = <0x18>;
    		irq-gpios = <&gpio0 29 GPIO_ACTIVE_HIGH>;
    		disconnect-sdo-sa0-pull-up;
    	};
    
    	eeprom0: eeprom@50 {
    		/* 24CW160 (16 kbit eeprom) */
    		/* 0x8000 config register not accessible! If required, set size to 64K */
    		compatible = "atmel,at24";
    		reg = <0x50>;
    		size = <DT_SIZE_K(2)>;
    		pagesize = <32>;
    		address-width = <16>;
    		timeout = <5>;
    	};
    };
    
    &pwm0 {
    	status = "okay";
    	pinctrl-0 = <&pwm0_default>;
    	pinctrl-1 = <&pwm0_sleep>;
    	pinctrl-names = "default", "sleep";
    };
    

    prj.conf:

    CONFIG_STDOUT_CONSOLE=y
    
    # Adding I2C
    CONFIG_I2C=y
    
    # Add the accelerometer
    CONFIG_SENSOR=y
    CONFIG_LIS2DH=y
    CONFIG_CBPRINTF_FP_SUPPORT=y
    
    # newlibc for printing floats
    CONFIG_NEWLIB_LIBC=y
    CONFIG_NEWLIB_LIBC_FLOAT_PRINTF=y
    
    
    CONFIG_SERIAL=y

  • Hello,

    roddyb said:
    "Device not ready" indicating the sensor was not initialized properly in the code

    The error message suggests that the sensor device specified in your code isn’t properly initialized or detected. Please ensure that the I2C bus (i2c2) is enabled and configured correctly. Verify that the pinctrl settings are appropriate for your hardware setup. Confirm that your sensor is connected to the I2C2 bus with the address 0x18, and double-check the wiring and connections.

    Please review this guide and ensure that you have followed all the steps mentioned.

    Kind regards,

    Abhijith

  • Thank you for the reply! I have double checked that the I2C bus is enabled and configured. As far as I am aware the pinctrl settings are appropriate for my board. I can also confirm that the sensor connected to the I2C bus with the address 0x18, and the wiring is correct: VCC ->, GND -> GND, SDA -> P0.08, SCL -> 0.07. I spent some time working through the guide you sent, but I found that I already had most of the information they asked to include. Do  you think I could be missing something in the overlay file or in the devicetree that would stop the sensor from initializing?

    Thanks,

    Roddy

  • Issue fixed! It seemed the register had to be 0x19 and not 0x19 and the pin assignments were wrong.

  • Yup that depends on your LIS2DH HW configuration.
    As per LIS2DH12 datasheet, if the SD0 pin is connected to the supply voltage, the I2C address of the accelerometer will be 0x19 and not 0x18.

    Glad you got that figured out.

Related