RPLidar Values are inconsistent (Any help is appreciated)

Hello Everyone I am using RpLidar A1M8 from SlamTec and I followed the tutorial from "https://www.instructables.com/How-to-Use-the-RPLIDAR-360-Laser-Scanner-With-Ardu/" to set up my arudino and lidar. From this video the value of the angle and distance are consistent and sensical. However mine returns arbitrary values here is a screenshot:


I have tried multiple different baudrates and changing wires but to no avail.
Here is my code running on arduino:

#include <RPLidar.h>
#include <Encoder.h>

RPLidar lidar;

// L298N control pins
const int LEFT_MOTOR_IN1 = 0;  // Direction pin 1 for left motor
const int LEFT_MOTOR_IN2 = 0;  // Direction pin 2 for left motor

const int RIGHT_MOTOR_IN3 = 5;  // Direction pin 1 for right motor
const int RIGHT_MOTOR_IN4 = 4;  // Direction pin 2 for right motor

const int PIN_ENCOD_A_MOTOR_LEFT = 43;  // A channel for encoder of left motor
const int PIN_ENCOD_B_MOTOR_LEFT = 42;  // B channel for encoder of left motor

const int PIN_ENCOD_A_MOTOR_RIGHT = 52;  // A channel for encoder of right motor
const int PIN_ENCOD_B_MOTOR_RIGHT = 53;  // B channel for encoder of right motor

long pos_left = 0;   // Left motor encoder position
long pos_right = 0;  // Right motor encoder position

Encoder leftEncoder(PIN_ENCOD_A_MOTOR_LEFT, PIN_ENCOD_B_MOTOR_LEFT);
Encoder rightEncoder(PIN_ENCOD_A_MOTOR_RIGHT, PIN_ENCOD_B_MOTOR_RIGHT);

void setup() {
  Serial1.begin(19200);
  lidar.begin(Serial1);
  lidar.startScan();

  // Set up motor control pins
  pinMode(LEFT_MOTOR_IN1, OUTPUT);
  pinMode(LEFT_MOTOR_IN2, OUTPUT);

  pinMode(RIGHT_MOTOR_IN3, OUTPUT);
  pinMode(RIGHT_MOTOR_IN4, OUTPUT);

  Serial.begin(19200);

  // Define the rotary encoder for left motor
  pinMode(PIN_ENCOD_A_MOTOR_LEFT, INPUT_PULLUP);
  pinMode(PIN_ENCOD_B_MOTOR_LEFT, INPUT_PULLUP);

  // Define the rotary encoder for right motor
  pinMode(PIN_ENCOD_A_MOTOR_RIGHT, INPUT);
  pinMode(PIN_ENCOD_B_MOTOR_RIGHT, INPUT);
}

float minDist = 100000;
float angleAtMinDist = 0;

void loop() {
  getLidarResults();
  pos_right = rightEncoder.read();
  pos_left = leftEncoder.read();
}

void getLidarResults() {
  if (IS_OK(lidar.waitPoint())) {
    float distance = lidar.getCurrentPoint().distance;  // distance value in mm unit
    float angle = lidar.getCurrentPoint().angle;        // angle value in degree

    if (lidar.getCurrentPoint().startBit) {
      minDist = 100000;
      angleAtMinDist = 0;
    } else {
      if (distance > 0 && distance < minDist) {
        minDist = distance;
        angleAtMinDist = angle;
      }
    }
    // Print the current distance and angle
    printData(distance, angle);
    delay(500);
  } else {
    rplidar_response_device_info_t info;
    if (IS_OK(lidar.getDeviceInfo(info, 100))) {
      // detected...
      lidar.startScan();
      delay(1000);
    }
  }
}

void printData(float distance, float angle) {
  Serial.print("dist (meters): ");
  Serial.print(distance / 1000.0);  // Convert mm to meters
  Serial.print("     angle: ");
  Serial.println(angle);
}

Sorry your screen shot is not readable. Consider reading the forum guidelines they will help.

1 Like


Here is another screenshot

Cut and paste text, not screenshots. Consider reading the forum guidelines they will help.

Test the lidar by itself, with simple example code, and make sure it is working properly before adding other code. Arduino device libraries usually include example code for testing.

I used the following sample code:

/*
 * RoboPeak RPLIDAR Arduino Example
 * This example shows the easy and common way to fetch data from an RPLIDAR
 * 
 * You may freely add your application code based on this template
 *
 * USAGE:
 * ---------------------------------
 * 1. Download this sketch code to your Arduino board
 * 2. Connect the RPLIDAR's serial port (RX/TX/GND) to your Arduino board (Pin 0 and Pin1)
 * 3. Connect the RPLIDAR's motor ctrl pin to the Arduino board pin 3 
 */
 
/* 
 * Copyright (c) 2014, RoboPeak 
 * All rights reserved.
 * RoboPeak.com
 *
 * Redistribution and use in source and binary forms, with or without modification, 
 * are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, 
 *    this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice, 
 *    this list of conditions and the following disclaimer in the documentation 
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
 * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 
 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */
 
// This sketch code is based on the RPLIDAR driver library provided by RoboPeak
#include <RPLidar.h>

// You need to create an driver instance 
RPLidar lidar;

#define RPLIDAR_MOTOR 3 // The PWM pin for control the speed of RPLIDAR's motor.
                        // This pin should connected with the RPLIDAR's MOTOCTRL signal 
                       
                        
void setup() {
  // bind the RPLIDAR driver to the arduino hardware serial
  Serial.begin(9600);
  lidar.begin(Serial1);
  
  // set pin modes
  pinMode(RPLIDAR_MOTOR, OUTPUT);
}

void loop() {
  if (IS_OK(lidar.waitPoint())) {
    float distance = lidar.getCurrentPoint().distance; //distance value in mm unit
    float angle    = lidar.getCurrentPoint().angle; //anglue value in degree
    bool  startBit = lidar.getCurrentPoint().startBit; //whether this point is belong to a new scan
    byte  quality  = lidar.getCurrentPoint().quality; //quality of the current measurement
    
    //perform data processing here... 
    //Serial.print(distance);
    Serial.println(angle);
    
  } else {
    analogWrite(RPLIDAR_MOTOR, 0); //stop the rplidar motor
    
    // try to detect RPLIDAR... 
    rplidar_response_device_info_t info;
    if (IS_OK(lidar.getDeviceInfo(info, 100))) {
       // detected...
       lidar.startScan();
       
       // start motor rotating at max allowed speed
       analogWrite(RPLIDAR_MOTOR, 255);
       delay(1000);
    }
  }
}

I am getting absurd angle values : 511.73
255.98
497.52
254.98
383.98
497.98
503.92
510.23

Have you contacted SlamTec for support? The device is hardly ever mentioned on this forum, so it is unlikely that any of the regulars have hands on experience with it.

Absurd angles are reported as normal here:

They suggest subtracting 360.

The randomness in angles might be from slow sampling due to low baud rates, and delays causing many of the 8000 samples/period to be skipped as the turntable spins.

I'd modify the sample code to increase the baud rate and show the times:

/*
   RoboPeak RPLIDAR Arduino Example
   This example shows the easy and common way to fetch data from an RPLIDAR

   You may freely add your application code based on this template

   USAGE:
   ---------------------------------
   1. Download this sketch code to your Arduino board
   2. Connect the RPLIDAR's serial port (RX/TX/GND) to your Arduino board (Pin 0 and Pin1)
   3. Connect the RPLIDAR's motor ctrl pin to the Arduino board pin 3
*/

/*
   Copyright (c) 2014, RoboPeak
   All rights reserved.
   RoboPeak.com

   Redistribution and use in source and binary forms, with or without modification,
   are permitted provided that the following conditions are met:

   1. Redistributions of source code must retain the above copyright notice,
      this list of conditions and the following disclaimer.

   2. Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation
      and/or other materials provided with the distribution.

   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
   EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
   SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
   OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
   TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
   EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

*/

// This sketch code is based on the RPLIDAR driver library provided by RoboPeak
#include <RPLidar.h>

// You need to create an driver instance
RPLidar lidar;

#define RPLIDAR_MOTOR 3 // The PWM pin for control the speed of RPLIDAR's motor.
// This pin should connected with the RPLIDAR's MOTOCTRL signal


void setup() {
  // bind the RPLIDAR driver to the arduino hardware serial
  Serial.begin(115200);
  lidar.begin(Serial1);

  // set pin modes
  pinMode(RPLIDAR_MOTOR, OUTPUT);
}

void loop() {
  if (IS_OK(lidar.waitPoint())) {
    float distance = lidar.getCurrentPoint().distance; //distance value in mm unit
    float angle    = lidar.getCurrentPoint().angle; //anglue value in degree
    bool  startBit = lidar.getCurrentPoint().startBit; //whether this point is belong to a new scan
    byte  quality  = lidar.getCurrentPoint().quality; //quality of the current measurement

    //perform data processing here...
    Serial.print(millis());
    Serial print(" ");
    Serial.print(angle);
    //Serial print(" ");
    //Serial.print(distance);
    //Serial print(" ");
    //Serial.print(distance);
    Serial.println();

  } else {
    analogWrite(RPLIDAR_MOTOR, 0); //stop the rplidar motor

    // try to detect RPLIDAR...
    rplidar_response_device_info_t info;
    if (IS_OK(lidar.getDeviceInfo(info, 100))) {
      // detected...
      lidar.startScan();

      // start motor rotating at max allowed speed
      analogWrite(RPLIDAR_MOTOR, 255);
      delay(1000);
    }
  }
}

Thanks for the heads up! Looks like the RPLidar is yet another unfinished, expensive, poorly documented, poorly supported product to avoid.

I liked the concept, but most of the documentation looks like sales literature.

Their library is 10 years old and still on the initial commit. It doesn't seem to indicate how to change to the advertised 8000, 4000, or 2000 Hz sampling. It looks like the library receives 5 bytes/sample at 115200 baud, so by default, maybe it's effectively only 2000Hz.

Never been impressed with the quality of any coding project I've seen on Instructables. You're welcome to try my port of Slamtec's drivers. It requires an ESP32 board with PSRAM. It includes an example that I tested with an A1M8.
https://github.com/gfvalvo/SlamtecLidarESP32

Were you able to get useful, reliable data from the sensor?

Yes, in my limited testing. I was able to produce a crude polar graph like that displayed by the SlamTech demo GUI. I'm not a Windows app developer, so I didn't try to create the polished product they did.

What sort of sampling rates did you get? SlamTech advertises 2000-8000 Hz, but their arduino library code examples look very slow and as if it would skip lots of points.

Was the sensor ever used in a practical application, like a mobile robot?

Truthfully, it's been a while since I ported SlamTech's SDK to ESP32 and I no long have the setup assembled. I'd encourage someone to try the code from GitHub.

Who is "their"? I'm not aware of an Arduino library from SlamTech. What's being discussed in this thread is from robopeak.

The code I have on GitHub is an ESP32 port of SlamTech's multi-threaded SDK.

1 Like

Robopeak was the one I meant.

So, out of curiosity, I reconnected my A1M8 setup and instrumented the code to gather some statistics. First, here are the available Scan Modes supported by my unit along with some other information it reports:

Firmware Ver: 1.29
Hardware Rev: 7
Resetting
SLAMTEC Lidar health status : 0
Motor Speed Control Support: None

Avaiable Scan Modes:

Mode ID: 0, Mode Name: Standard, uS Per Sample: 508.00, Max Distance: 12.00, Answer Type: 0x81
Mode ID: 1, Mode Name: Express, uS Per Sample: 254.00, Max Distance: 12.00, Answer Type: 0x82
Mode ID: 2, Mode Name: Boost, uS Per Sample: 127.00, Max Distance: 12.00, Answer Type: 0x84
Mode ID: 3, Mode Name: Sensitivity, uS Per Sample: 127.00, Max Distance: 12.00, Answer Type: 0x84
Mode ID: 4, Mode Name: Stability, uS Per Sample: 201.00, Max Distance: 12.00, Answer Type: 0x84

Here is the performance data measured by my code:

Scan Mode: Standard
Scans Rate: 7.6 Scans/Second
Sample Period: 511.9 us
Sample Rate: 1954 Samples/Second

Scan Mode: Express
Scans Rate: 7.3 Scans/Second
Sample Period: 267.5 us
Sample Rate: 3738 Samples/Second

Scan Mode: Boost
Scans Rate: 7.6 Scans/Second
Sample Period: 127.9 us
Sample Rate: 7818 Samples/Second

Scan Mode: Sensitivity
Scans Rate: 7.6 Scans/Second
Sample Period: 127.9 us
Sample Rate: 7817 Samples/Second

Scan Mode: Stability
Scans Rate: 7.6 Scans/Second
Sample Period: 201.0 us
Sample Rate: 4975 Samples/Second

The values are pretty close to what is claimed. The Scan Rate is the same for all modes. The value of 7.6 complete scans per second corresponds to 456 RPM which seems plausible.

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.