Power off LSM6DSO Sensor between measurements

Hello,
I want to switch off the power supply to my LSM6DSO IMU between measurements. The measurements only take place once a minute. If I operate it permanently with voltage, it would consume about 200uA. To save this, I switched off the voltage. Unfortunately this does not work, I no longer get any values back when I query the sensor. I tried it with different delays between switching on and measuring, but 0 values are always displayed. If I constantly power the IMU, everything works.
You can watch it briefly in a video. www.youtube.com/watch


nrf connect sdk 2.1.2

What do I have to change to make this work? or how can I initialize the lsm6dso manually?

Best regards, Jonas

		gpio_pin_set(gpio_dev, VDD_PIN_IMU, 1);
		k_sleep(K_MSEC(10));
		remap_pins_imu();
		pm_device_action_run(imu_dev,PM_DEVICE_ACTION_TURN_ON);		
		get_rotation(imu_dev);
		pm_device_action_run(imu_dev,PM_DEVICE_ACTION_TURN_OFF);
		k_sleep(K_MSEC(10));
		// gpio_pin_set(gpio_dev, VDD_PIN_IMU, 0);
dynamic_pinctrl_evaluation.zip

Parents
  • The LSM6DSO driver, as it stands, does not handle any PM state actions. You would need to modify the driver and add support for PM state transitions and recall the initialisation functions of the driver when the IMU is powered again.

  • Thanks, I just added the power management functionality in the lsm6dso driver and receive now measurement values. Not correct ones, but better than only zeros, 
    If someone has the same Problem here a quick guide how to add power management functionality to a sensor driver: 

    The <driver_model>.c file has to be expanded with a pm_action function. 

    #ifdef CONFIG_PM_DEVICE
    static int lsm6dso_pm_action(const struct device *dev,
    			    enum pm_device_action action)
    {
    	int ret = 0;
    
    	switch (action) {
    	case PM_DEVICE_ACTION_RESUME:
    		/* Re-initialize the chip */
    		ret = lsm6dso_init(dev);
    		break;
    	case PM_DEVICE_ACTION_SUSPEND:
    		/* Put the chip into sleep mode - 
    		I haven't done this, because I don't need it actually */
    		break;
    	default:
    		return -ENOTSUP;
    	}
    	return ret;
    }
    #endif /* CONFIG_PM_DEVICE */

    Next the DEVICE_INIT define has to be edited: 

    #define LSM6DSO_DEVICE_INIT(inst)					\
    	DEVICE_DT_INST_DEFINE(inst,					\
    			    lsm6dso_init,				\
    			    PM_DEVICE_DT_INST_GET(inst),	\  // <- instead of NULL add this
    			    &lsm6dso_data_##inst,			\
    			    &lsm6dso_config_##inst,			\
    			    POST_KERNEL,				\
    			    CONFIG_SENSOR_INIT_PRIORITY,		\
    			    &lsm6dso_driver_api);

    Lastly edit the <Device>_DEFINE :

    #define LSM6DSO_DEFINE(inst)						\
    	static struct lsm6dso_data lsm6dso_data_##inst;			\
    	static const struct lsm6dso_config lsm6dso_config_##inst =	\
    		COND_CODE_1(DT_INST_ON_BUS(inst, spi),			\
    			(LSM6DSO_CONFIG_SPI(inst)),			\
    			(LSM6DSO_CONFIG_I2C(inst)));			\
    	PM_DEVICE_DT_INST_DEFINE(inst, lsm6dso_pm_action); \     // <- add this
    	LSM6DSO_DEVICE_INIT(inst)
    
    DT_INST_FOREACH_STATUS_OKAY(LSM6DSO_DEFINE)

    when you call pm_device_action_run(dev,PM_DEVICE_ACTION_RESUME); the init function in the device driver is called.

    Thanks   Slight smile

Reply
  • Thanks, I just added the power management functionality in the lsm6dso driver and receive now measurement values. Not correct ones, but better than only zeros, 
    If someone has the same Problem here a quick guide how to add power management functionality to a sensor driver: 

    The <driver_model>.c file has to be expanded with a pm_action function. 

    #ifdef CONFIG_PM_DEVICE
    static int lsm6dso_pm_action(const struct device *dev,
    			    enum pm_device_action action)
    {
    	int ret = 0;
    
    	switch (action) {
    	case PM_DEVICE_ACTION_RESUME:
    		/* Re-initialize the chip */
    		ret = lsm6dso_init(dev);
    		break;
    	case PM_DEVICE_ACTION_SUSPEND:
    		/* Put the chip into sleep mode - 
    		I haven't done this, because I don't need it actually */
    		break;
    	default:
    		return -ENOTSUP;
    	}
    	return ret;
    }
    #endif /* CONFIG_PM_DEVICE */

    Next the DEVICE_INIT define has to be edited: 

    #define LSM6DSO_DEVICE_INIT(inst)					\
    	DEVICE_DT_INST_DEFINE(inst,					\
    			    lsm6dso_init,				\
    			    PM_DEVICE_DT_INST_GET(inst),	\  // <- instead of NULL add this
    			    &lsm6dso_data_##inst,			\
    			    &lsm6dso_config_##inst,			\
    			    POST_KERNEL,				\
    			    CONFIG_SENSOR_INIT_PRIORITY,		\
    			    &lsm6dso_driver_api);

    Lastly edit the <Device>_DEFINE :

    #define LSM6DSO_DEFINE(inst)						\
    	static struct lsm6dso_data lsm6dso_data_##inst;			\
    	static const struct lsm6dso_config lsm6dso_config_##inst =	\
    		COND_CODE_1(DT_INST_ON_BUS(inst, spi),			\
    			(LSM6DSO_CONFIG_SPI(inst)),			\
    			(LSM6DSO_CONFIG_I2C(inst)));			\
    	PM_DEVICE_DT_INST_DEFINE(inst, lsm6dso_pm_action); \     // <- add this
    	LSM6DSO_DEVICE_INIT(inst)
    
    DT_INST_FOREACH_STATUS_OKAY(LSM6DSO_DEFINE)

    when you call pm_device_action_run(dev,PM_DEVICE_ACTION_RESUME); the init function in the device driver is called.

    Thanks   Slight smile

Children
No Data
Related