Garmin LiDAR-Lite V3HP and Arduino

Recently got this new sensor for a college project. So, this is a simple guide to get this LiDAR sensor working on an Arduino Nano using the I2C bus. There is a way to interface this sensor with PWM, but this guide will not be going there.

The specifications of this sensor are impressive:

  • 40m range
  • 1cm resolution
  • 1kHz update speed
  • 0.5degree beam divergence
  • IPX7 rating

Full datasheet can be found here.


Hardware

In addition to the sensor and a microcontroller, you’ll also need a pair of 4.7k – 10k ohm pull-up resistors and a 470-680uF capacitor across 5V and GND.

The connections are as follows:

  • Red (5V) –> Arduino 5V
  • Black (GND) –> Arduino Ground
  • Green (SCL) –> Arduino A5
  • Blue (SDA) –> Arduino A4
  • Yellow (Mode Control) –> (not connected)
  • Orange (Power enable) –> (not connected; has own internal pull-up)

Software

The easiest way to interface with the sensor is to use the garmin LiDAR-lite library. Githup repo here.

The code to the right is a near enough CTRL+C & CTRL+V of the v3HP_I2C demo.

Once uploaded, open the Serial monitor and type in the command you want: “s” for single shot, “c” for a continuous measure, and “.” to stop the continuous stream.

myLidarLite.configure(0);
will take an integer between 0-5 and will change the configuration as follows:

0: Default mode, balanced performance.
1: Short range, high speed. Uses 0x1d maximum acquisition count.
2: Default range, higher speed short range. Turns on quick termination detection for faster measurements at short range (with decreased accuracy)
3: Maximum range. Uses 0xff maximum acquisition count.
4: High sensitivity detection. Overrides default valid measurement detection algorithm, and uses a threshold value for high sensitivity and noise.
5: Low sensitivity detection. Overrides default valid measurement detection algorithm, and uses a threshold value for low sensitivity and noise.

#include <stdint.h>
#include <Wire.h>
#include <LIDARLite_v3HP.h>

LIDARLite_v3HP myLidarLite;

#define FAST_I2C

enum rangeType_T {
    RANGE_NONE,
    RANGE_SINGLE,
    RANGE_CONTINUOUS,
    RANGE_TIMER
};

void setup(){
    Serial.begin(115200);
    Wire.begin();
    #ifdef FAST_I2C
        #if ARDUINO >= 157
            Wire.setClock(400000UL); 
        #else
            TWBR = ((F_CPU / 400000UL) - 16) / 2; /
        #endif
    #endif
    myLidarLite.configure(0);
}


void loop() {
    uint16_t distance;
    uint8_t  newDistance = 0;
    uint8_t  c;
    rangeType_T rangeMode = RANGE_NONE;

    PrintMenu();

    while (1) {
        if (Serial.available() > 0) {      
            c = (uint8_t) Serial.read(); 
            switch (c) {
                case 'S':
                case 's':
                    rangeMode = RANGE_SINGLE;
                    break;
                case 'C':
                case 'c':
                    rangeMode = RANGE_CONTINUOUS;
                    break;
                case 'T':
                case 't':
                    rangeMode = RANGE_TIMER;
                    break;
                case '.':
                    rangeMode = RANGE_NONE;
                    break;
                case 'D':
                case 'd':
                    rangeMode = RANGE_NONE;
                    dumpCorrelationRecord();
                    break;
                case 'P':
                case 'p':
                    rangeMode = RANGE_NONE;
                    peakStackExample();
                    break;
                case 0x0D:
                case 0x0A:
                    break;
                default:
                    rangeMode = RANGE_NONE;
                    PrintMenu();
                    break;
            }
        }

        switch (rangeMode) {
            case RANGE_NONE:
                newDistance = 0;
                break;

            case RANGE_SINGLE:
                newDistance = distanceSingle(&distance);
                break;

            case RANGE_CONTINUOUS:
                newDistance = distanceContinuous(&distance);
                break;

            case RANGE_TIMER:
                delay(250); // 4 Hz
                newDistance = distanceFast(&distance);
                break;

            default:
                newDistance = 0;
                break;
        }

        
        if (newDistance) {
            Serial.println(distance);
        }

        if (rangeMode == RANGE_SINGLE)
        {
            rangeMode = RANGE_NONE;
        }
    }
}

void PrintMenu(void)
{
    Serial.println("=====================================");
    Serial.println("== Type a single character command ==");
    Serial.println("=====================================");
    Serial.println(" S - Single Measurement");
    Serial.println(" C - Continuous Measurement");
    Serial.println(" T - Timed Measurement");
    Serial.println(" . - Stop Measurement");
    Serial.println(" D - Dump Correlation Record");
    Serial.println(" P - Peak Stack Example");
}

uint8_t distanceSingle(uint16_t * distance) {
    myLidarLite.waitForBusy();
    myLidarLite.takeRange();
    myLidarLite.waitForBusy();
    *distance = myLidarLite.readDistance();
    return 1;
}

uint8_t distanceContinuous(uint16_t * distance) {
    uint8_t newDistance = 0;
    if (myLidarLite.getBusyFlag() == 0) {
        // Trigger the next range measurement
        myLidarLite.takeRange();
        *distance = myLidarLite.readDistance();
        newDistance = 1;
    }
    return newDistance;
}

uint8_t distanceFast(uint16_t * distance) {
    myLidarLite.waitForBusy();
    myLidarLite.takeRange();
    *distance = myLidarLite.readDistance();
    return 1;
}

void dumpCorrelationRecord() {
    myLidarLite.correlationRecordToSerial(256);
}

void peakStackExample() {
    int16_t   peakArray[8];
    int16_t   distArray[8];
    uint8_t   i;
    myLidarLite.peakStackRead(peakArray, distArray);
    Serial.println();
    Serial.println("IDX PEAK DIST");
    for (i=0 ; i<8 ; i++)
    {
        Serial.print(i);
        Serial.print("   ");
        Serial.print(peakArray[i]);
        Serial.print("  ");
        Serial.print(distArray[i]);
        Serial.println();
    }
}

Page created: 26/10/2024
Last updated: 26/10/2024