RT-Thread连接RPLidar激光雷达

优质
小牛编辑
137浏览
2023-12-01

引言

最早一些智能小车可能会有一些超声波模块,用来判断前方的障碍物,并配合舵机的旋转,从而知道各个方向的障碍物分布。但是如果使用激光雷达的话,可以一次性得到360度范围内的障碍物分布。

Lidar Scan

激光雷达基本上已经成为无人驾驶的必备传感器了,当然,它的成本也并不低,这篇文档将会介绍如何利用 RT-Thread 获取思岚 RPLidar A1 的扫描数据。

RPLidar A1

其实思岚的激光雷达就是串口发送控制命令,然后激光雷达响应从串口发送扫描结果,根据思岚的通信协议进行解析就可以了,后面的文档就不会具体介绍通信协议了,毕竟官方文档已经介绍的很详细了。

在开始介绍之前,需要准备好这些东西:

  • 搭建好 RT-Thread 的环境 (Git, Env 工具, RT-Thread 源码)
  • RPLidar A1 (或者其他A系列也可以)
  • STM32 (或者其他可以运行 RT-Thread 的开发板,需要有2个串口)

1. 硬件接线

在介绍接线之前,先给出官方资料链接,在这里可以找到用户手册ROS软件包SDK说明通信协议等很多重要的资料。

我使用的是 STM32-L746RG Nucleo 开发板,使用其他可以运行 RT-Thread 并有 2个串口 的板子当然也是可以的。

img

STM32 和激光雷达的接线可以参照这里,主要也就是给电机的供电,和串口 RX TX。

硬件接线

这里总结一下接线:

激光雷达STM32备注
GNDGND
RXTX
TXRX
V5.0VCC
GNDGND
VMOTOCTLVCC也可以接一个 PWM 手动控制电机转速
VMOTOVCC电机电源

接好线上电后,应当就可以看到激光雷达开始旋转。

2. RPlidar 软件包

2.1 串口配置

在下载 RPlidar 软件包之前,需要先配置好开发板的2个串口,一个用于 msh 调试,一个用来连接激光雷达。

以 STM32 为例,下载好 RT-Thread 源码后,根据我手上的板子型号,进入rt-thread/bsp/stm32/stm32l476-st-nucleo 目录,在 board/CubeMX_Config 下可以找到 CubeMX_Config.ioc 打开。

img

这里我配置了两个串口 UART2 (MSH) 和 UART3 (激光雷达),可以根据自己的板子调整,然后 CubeMX 生成代码,把生成的项目里的 main.c 下面的 SystemClock_Config 函数,复制到 board.c 里面替换。

接下来我们需要编辑 board/Kconfig 在里面添加串口的配置,当然,如果你的 bsp 已经有相关配置就不需要了。

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
    endif

2.2 下载软件包

接下来我们就可以下载软件包了,右键打开 env 工具。

env

输入 menuconfig 进入 Hardware Drivers 打开两个串口:

img

再进入 RT-Thread Online Package 选中 RPLidar 软件包:

img

软件包选中以后,我们保存 KConfig 的配置,就可以下载软件包了,在 env 里面输入:

pkgs --update

这样我们就下好了 RPLidar 软件包,接下来就可以开始编译获取激光雷达的数据了。

如果在 Peripheral libraries and drivers 找不到 RPLidar 这个软件包的话,需要先在 env 下 pkgs --upgrade 一下更新软件包仓库。

2.3 编译上传

接线完成,串口配置完成,软件包也下载完了,最后我们就可以编译上传了。

编译的话我们可以用 Keil 也可以用 env 自带的 arm-none-gcc,如果使用 Keil 的话,先生成项目:

scons --target=mdk5 -s

然后就可以打开 Keil 项目编译了,如果是 arm-none-gcc,直接在 env 下编译就可以了。

scons

这里简单介绍一下例程代码,以激光雷达复位为例:

#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);

代码非常短我也增加了一些注释就不重复介绍了,主要流程就是:

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

2.4 获取激光雷达数据

固件编译好上传之后,就可以用串口调试助手打开 msh 了,这里我使用 putty 或者 kitty,输入 rplidar 然后 Tab 自动补全,可以看到有很多命令:

img

如果输入 rplidar_scan_and_recv_example 就可以看到一圈扫描的结果了:

扫描结果

3. 总结

思岚激光雷达可以通过串口和单片机通信,然后单片机发送控制指令,例如扫描(0xA5 0x20),激光雷达就会从串口不停地发送扫描数据,接下来要做的就是数据的解析了,而这些在 RT-Thread 的 rplidar 软件包里已经完成了,更多的 API 可以参考这里

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);

顺便一提,因为我手头只有思岚激光雷达 A1,所以 TCP 连接和一些我的设备不支持的命令还没有实现,欢迎大家有更多高级雷达的小伙伴提 PR 完善这个软件包。

4. 参考资料