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