LiDAR via RT-Thread

RT-Thread connects to RPlidar A1 LiDAR

Some of the earliest smart cars may have some ultrasonic modules to determine the obstacles ahead, and cooperate with the rotation of the servo to know the distribution of obstacles in all directions. But if laser radar is used, the obstacle distribution within a 360-degree range can be obtained at one time.

LiDAR has basically become an essential sensor for driverless cars. Of course, its cost is not low. This document will introduce how to use RT-Thread to obtain the scanning data of SLAM RPLidar A1.

In fact, Silam's laser radar sends control commands through the serial port, and then the laser radar responds by sending scanning results from the serial port. It can be parsed according to Silam's communication protocol . The following documents will not introduce the communication protocol in detail, after all, the official documents have already introduced it in detail.

Before we start, you need to prepare these things:

  • Build the RT-Thread environment ( Git , Env tools , RT-Thread source code )

  • RPLidar A1 (or other A series)

  • STM32 (or other development boards that can run RT-Thread, which need to have 2 serial ports)

Before introducing the wiring, here is a link to the official documentation , where you can find the user manual , ROS software package , SDK instructions , communication protocol and many other important materials.

I am using the STM32-L746RG Nucleo development board, but you can also use other boards that can run RT-Thread and have two serial ports .

The wiring of STM32 and LiDAR can be referred to here , which mainly involves the power supply to the motor and the serial port RX TX.

Here is a summary of the wiring:

After connecting the cables and powering on, you should be able to see the LiDAR start to rotate.

Before downloading the RPlidar software package, you need to configure the two serial ports of the development board, one for msh debugging and one for connecting to the lidar.

Taking STM32 as an example, after downloading the RT-Thread source code, according to the board model I have, I enter the rt-thread/bsp/stm32/stm32l476-st-nucleo directory, and find CubeMX_Config.ioc ​​under board/CubeMX_Config to open it.

Here I configured two serial ports UART2 (MSH) and UART3 (LiDAR), which can be adjusted according to your own board. Then CubeMX generates code and copies the SystemClock_Config function under main.c in the generated project to board.c and replace it.

Next we need to edit board/Kconfig and add the serial port configuration in it. Of course, if your BSP already has relevant configuration, this is not necessary.

menuconfig BSP_USING_UART
    bool "Enable UART"
    default y
    select RT_USING_SERIAL
    if BSP_USING_UART
        config BSP_USING_UART2
            bool "Enable UART2"
            default n

        config BSP_UART2_RX_USING_DMA
            bool "Enable UART2 RX DMA"
            depends on BSP_USING_UART2 && RT_SERIAL_USING_DMA
            default n
    endifcopymistakeCopy Success

Next we can download the software package and right-click to open the env tool.

Enter menuconfig and enter Hardware Drivers to open two serial ports:

Then go to RT-Thread Online Package and select the RPLidar software package:

After the software package is selected, we save the KConfig configuration and then download the software package. Enter in env:

pkgs --updatecopymistakeCopy Success

Now that we have downloaded the RPLidar software package, we can start compiling and obtaining the lidar data.

If the RPLidar software package cannot be found in Peripheral libraries and drivers , you need to update the software package repository by running pkgs --upgrade under env first.

The wiring is completed, the serial port configuration is completed, and the software package is downloaded. Finally, we can compile and upload.

For compilation, we can use Keil or arm-none-gcc that comes with env. If using Keil, generate the project first:

scons --target=mdk5 -scopymistakeCopy Success

Then you can open the Keil project and compile it. If it is arm-none-gcc, you can compile it directly under env.

sconscopymistakeCopy Success

Here is a brief introduction to the routine code, taking the laser radar reset as an example:

#include <rtthread.h>
#include "rplidar.h"

#define RPLIDAR_DEVICE_NAME    "rplidar"    /* 设备名称 */

static int rplidar_stop_example(int argc, char *argv[])
{
    rt_err_t ret;

    // 获取激光雷达设备
    rt_device_t lidar = rp_lidar_create(RPLIDAR_DEVICE_NAME);
    if(lidar == RT_NULL)
    {
        rt_kprintf("Failed to find device %s\n", RPLIDAR_DEVICE_NAME);
        return -1;
    }

    // 雷达初始化
    ret = rp_lidar_init(lidar);
    if(ret != RT_EOK)
    {
        rt_kprintf("Failed to init lidar device\n");
        return -1;
    }

    // 发送停止命令
    ret = rp_lidar_stop(lidar);
    if(ret == RT_EOK)
    {
        rt_kprintf("Lidar stopped scanning\n");
    }
    else
    {
        rt_kprintf("Failed to communicate with lidar device\n");
    }

    return RT_EOK;
}
MSH_CMD_EXPORT(rplidar_stop_example, rplidar stop example);copymistakeCopy Success

The code is very short and I have added some comments so I won’t repeat them. The main process is:

1. 获取雷达设备  rp_lidar_create
2. 雷达初始化    rp_lidar_init
3. 发送控制命令  rp_lidar_scan
4. 获取雷达数据  rp_lidar_get_scan_datacopymistakeCopy Success

After the firmware is compiled and uploaded, you can use the serial debugging assistant to open msh. Here I use putty or kitty , enter rplidar and then Tab to automatically complete. You can see that there are many commands:

If you enter rplidar_scan_and_recv_example, you can see the results of a scan:

Silan LiDAR can communicate with MCU through serial port, and then MCU sends control instructions, such as scan (0xA5 0x20), LiDAR will continuously send scan data from serial port, and the next thing to do is to parse the data, which has been completed in RT-Thread's rplidar software package. More APIs can be found here .

rt_device_t rp_lidar_create(const char* lidar_name);
rt_err_t rp_lidar_init(rt_device_t lidar);

rt_err_t rp_lidar_scan(rt_device_t lidar, _u32 timeout);
rt_err_t rp_lidar_stop(rt_device_t lidar);
rt_err_t rp_lidar_reset(rt_device_t lidar);

rt_err_t rp_lidar_get_health(rt_device_t lidar, rplidar_response_device_health_t* health, _u32 timeout);
rt_err_t rp_lidar_get_device_info(rt_device_t lidar, rplidar_response_device_info_t* info, _u32 timeout);
rt_err_t rp_lidar_get_scan_data(rt_device_t lidar, rplidar_response_measurement_node_t* node, _u32 timeout);
u_result rp_lidar_wait_scan_data(rt_device_t lidar, rplidar_response_measurement_node_t * node, _u32 timeout);

u_result rp_lidar_wait_resp_header(rt_device_t lidar, rplidar_ans_header_t * header, _u32 timeout);
u_result rp_lidar_recev_data(rt_device_t lidar, _u8* buffer, size_t len, _u32 timeout);copymistakeCopy Success

By the way, because I only have Silan LiDAR A1, TCP connection and some commands that my device does not support are not implemented yet. Friends who have more advanced radars are welcome to submit PR to improve this package.

Last updated

Assoc. Prof. Wiroon Sriborrirux, Founder of Advance Innovation Center (AIC) and Bangsaen Design House (BDH), Electrical Engineering Department, Faculty of Engineering, Burapha University