LiDAR Scanner Using the LW20 Mini Laser Module

LiDAR has become a hot topic recently with the advent of self-driving cars and greater autonomy for both drones and ground based robots, but these sensors have been very expensive, bulky and complicated to use. LightWare recently announced the launch of a tiny LiDAR module called the LW20 that can be attached to a regular, digital servo to create SLAM maps and give proximity alarms to trigger changes of direction or other avoidance actions.

One of the amazing features of the LW20 is that it includes hardware and software to drive a conventional servo, either aiming it in a specific direction or moving it in a continuous scanning pattern. Only digital servos are compatible with the LW20 because the update rate is too fast for analog servos.

Different servos have a different range of movement, typically from ±30 to ±180 degrees and the angular resolution (number of us change in the PWM width that causes 1 degree of movement) of each type of servo is different. So the LW20 has a set of commands specifically for servo setup. This means that you can connect almost any type of digital servo and configure the LW20 to control it accurately.

I downloaded the free 3D printable servo bracket for the LW20 from here: 3D printer file and mounted the LW20 onto a DS919MG servo from Corona. In the picture below there’s also a stand that my wife designed to hold the whole thing upright for bench-top testing.

With the onboard drivers handling the servo, it’s easy to connect a standard Arduino without the need for a shield or any extra hardware. The version of the LW20 that I have uses a serial port for communication and I connected this to COM1 on my Arduino Mega. There’s a version of the LW20 that uses I2C instead.

The LW20 is capable of transmitting results 388 times per second at a baud rate of 921600. This is a little too fast for the Mega so I set the LW20 to a baud rate of 115200 and matched it with the Mega.

The LW20 can stream results or supply answers when asked. The comms protocol uses simple ASCII strings and you can directly interrogate the LW20, change settings, switch on selected data streams or perform actions. For example, typing the following command sequence directly to the serial port of the LW20 moves the servo to the central position:

?P // Ping the LW20 to confirm that it is connected
#SC,1 // Activate the servo driver
#SM // Move the servo to the middle position

The full command set can be found in the manual here.

The LW20 also provides support for complex actions. For example, it can be set to stream a complete SLAM map as it scans or you can pre-configure alarm zones so that you don’t need to analyze the raw data. The alarms can be set to look to the right and left of center so that any unexpected obstacles in these zones would trigger a corresponding steer left or steer right decision in a navigation sketch running on the Arduino.

The LW20 has a really long measuring range of up to 100m and it is in an IP67 (waterproof) housing, so it is well suited to the outdoor operation of drones or ground based robots that need to avoid things like trees.

Software genius Robert has written an Arduino library for the LW20 (see attachment) that lets you configure the servo, set scanning parameters and initialize sense-and-avoid alarms in just a few lines of code. The sample sketch below does just this:

#include <LW20.h>                         // Include the LW20 library

LW20 lw20(Serial1, 115200);               // Instantiate the LW20 using the hardware Serial Port1 at 115200 baud

void setup() 
{
  // Start serial monitor port.
  Serial.begin(115200);                 // Prepare the USB Terminal to use as a monitor

  // Setup LW20.
  lw20.init();                          // Get the LW20 ready for commands
  lw20.setLaserParams(LW20_MODE_388);   // Set the LW20 update rate to 388 readings per second
  lw20.setServoParams(1000, 2000, 10);  // Configure the servo PWM from 1ms to 2ms with a resolution of 10us per degree
  lw20.setScanParams(-30, 30, 8, 3.5);  // Set the scanning field of view to ±30 degrees, stepping 8 times per result, compensating for 3.5 degrees of servo lag
  lw20.setAlarmAParams(3.5, -15, 0);    // Set up Alarm A at 3.5m in a segment from -15 degrees to straight ahead
  lw20.setAlarmBParams(3.5, 0, 15);     // Set up Alarm B at 3.5m in a segment from straight ahead to +15 degrees 
  lw20.startScan();                     // Start an automatic scan using the above parameters
}

void loop() 
{
                                        // Check the alarm status every 100ms
  bool a, b;
  lw20.checkAlarmStatus(&a, &b);        // Check the status of both alarms simultaneously

  Serial.print("Alarm A:");             // Print out the alarm status on the USB Terminal
  Serial.print(a);
  Serial.print(" Alarm B:");
  Serial.println(b);
  
  delay(100);
}

The sketch works as follows:

  • The LW20 is initialized and configured to run at 388 readings per second.
  • The electrical specifications of the servo are given to the LW20 so that it knows how to drive the servo to its limits and what angular resolution the servo has.
  • The scanning characteristics of the servo are set to give a 60 degree field of view (±30). This servo is limited to ±45 degrees.
  • The movement speed of the servo set to 8 steps per result giving an angular resolution of 0.5 degrees.
  • The LW20 compensates for servo lag of 3.5 degrees. There is a detailed explanation of servo lag in the LW20 manual.
  • Alarm A is configured to trigger when an object is found left of center and within 3.5m.
  • Alarm B is configured to trigger when an object is found right of center and within 3.5m.
  • The LW20 is is told to start automatic scanning.
  • The status of the alarms is checked every 100ms and reported back to the USB Terminal.

The results of the LW20 scan would be used to provide autonomous navigation or collision avoidance information to the main program of the sketch. The LW20 can be made to do lots of other things by using the full API and if you are interested then you will be able to download updates from the LightWare website as they become available.

Thanks for reading :slight_smile: L.D.

LW20.zip (9.57 KB)

Thank you. Works perfectly fine with my Arduino mega! Do you have also a sample sketch for using I2C?

Hi L.D.

Thanks for your post.

I have been able to use LW20 library and your posted code to get alarms into Arduino serial monitor from LW20 laser. It works really nice!!

Our goal is to obtain distance and angle from laser. Once these parameters are available on Arduino and after some processing, we will be sending it to an auto-pilot device.

You mentioned on you post that LW20 can stream results or supply answers when ask. And that we can directly interrogate the LW20 (No need for LW20 library).

I have tried to achieved this using Serial.Write function on Serial1 port (Ping 18/19 EtherMega). Unfortunately I don't think I have been able to write any commands to LW20 yet.

Could you please share an example of write function that you would use to interact with LW20 without using LW20 library? Mainly I an struggling on how to build the string to be sent to LW20 to start streaming results.

Thanks in advance for your help.

Best Regards CV