Get data from Lidar Lite V3 over I2C (Zephyr os)

Hi,

I am trying to get the data from the Lidar Lite V3 sensor via the I2C bus. However, I only receive a 0 back.
So my question is the implementation generally correct?

Lidar V3 datasheet: https://static.garmin.com/pumac/LIDAR_Lite_v3_Operation_Manual_and_Technical_Specifications.pdf

Overlay file:

&arduino_i2c { /* i2c */
    compatible = "nordic,nrf-twim";
    status = "okay";
    clock-frequency = <I2C_BITRATE_FAST>;
};

prj.conf file:

CONFIG_LOG=y
CONFIG_I2C=y
CONFIG_I2C_NRFX=y
CONFIG_STDOUT_CONSOLE=y
CONFIG_PRINTK=y

main.c file :

/*
 * Copyright (c) 2012-2014 Wind River Systems, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr/kernel.h>
#include <zephyr/drivers/i2c.h>
#include <zephyr/logging/log.h>

LOG_MODULE_REGISTER(main);

#define I2C_NODE		DT_ALIAS(arduino_i2c)
#define LIDAR_I2C_ADDR	0x62
#define I2C_DEV_NAME	DT_NODELABEL(arduino_i2c)
#define DELAY_TIME K_MSEC(500)



void main(void)
{
	uint32_t i2c_cfg = I2C_SPEED_SET(I2C_SPEED_FAST) | I2C_MODE_CONTROLLER;
	const struct device *const i2c_dev = DEVICE_DT_GET(I2C_DEV_NAME);
	uint8_t data[2] = {0};
	int i2c_device_ready, ret = 0;

	if (i2c_dev == NULL || !device_is_ready(i2c_dev)) {
		LOG_INF("I2C: Device is not ready.\n");
		return;
	}else
	{
		LOG_INF("I2C: Device is ready.\n");
	}

	if (i2c_configure(i2c_dev, i2c_cfg)) {
		LOG_INF("I2C config failed\n");
		return;
	}
	while (1) 
	{
		ret = i2c_reg_write_byte(i2c_dev, LIDAR_I2C_ADDR, 0x00, 0x04);
		if (ret) {
				printk("Error writing to reg 0x00! error code (%d)\n", ret);
				return;
			}
		
		while (!i2c_device_ready)
		{	
			uint8_t ready = 55;
				ret = i2c_reg_read_byte(i2c_dev, LIDAR_I2C_ADDR, 0x01, &ready);
			if (ret) {
				printk("Error reading reg 0x01! error code (%d)\n", ret);
				return;
			}
			if (ready == 0){
				i2c_device_ready = 1;
			}
			printk("data ready: %d \n", ready);
			k_sleep(DELAY_TIME);

		}
		i2c_device_ready = 0;	

		ret =  i2c_burst_read(i2c_dev, LIDAR_I2C_ADDR, 0x8f, &data, sizeof(data));
		if (ret) {
			printk("Error writing to FRAM! error code (%d)\n", ret);
			return;
		}
		printk("data: %d \n", (data[0] << 8 + data[1]));
	}

}

  • Hello,

    Letting you know I have been assigned to this case.

    Could you please share the DK and SDK version you are trying with.

    Kind Regards,

    Abhijith

  • Sure :)

    I use the board nRF52840 DK and the nRF Connect SDK v2.2.0

  • Hello,

    First of all I am not familiar with this sensor. But the registers you mentioned in the program looks okay for  me from the data sheet. In the overlay file you need to mention the sensor as child node to the i2c controller (depending on which i2c you have used). You need to add something like below in the overlay file.

    &i2c0 {        // depending on your i2c controller
        
        lidar: lidar@62{
            compatible = "i2c-device";
            reg = < 0x62 >;
            label = "LIDAR";
        };
    };
    
    // This is just a reference

    Take a look at this tutorial from Nordic which explains the interfacing of a digital temperature sensor via I2c. In this they mention how you can edit and update the overlay and prj config.

    Kind Regards,

    Abhijith

  • Thank for u help i got it now Slight smile

    For anyone who is interested in the solution. Is not very nice implements, but is works:) 

    Overlay file:

    &i2c0 {
        status = "okay";
        clock-frequency = <I2C_BITRATE_FAST>;
    };

    main.c file:

    #include <stdio.h>
    #include <string.h>
    #include <zephyr/zephyr.h>
    #include <zephyr/device.h>
    #include <zephyr/drivers/i2c.h>
    
    #define I2C_DEV_NAME DT_NODELABEL(i2c0)
    #define LIDAR_LITE_V3_ADDRESS 0x62
    #define REG_DISTANCE 0x8f
    #define REG_READ 0x01
    
    #define LIDAR_LITE_V3_ADDRESS 0x62
    
    // Variable to store the distance measurement
    uint16_t distance;
    uint8_t register_value;
    
    // Function to get the distance
    void get_distance(struct device *i2c)
    {
        uint8_t reg_distance = REG_DISTANCE;
        uint8_t data[2] = {0};
    
        // // Send the distance register address
        i2c_write(i2c, &reg_distance, 1, LIDAR_LITE_V3_ADDRESS);
        // Read the two bytes from the Lidar Lite V3 sensor
        i2c_read(i2c, &data, 2, LIDAR_LITE_V3_ADDRESS);
    
        // Combine the two bytes into a 16-bit distance value
        distance = (data[0] << 8) | data[1];
    }
    
    void read_register(struct device *i2c)
    {
        uint8_t reg = REG_READ;
    
        // set the register 0x01 to read.
        i2c_write(i2c, &reg, 1, LIDAR_LITE_V3_ADDRESS);
        // read the status od the register 0x01
        i2c_read(i2c, &register_value, 2, LIDAR_LITE_V3_ADDRESS);
    }
    
    void main(void)
    {
        struct device *i2c;
        int ret;
    
        // Initialize the I2C bus
        i2c = DEVICE_DT_GET(I2C_DEV_NAME);
        if (!i2c)
        {
            printf("I2C: Device not found.\n");
            return;
        }
        // initiate sensor
        // for Lidar Lite V3 we have to send 0x04 to the command register before reading distance data
        uint8_t data0[2] = {0x00, 0x04};
        i2c_write(i2c, &data0, 2, LIDAR_LITE_V3_ADDRESS);
        if (ret != 0)
        {
            printf("I2C: Error while writing to command register.\n");
            return;
        }
    
        // configurie the Lidar Sensor
        uint8_t data[2] = {0x02, 0x80};
        // Write the register address and the desired value to the device
        i2c_write(i2c, &data, 2, LIDAR_LITE_V3_ADDRESS);
        // configurie the Lidar Sensor
        uint8_t data1[2] = {0x04, 0x08};
        // Write the register address and the desired value to the device
        i2c_write(i2c, &data1, 2, LIDAR_LITE_V3_ADDRESS);
        // configurie the Lidar Sensor
        uint8_t data2[2] = {0x1c, 0x00};
        // Write the register address and the desired value to the device
        i2c_write(i2c, &data2, 2, LIDAR_LITE_V3_ADDRESS);
    
        while (1)
        {
            // Read the register 0x01 and check the value of the LSB
            read_register(i2c);
            if (register_value & 0x01)
            {
                printf("LSB is high\n");
            }
            else
            {
                printf("LSB is low\n");
                // Get the distance measurement from the Lidar Lite V3 sensor
                get_distance(i2c);
                // Print the distance measurement
                printf("Distance: %d cm\n", distance);
            }
    
            // for Lidar Lite V3 we have to send 0x04 to the command register 0x00 before reading distance data
            i2c_write(i2c, &data0, 2, LIDAR_LITE_V3_ADDRESS);
    
            k_sleep(K_MSEC(100));
        }
    }

  • Hello,

    Glad to hear it worked Relaxed.

    Kind Regards,

    Abhijith

Related