Multiple VL53L0X time of flight sensors

Hello all,

I am trying to write some code to read the sensor values from two VL53L0X tof sensors, but I'm having some trouble.

My current code:

#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/drivers/sensor.h>
#include <zephyr/sys/printk.h>
#include <zephyr/drivers/gpio.h>

static const struct device *const leftSensor = DEVICE_DT_GET(DT_NODELABEL(right_st_vl53l0x));
static const struct device *const rightSensor = DEVICE_DT_GET(DT_NODELABEL(left_st_vl53l0x));

int main(void)
{
        struct sensor_value leftSensorValue;
        struct sensor_value rightSensorValue;
        int ret;

        k_sleep(K_MSEC(1000));

        if (!device_is_ready(leftSensor)) {
	        printk("Left Sensor: device not ready.\n");
	        return 0;
	}
        if (!device_is_ready(rightSensor)) {
	        printk("Right Sensor: device not ready.\n");
	        return 0;
	}
	while (1) {
		ret = sensor_sample_fetch(leftSensor);
		if (ret) {
			printk("sensor_sample_fetch failed ret %d\n", ret);
			return 0;
		}

		ret = sensor_channel_get(leftSensor, SENSOR_CHAN_PROX, &leftSensorValue);
		printk("prox is %d\n", leftSensorValue.val1);

		ret = sensor_channel_get(leftSensor,
					 SENSOR_CHAN_DISTANCE,
					 &leftSensorValue);
		printf("distance is %.3fm\n", sensor_value_to_double(&leftSensorValue));
                
		k_sleep(K_MSEC(1000));
	}
	return 0;
}

My devicetree:

&i2c1 {
    
    right_st_vl53l0x: right_st_vl53l0x@29{
        compatible = "st,vl53l0x";
        status = "okay";
        reg = < 0x29 >;
        xshut-gpios = < &gpio0 15 (GPIO_ACTIVE_LOW)>;
    };
    left_st_vl53l0x: left_st_vl53l0@52{
        compatible = "st,vl53l0x";
        status = "okay";
        reg = < 0x52 >;
        xshut-gpios = < &gpio0 16 (GPIO_ACTIVE_LOW)>;
    };
};
&pinctrl {
	i2c1_default: i2c1_default{
		group1 {
			psels = <NRF_PSEL(TWIM_SDA, 0, 5)>,
				<NRF_PSEL(TWIM_SCL, 0, 4)>;
		};
	};

	i2c1_sleep: i2c1_sleep{
		group1 {
			psels = <NRF_PSEL(TWIM_SDA, 0, 5)>,
				<NRF_PSEL(TWIM_SCL, 0, 4)>;
			low-power-enable;
		};
	};

};

And Kconfig:

CONFIG_STDOUT_CONSOLE=y
CONFIG_I2C=y
CONFIG_GPIO=y
CONFIG_SENSOR=y
CONFIG_VL53L0X_PROXIMITY_THRESHOLD=100
CONFIG_TFM_SECURE_UART=n
CONFIG_TFM_LOG_LEVEL_SILENCE=y
CONFIG_VL53L0X_RECONFIGURE_ADDRESS=y
#debug
#CONFIG_DEBUG=y
#CONFIG_LOG=y
#CONFIG_SENSOR_LOG_LEVEL_DBG=y
CONFIG_CBPRINTF_FP_SUPPORT=y

Whenever I run this code I get a ret error (-19) or sometimes (-5).

Any help is much appreciated!

Parents
  • Hello,

    Which Nordic chip or development kit (DK) are you using? Could you also provide details of the SDK version you are using?

    Whenever I run this code I get a ret error (-19) or sometimes (-5).

    I recommend attaching the complete log to troubleshoot the issue. Please ensure that the I2C addresses (0x29 and 0x52) are correctly set and do not conflict. Additionally, I noticed that static const struct device *const leftSensor = DEVICE_DT_GET(DT_NODELABEL(right_st_vl53l0x)); and DEVICE_DT_GET(DT_NODELABEL(left_st_vl53l0x)); refer to different labels than those used in your device tree overlay. While this might work, it is somewhat confusing.

    Kind Regards,

    Abhijith

Reply
  • Hello,

    Which Nordic chip or development kit (DK) are you using? Could you also provide details of the SDK version you are using?

    Whenever I run this code I get a ret error (-19) or sometimes (-5).

    I recommend attaching the complete log to troubleshoot the issue. Please ensure that the I2C addresses (0x29 and 0x52) are correctly set and do not conflict. Additionally, I noticed that static const struct device *const leftSensor = DEVICE_DT_GET(DT_NODELABEL(right_st_vl53l0x)); and DEVICE_DT_GET(DT_NODELABEL(left_st_vl53l0x)); refer to different labels than those used in your device tree overlay. While this might work, it is somewhat confusing.

    Kind Regards,

    Abhijith

Children
  • Thank you for the reply,

    I am using the nrf5340dk and my SDK version is v2.7.0 rc3 but I have also tried v2.6.1.

    I don't quite follow in what you mean by attaching the complete log, furthermore I don't quite know what you mean by making sure the I2C addresses are set correctly. I was able to get readings from one VL53L0X on the default address of 0x29. I have tried multiple addresses for the second VL53L0X.

    Finally, apologies for the confusing application code on the device pointer, when I was trying to debug I swapped around the sensors and forgot to put it back.

    Best,

    Declan S

  • My mistake, I somehow completely forgot about the verbose logs Disappointed. When running I now get this output:

    [00:00:00.499,664] <dbg> VL53L0X: vl53l0x_init: [left_st_vl53l0@39] Shutdown
    [00:00:00.499,694] <dbg> VL53L0X: vl53l0x_init: [left_st_vl53l0@39] Initialized
    [00:00:00.499,725] <dbg> VL53L0X: vl53l0x_init: [right_st_vl53l0x@29] Shutdown
    [00:00:00.499,755] <dbg> VL53L0X: vl53l0x_init: [right_st_vl53l0x@29] Initialized
    *** Booting nRF Connect SDK 3758bcbfa5cd ***
    [00:00:02.500,000] <dbg> VL53L0X: vl53l0x_start: [right_st_vl53l0x@29] Starting
    [00:00:02.525,451] <dbg> VL53L0X: vl53l0x_start: [right_st_vl53l0x@29] VL53L0X_GetDeviceInfo = 0
    [00:00:02.525,482] <dbg> VL53L0X: vl53l0x_start:    Device Name : VL53L0X ES1 or later
    [00:00:02.525,512] <dbg> VL53L0X: vl53l0x_start:    Device Type : VL53L0X
    [00:00:02.525,543] <dbg> VL53L0X: vl53l0x_start:    Device ID : VL53L0C@V0DH/1$1
    [00:00:02.525,573] <dbg> VL53L0X: vl53l0x_start:    ProductRevisionMajor : 1
    [00:00:02.525,573] <dbg> VL53L0X: vl53l0x_start:    ProductRevisionMinor : 1
    [00:00:02.657,531] <err> VL53L0X: [right_st_vl53l0x@29] VL53L0X_PerformRefCalibration failed
    leftSensor_sample_fetch failed ret -134

  • Progress. I changed the xShut for the right sensor to P0.30 and the left sensor to P0.11. It seems to be able to change the left sensors default address but gets stuck on its calibration:

    [00:00:00.477,539] <dbg> VL53L0X: vl53l0x_init: [left_st_vl53l0@39] Shutdown
    [00:00:00.477,569] <dbg> VL53L0X: vl53l0x_init: [left_st_vl53l0@39] Initialized
    [00:00:00.477,600] <dbg> VL53L0X: vl53l0x_init: [right_st_vl53l0x@29] Shutdown
    [00:00:00.477,630] <dbg> VL53L0X: vl53l0x_init: [right_st_vl53l0x@29] Initialized
    *** Booting nRF Connect SDK 3758bcbfa5cd ***
    [00:00:02.477,874] <dbg> VL53L0X: vl53l0x_start: [right_st_vl53l0x@29] Starting
    [00:00:02.503,356] <dbg> VL53L0X: vl53l0x_start: [right_st_vl53l0x@29] VL53L0X_GetDeviceInfo = 0
    [00:00:02.503,387] <dbg> VL53L0X: vl53l0x_start:    Device Name : VL53L0X ES1 or later
    [00:00:02.503,417] <dbg> VL53L0X: vl53l0x_start:    Device Type : VL53L0X
    [00:00:02.503,448] <dbg> VL53L0X: vl53l0x_start:    Device ID : VL53L0CAV0DH/1$5
    [00:00:02.503,479] <dbg> VL53L0X: vl53l0x_start:    ProductRevisionMajor : 1
    [00:00:02.503,479] <dbg> VL53L0X: vl53l0x_start:    ProductRevisionMinor : 1
    [00:00:02.778,198] <dbg> VL53L0X: vl53l0x_start: [right_st_vl53l0x@29] Started
    [00:00:03.816,741] <dbg> VL53L0X: vl53l0x_start: [left_st_vl53l0@39] Starting
    [00:00:03.818,511] <dbg> VL53L0X: vl53l0x_start: [left_st_vl53l0@39] I2C address reconfigured
    [00:00:03.843,933] <dbg> VL53L0X: vl53l0x_start: [left_st_vl53l0@39] VL53L0X_GetDeviceInfo = 0
    [00:00:03.843,963] <dbg> VL53L0X: vl53l0x_start:    Device Name : VL53L0X ES1 or later
    [00:00:03.843,994] <dbg> VL53L0X: vl53l0x_start:    Device Type : VL53L0X
    [00:00:03.844,024] <dbg> VL53L0X: vl53l0x_start:    Device ID : VL53L0C@V0DH/1$1
    [00:00:03.844,024] <dbg> VL53L0X: vl53l0x_start:    ProductRevisionMajor : 1
    [00:00:03.844,055] <dbg> VL53L0X: vl53l0x_start:    ProductRevisionMinor : 1
    [00:00:03.976,074] <err> VL53L0X: [left_st_vl53l0@39] VL53L0X_PerformRefCalibration failed
    leftSensor_sample_fetch failed ret -134

  • Quite chuffed, I fixed the issue.

    It seems as though in the process or initialisation the tof sensor with the non-default address has to be initialised first, why? No clue. Below is the working code for anyone who runs into the same problem:

    My application code:

    #include <zephyr/kernel.h>
    #include <zephyr/device.h>
    #include <zephyr/drivers/sensor.h>
    #include <zephyr/sys/printk.h>
    #include <zephyr/drivers/gpio.h>
    
    #define LEFT_SENSOR_NODE DT_NODELABEL(left_sensor)
    #define RIGHT_SENSOR_NODE DT_NODELABEL(right_sensor)
    
    static const struct device *const leftSensor = DEVICE_DT_GET(LEFT_SENSOR_NODE);
    
    static const struct device *const rightSensor = DEVICE_DT_GET(RIGHT_SENSOR_NODE);
    
    int main(void)
    {
        struct sensor_value leftSensorValue;
        struct sensor_value rightSensorValue;
        int ret;
    
        k_sleep(K_MSEC(1000));
    
        if (!device_is_ready(rightSensor)) {
    	    printk("Left Sensor: device not ready.\n");
    	    return 0;
    	}
    
    	k_sleep(K_MSEC(1000));
    
        ret = sensor_sample_fetch(rightSensor);
    	if (ret) {
    		printk("leftSensor_sample_fetch failed ret %d\n", ret);
    		return 0;
    	}
    
    	k_sleep(K_MSEC(1000));
    
        if (!device_is_ready(leftSensor)) {
    	    printk("Right Sensor: device not ready.\n");
    	    return 0;
    	}
    	ret = sensor_sample_fetch(leftSensor);
    	if (ret) {
    		printk("leftSensor_sample_fetch failed ret %d\n", ret);
    		return 0;
    	}
    	
    	while (1) {
    		ret = sensor_sample_fetch(leftSensor);
    		if (ret) {
    			printk("sensor_sample_fetch failed ret %d\n", ret);
    			return 0;
    		}
    
    		//ret = sensor_channel_get(leftSensor, SENSOR_CHAN_PROX, &leftSensorValue);
    		//printk("prox is %d\n", leftSensorValue.val1);
    
    		ret = sensor_channel_get(leftSensor,
    					 SENSOR_CHAN_DISTANCE,
    					 &leftSensorValue);
    		printf("Left Sensor distance is %.3fm\n", sensor_value_to_double(&leftSensorValue));
                    
    		k_sleep(K_MSEC(100));
    		ret = sensor_sample_fetch(rightSensor);
    		if (ret) {
    			printk("sensor_sample_fetch failed ret %d\n", ret);
    			return 0;
    		}
    
    		//ret = sensor_channel_get(leftSensor, SENSOR_CHAN_PROX, &leftSensorValue);
    		//printk("prox is %d\n", leftSensorValue.val1);
    
    		ret = sensor_channel_get(rightSensor,
    					 SENSOR_CHAN_DISTANCE,
    					 &rightSensorValue);
    		printf("Right Sensor distance is %.3fm\n", sensor_value_to_double(&rightSensorValue));
                    
    		k_sleep(K_MSEC(1000));
    	}
    	
    	return 0;
    }
    

    My devicetree overlay:

    &i2c1 {
        
        left_sensor: left_st_vl53l0x@29{
            compatible = "st,vl53l0x";
            status = "okay";
            reg = < 0x29 >;
            xshut-gpios = < &gpio0 30 (GPIO_ACTIVE_LOW)>;
        };
        right_sensor: right_st_vl53l0@2a{
            compatible = "st,vl53l0x";
            status = "okay";
            reg = < 0x2a >;
            xshut-gpios = < &gpio0 8 (GPIO_ACTIVE_LOW)>;
        };
    };
    &pinctrl {
    	i2c1_default: i2c1_default{
    		group1 {
    			psels = <NRF_PSEL(TWIM_SDA, 0, 5)>,
    				<NRF_PSEL(TWIM_SCL, 0, 4)>;
    		};
    	};
    
    	i2c1_sleep: i2c1_sleep{
    		group1 {
    			psels = <NRF_PSEL(TWIM_SDA, 0, 5)>,
    				<NRF_PSEL(TWIM_SCL, 0, 4)>;
    			low-power-enable;
    		};
    	};
    
    };

    Kconfig:

    CONFIG_STDOUT_CONSOLE=y
    CONFIG_I2C=y
    CONFIG_GPIO=y
    CONFIG_SENSOR=y
    CONFIG_VL53L0X_PROXIMITY_THRESHOLD=100
    CONFIG_TFM_SECURE_UART=n
    CONFIG_TFM_LOG_LEVEL_SILENCE=y
    CONFIG_VL53L0X_RECONFIGURE_ADDRESS=y
    #debug
    CONFIG_DEBUG=y
    CONFIG_LOG=y
    CONFIG_SENSOR_LOG_LEVEL_DBG=y
    CONFIG_CBPRINTF_FP_SUPPORT=y

    Best,

    Declan S

Related