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;
}