2 Garmin Lidar-Lite Sensors using I2C

The post Switching Device Address on a Garmin LIDAR Sensor via I2C
closed with an unanswered request for a complete working example for 2 Garmin LidarLite units communicating over I2C.

Here's a stripped-down version of the v3HP_I2C sketch provided with Garmin's LidarLite Arduino Library, modified to work with 2 of the LIDAR-Lite_v3HP sensors. The power enable (orange) wire of one sensor is connected to GPIO pin 6 to allow it to be disabled while the I2C address on the other is changed.

// LIDAR-Lite - Version: 3.0.6
#include <stdint.h>
#include <Wire.h>
#include <LIDARLite_v3HP.h>

LIDARLite_v3HP myLidarLite1;
LIDARLite_v3HP myLidarLite2;
const uint8_t lidar1_address = LIDARLITE_ADDR_DEFAULT;  //0x62
const uint8_t lidar2_address = 0x64;
const int lidar1_en_pin = 6;

#define FAST_I2C

void setup()
{
    pinMode(lidar1_en_pin, OUTPUT);

    // Initialize Arduino serial port (for display of ASCII output to PC)
    Serial.begin(115200);

    // Initialize Arduino I2C (for communication to LidarLite)
    Wire.begin();
    #ifdef FAST_I2C
        #if ARDUINO >= 157
            Wire.setClock(400000UL); // Set I2C frequency to 400kHz (for Arduino Due)
        #else
            TWBR = ((F_CPU / 400000UL) - 16) / 2; // Set I2C frequency to 400kHz
        #endif
    #endif

    // Disable sensor 1 until sensor 2 addr changed
    digitalWrite(lidar1_en_pin, LOW);
    myLidarLite2.setI2Caddr(lidar2_address, true);
    
    // Configure the LidarLite internal parameters so as to lend itself to
    // various modes of operation by altering 'configure' input integer to
    // anything in the range of 0 to 5. See LIDARLite_v3HP.cpp for details.
    myLidarLite2.configure(0,lidar2_address);
    
    // Re-enable sensor 1
    digitalWrite(lidar1_en_pin, HIGH);
    myLidarLite1.configure(0);
}


void loop()
{
    uint16_t distance;
    uint8_t  newDistance = 0;

    // Continuous loop
    while (1)
    {
        // Lidar 1
        delay(250); // 4 Hz
        newDistance = distanceFast(myLidarLite1, lidar1_address,&distance);

        // When there is new distance data, print it to the serial port
        if (newDistance)
        {
            Serial.println(distance);
        }

        // Lidar 2
        delay(250); // 4 Hz
        newDistance = distanceFast(myLidarLite2, lidar2_address,&distance);

        // When there is new distance data, print it to the serial port
        if (newDistance)
        {
            Serial.print("    ");
            Serial.println(distance);
        }
    }
}

//---------------------------------------------------------------------
// Read Single Distance Measurement
//
// This is the simplest form of taking a measurement. This is a
// blocking function as it will not return until a range has been
// taken and a new distance measurement can be read.
//---------------------------------------------------------------------
uint8_t distanceSingle(LIDARLite_v3HP& sensor, uint8_t lidar_address, uint16_t * distance)
{
    // 1. Wait for busyFlag to indicate device is idle. This must be
    //    done before triggering a range measurement.
    sensor.waitForBusy(lidar_address);

    // 2. Trigger range measurement.
    sensor.takeRange(lidar_address);

    // 3. Wait for busyFlag to indicate device is idle. This should be
    //    done before reading the distance data that was triggered above.
    sensor.waitForBusy(lidar_address);

    // 4. Read new distance data from device registers
    *distance = sensor.readDistance(lidar_address);

    return 1;
}

//---------------------------------------------------------------------
// Read Distance Measurement, Quickly
//
// Read distance. The approach is to poll the status register until the device goes
// idle after finishing a measurement, send a new measurement command, then read the
// previous distance data while it is performing the new command.
//---------------------------------------------------------------------
uint8_t distanceFast(LIDARLite_v3HP& sensor, uint8_t lidar_address,uint16_t * distance)
{
    // 1. Wait for busyFlag to indicate device is idle. This must be
    //    done before triggering a range measurement.
    sensor.waitForBusy(lidar_address);

    // 2. Trigger range measurement.
    sensor.takeRange(lidar_address);

    // 3. Read previous distance data from device registers.
    //    After starting a measurement we can immediately read previous
    //    distance measurement while the current range acquisition is
    //    ongoing. This distance data is valid until the next
    //    measurement finishes. The I2C transaction finishes before new
    //    distance measurement data is acquired.
    *distance = sensor.readDistance(lidar_address);

    return 1;
}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.