先上图片:
一般来说,这样子的激光雷达都是与电脑或者树莓派等等配合使用的,但是暂时没有时间去捣鼓slam算法相关的东西,那有没有方法把它应用在其他简单的项目中呢?
。。。。我看到了角落的arduino。。。。
查了一下资料,确实可以。
于是完成了一个使用arduino获取激光雷达信息,并且在st7789 ips显示屏上绘制雷达信息的项目。
首先控制激光雷达:
硬件方面:
bom:Arduino Mega2560开发板、RPLIDAR A1激光雷达、连接线若干。
接线:
这里我是重新做了一套连接线用于连接arduino:
Arduino Mega 引脚 | RPLidar A1 引脚 |
---|---|
TX1 | RX |
5V | VCC_5V |
GND | GND |
GND | GND_MOTO |
Pin 3 | CTRL_MOTO |
5V | 5V_MOTO |
按照上面的表格连接完成就好啦
在官方给出的数据中,电机的供电电压可以上升至9V,也就是说如果对电机的供电不满意,觉得动力不足 的话,可以尝试给他提供稍微高一些的电压。
编程方面:
需要安装依赖库:RPLidar
RoboPeak开发的RPlidar的Arduino库,但是在Arduino IDE的库管理中没有,所以需要自己安装。
链接:
https://github.com/robopeak/rplidar_arduino
解压后,把「RPLidarDriver」文件夹,放在Arduino IDE 的安装目录下的「libraries」文件夹中,就可以使用RPLiadar库了。
至此,就可以试着控制雷达啦
// 加载RPLidar库
#include <RPLidar.h>
// 创建一个名为lidar的雷达驱动实例
RPLidar lidar;
//定义控制电机的PWM引脚:
#define RPLIDAR_MOTOR 3
//绑定指定串口:
lidar.begin(Serial1);
//设置控制电机的PWM引脚为输出模式
pinMode(RPLIDAR_MOTOR, OUTPUT);
//使用以下判断可以返回lidar是否正常工作的值
IS_OK(lidar.waitPoint()
//返回当前距离值,以毫米(mm)为单位
float distance = lidar.getCurrentPoint().distance;
//返回当前角度度数
float angle = lidar.getCurrentPoint().angle;
//返回该点是否属于一个新的扫描点
bool startBit = lidar.getCurrentPoint().startBit;
//返回当前测量的质量
byte quality = lidar.getCurrentPoint().quality;
要完成第一张图片的效果,还需要连接显示屏(ips240*240 st7789)
显示屏的接线:
Arduino Mega 引脚 | st7789 引脚 |
---|---|
8 | TFT_DC |
9 | TFT_RST |
10 | TFT_CS |
20 | TFT_MOSI |
21 | TFT_SCLK |
显示屏方面,需要两个相关库:
Adafruit-GFX-Library
在Arduino "库管理器"中搜索“Adafruit GFX Library”,选择最新版本,点击 安装 进行安装。此库的GitHub地址为:https://github.com/adafruit/Adafruit-GFX-Library
Arduino-ST7789-Library
此库暂时无法通过库管理器安装,可以到GitHub下载包,放到Arduino的库文件目录,重新打开Arduino就会自动加载了。
此库的GitHub地址是:https://github.com/ananevilya/Arduino-ST7789-Library
最终的程序如下:
#include <RPLidar.h>
#include <Adafruit_GFX.h>
#include <Arduino_ST7789.h>
#include <SPI.h>
#include <TFT_eSPI.h>
TFT_eSPI tft1 = TFT_eSPI();
#define TFT_DC 8
#define TFT_RST 9
#define TFT_CS 10
#define TFT_MOSI 20
#define TFT_SCLK 21
#define RPLIDAR_MOTOR 3
RPLidar lidar;
Arduino_ST7789 tft = Arduino_ST7789(TFT_DC, TFT_RST, TFT_MOSI, TFT_SCLK, TFT_CS);
float pi = 3.1415926;
float data[360];
void setup() {
Serial.begin(115200);
lidar.begin(Serial1);
tft.init(240, 240);
pinMode(RPLIDAR_MOTOR, OUTPUT);
Serial.println("Initialized");
analogWrite(RPLIDAR_MOTOR, 255);
lidar.startScan();
}
void loop() {
tft.fillScreen(BLACK);
tft.setTextWrap(true);
tft.setTextColor(BLUE);
tft.setTextSize(2);
tft.setCursor(20, 30);
tft.print("by: Albert.H");
tft.setTextSize(3);
tft.setCursor(30, 60);
tft.print("Scaning...");
Serial.println("start scan");
long int time_start = millis();
int time_delay = 10000;
while (millis() < time_start + time_delay) {
Scan();
}
Serial.println("OK");
//for (int i = 0; i < 360; i++) {
//Serial.println(data[i]);
//}
ScreanShow();
Serial.println("END");
delay(1000000);
}
void Scan() {
if (IS_OK(lidar.waitPoint())) {
float distance = lidar.getCurrentPoint().distance; //distance value in mm unit
int angle = lidar.getCurrentPoint().angle; //anglue value in degree
if (distance != 0.0) {
data[angle] = distance;
}
}
}
void ScreanShow() {
tft.fillScreen(BLACK);
for (int i = 0; i < 360; i++) {
float angle = i;
int x = (data[i] * cos(angle / 180.0 * pi)) / 100 + 120;
int y = (data[i] * sin(angle / 180.0 * pi)) / 100 + 120;
tft.drawLine(120, 120, x, y, RED);
}
tft.drawCircle(120, 120, 100, GREEN);
tft.drawCircle(120, 120, 70, GREEN);
tft.drawCircle(120, 120, 40, GREEN);
tft.drawCircle(120, 120, 10, GREEN);
tft.setTextSize(1);
tft.setTextColor(GREEN);
tft.setTextWrap(true);
tft.setCursor(120, 120 + 100);
tft.print("10m");
tft.setCursor(120, 120 + 70);
tft.print("7m");
tft.setCursor(120, 120 + 40);
tft.print("4m");
tft.setCursor(120, 120 + 10);
tft.print("1m");
byte quality = lidar.getCurrentPoint().quality;
tft.setTextWrap(true);
tft.setTextColor(YELLOW);
tft.setTextSize(3);
tft.setCursor(10, 10);
tft.print(quality);
tft.setCursor(10, 10);
tft.print(quality);
}
效果:
参考文章:
RPLIDAR的参考
IPS显示屏的参考