garmin / LIDARLite_Arduino_Library

High-performance optical distance sensing.
Apache License 2.0
181 stars 84 forks source link

How to detect intensity of a measurement from lidar lite #14

Open TheDIYGuy opened 4 years ago

TheDIYGuy commented 4 years ago

I have a project using the lidar lite as a scanner and i want to be able to detect a reflective target i set up. I was wondering if there were any commands or functions i could use to determine the intensity of a measurement.

The end goal is to be able to perform a scan with 3 stationary reflective targets, setup at a different position, scan again near those targets, and be able to stitch these scans together with a 3D transformation using a survey technique called a resection

any help would be greatly appreciated

dwinters42 commented 4 years ago

Have not tried it, but have a look at the contents of the SIGNAL_STRENGTH register 0x0E, this should give you the return intensity (which of course depends on reflectivity, distance, angle, etc.).

You might try to use corner cubes for this application like surveyors do.

TheDIYGuy commented 4 years ago

I had a look at the contents of the register 0x0E. I used the short range high speed example the lidar lite library includes and modified it to receive the intensity instead of the distance.

I could not really analyze and understand the values i was getting. I will do more testing in the next few days pointing the lidar at a reflective target to observe the intensity values.

My code so far: I modified one of the example codes

/*------------------------------------------------------------------------------

LIDARLite Arduino Library v3/ShortRangeHighSpeed

This example shows a method for running the LIDAR-Lite at high speeds for short range operation. It uses an different approach than the default LIDAR-Lite library, showing how to read and write to the device using Wire directly, as well as various custom settings. See GetDistancePWM and GetDistanceI2C for simpler demonstrations of the device.

Connections: LIDAR-Lite 5 Vdc (red) to Arduino 5v LIDAR-Lite I2C SCL (green) to Arduino SCL LIDAR-Lite I2C SDA (blue) to Arduino SDA LIDAR-Lite Ground (black) to Arduino GND

(Capacitor recommended to mitigate inrush current when device is enabled) 680uF capacitor (+) to Arduino 5v 680uF capacitor (-) to Arduino GND

See the Operation Manual for wiring diagrams and more information: http://static.garmin.com/pumac/LIDAR_Lite_v3_Operation_Manual_and_Technical_Specifications.pdf

------------------------------------------------------------------------------*/

include

include

LIDARLite myLidarLite;

void setup() { Serial.begin(115200); // Initialize serial connection to display distance readings

/* begin(int configuration, bool fasti2c, char lidarliteAddress)

Starts the sensor and I2C.

Parameters
----------------------------------------------------------------------------
configuration: Default 0. Selects one of several preset configurations.
fasti2c: Default 100 kHz. I2C base frequency.
  If true I2C frequency is set to 400kHz.
lidarliteAddress: Default 0x62. Fill in new address here if changed. See
  operating manual for instructions.

*/ myLidarLite.begin(0, true); // Set configuration to default and I2C to 400 kHz

/* Write

Perform I2C write to device.

Parameters
----------------------------------------------------------------------------
myAddress: register address to write to.
myValue: value to write.
lidarliteAddress: Default 0x62. Fill in new address here if changed. See
  operating manual for instructions.

*/ // myLidarLite.write(0x02, 0x0d); // Maximum acquisition count of 0x0d. (default is 0x80) // myLidarLite.write(0x04, 0b00000100); // Use non-default reference acquisition count // myLidarLite.write(0x12, 0x03); // Reference acquisition count of 3 (default is 5) }

void loop() { // Take a measurement with receiver bias correction and print to serial terminal Serial.println(distanceFast(true));

// Take 99 measurements without receiver bias correction and print to serial terminal for(int i = 0; i < 99; i++) { Serial.println(distanceFast(false)); } }

// 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. int distanceFast(bool biasCorrection) { byte isBusy = 1; int distance; int loopCount; int intensity;

// Poll busy bit in status register until device is idle while(isBusy) { // Read status register Wire.beginTransmission(LIDARLITE_ADDR_DEFAULT); Wire.write(0x01); Wire.endTransmission(); Wire.requestFrom(LIDARLITE_ADDR_DEFAULT, 1); isBusy = Wire.read(); isBusy = bitRead(isBusy,0); // Take LSB of status register, busy bit

loopCount++; // Increment loop counter
// Stop status register polling if stuck in loop
if(loopCount > 9999)
{
  break;
}

}

// Send measurement command Wire.beginTransmission(LIDARLITE_ADDR_DEFAULT); Wire.write(0X00); // Prepare write to register 0x00 if(biasCorrection == true) { Wire.write(0X04); // Perform measurement with receiver bias correction } else { Wire.write(0X03); // Perform measurement without receiver bias correction } Wire.endTransmission();

//Begin reading the signal strength value Wire.beginTransmission(LIDARLITE_ADDR_DEFAULT); Wire.write(0x0e); Wire.endTransmission();

// Read the value Wire.requestFrom(LIDARLITE_ADDR_DEFAULT, 1); intensity = Wire.read();

// Immediately read previous distance measurement data. This is valid until the next measurement finishes. // The I2C transaction finishes before new distance measurement data is acquired. // Prepare 2 byte read from registers 0x0f and 0x10 Wire.beginTransmission(LIDARLITE_ADDR_DEFAULT); Wire.write(0x8f); Wire.endTransmission();

// Perform the read and repack the 2 bytes into 16-bit word Wire.requestFrom(LIDARLITE_ADDR_DEFAULT, 2); distance = Wire.read(); distance <<= 8; distance |= Wire.read();

// Return the measured distance // return distance; return intensity; }

SimonHuang135 commented 4 years ago

Hi, I also got the same issue, I use LiDAR Lite V3 and I2C connection to read signal strength from register 0x0e, however, the value can not be analysed. From V2 doc, it mentions that the signal strength should be 10 - 128, which is a 7 level digital signal, however, the values I can get are 98, 112, 126, 140, etc, which are all 14 apart and all are multiple of 7. My code is attached below, is there anything I did wrong? code.zip

TheDIYGuy commented 4 years ago

Hello, thanks for your question. I couldnt get a good look at your code as the signal strength function was missing, but i have included my intensity function and am pretty sure it is working. My numbers were not in multiples of 7. I hope this helps

int intensity() { byte isBusy = 1; int intensity; int loopCount;

// Poll busy bit in status register until device is idle while(isBusy) { // Read status register Wire.beginTransmission(LIDARLITE_ADDR_DEFAULT); Wire.write(0x01); Wire.endTransmission(); Wire.requestFrom(LIDARLITE_ADDR_DEFAULT, 1); isBusy = Wire.read(); isBusy = bitRead(isBusy,0); // Take LSB of status register, busy bit

loopCount++; // Increment loop counter
// Stop status register polling if stuck in loop
if(loopCount > 9999)
{
  break;
}

}

// Send measurement command / Wire.beginTransmission(LIDARLITE_ADDR_DEFAULT); Wire.write(0X00); // Prepare write to register 0x00 if(biasCorrection == true) { Wire.write(0X04); // Perform measurement with receiver bias correction } else { Wire.write(0X03); // Perform measurement without receiver bias correction } Wire.endTransmission(); / // read register 0x0e which is signal strength Wire.beginTransmission(LIDARLITE_ADDR_DEFAULT); Wire.write(0x0e); Wire.endTransmission(); Wire.requestFrom(LIDARLITE_ADDR_DEFAULT, 1); intensity = Wire.read();

// Return the measured intensity

return intensity; }

SimonHuang135 commented 4 years ago

Hi, Thank you for your reply. I put your intensity function into my code, however, it still shows me the signal strength are multiple of 7. (like 112, 126). If possible, could you send me ur file? Thank you

SimonHuang135 commented 4 years ago

Hi, here is my ino file with your intensity function, and I also print my original signal strength function(in cpp file) as well. Is that the computer problem which cause me get multiple of 7? Cuz I am using macbook. And BTW, could you tell me what is the signal strength value? like what unit? what range? I could not analyse it. Thank you

include

include

LIDARLite myLidarLite;

void setup() { Serial.begin(9600); // Initialize serial connection to display distance readings myLidarLite.begin(0, true); // Set configuration to default and I2C to 400 kHz myLidarLite.configure(0); // Change this number to try out alternate configurations }

int intensity() { byte isBusy = 1; int intensity; int loopCount; // Poll busy bit in status register until device is idle while(isBusy) { // Read status register Wire.beginTransmission(LIDARLITE_ADDR_DEFAULT); Wire.write(0x01); Wire.endTransmission(); Wire.requestFrom(LIDARLITE_ADDR_DEFAULT, 1); isBusy = Wire.read(); isBusy = bitRead(isBusy,0); // Take LSB of status register, busy bit } // Send measurement command / Wire.beginTransmission(LIDARLITE_ADDR_DEFAULT); Wire.write(0X00); // Prepare write to register 0x00 if(biasCorrection == true) { Wire.write(0X04); // Perform measurement with receiver bias correction } else { Wire.write(0X03); // Perform measurement without receiver bias correction } Wire.endTransmission(); / // read register 0x0e which is signal strength Wire.beginTransmission(LIDARLITE_ADDR_DEFAULT); Wire.write(0x0e); Wire.endTransmission(); Wire.requestFrom(LIDARLITE_ADDR_DEFAULT, 1); intensity = Wire.read();

// Return the measured intensity

return intensity;

}

void loop() { // Take a measurement with receiver bias correction and print to serial terminal Serial.print(myLidarLite.distance()); Serial.print(" "); Serial.print(intensity()); Serial.print(" "); Serial.println(myLidarLite.signalStrength()); // Take 99 measurements without receiver bias correction and print to serial terminal }