重要参考:
课程链接:https://www.bilibili.com/video/BV1Ci4y1L7ZZ
讲义链接:Introduction · Autolabor-ROS机器人入门课程《ROS理论与实践》零基础教程
8.2.3 arduino 基本语法演示
通信操作
1.通信实现01
需求: 通过串口,由 arduino 向计算机发送数据
实现:
/*
* 需求:通过串口,由 arduino 向计算机发送数据
* 实现:
* 1.setup中设置波特率
* 2.setup 或 loop 中使用 Serial.print 或 Serial.println() 发送数据
*
*
*
*/
void setup() {
Serial.begin(57600);
Serial.println("setup");
}
void loop() {
delay(3000);
Serial.print("loop");
Serial.print(" ");
Serial.println("hello");
}
2.通信实现02
需求: 通过串口,由计算机向Arduino发送数据
实现:
/*
* 需求:通过串口,由计算机向 arduino 发送数据
* 实现:
* 1.setup中设置波特率
* 2.loop 中接收发送的数据,并打印
*
*
*
*/
char num;
void setup() {
Serial.begin(57600);
}
void loop() {
if(Serial.available() > 0){
num = Serial.read();
Serial.print("I accept:");
Serial.println(num);
}
}
8.2.4 arduino 基本语法演示02
1.数字IO操作
需求:控制LED灯开关,在一个循环周期内前两秒使LED灯处于点亮状态,后两秒关闭LED灯
实现:
/*
* 控制LED灯开关,在一个循环周期内前两秒使LED灯处于点亮状态,后两秒关闭LED灯
* 1.setup 中设置引脚为输出模式
* 2.loop 中向引脚输出高电压,休眠 2000 毫秒后,再输出低电压,再休眠 2000 毫秒
*
*/
int led = 13;
void setup() {
Serial.begin(57600);
pinMode(led,OUTPUT);
}
void loop() {
digitalWrite(led,HIGH);//输出高电压
delay(2000);
digitalWrite(led,LOW);//输出低电压
delay(2000);
}
2.模拟IO操作
需求:控制LED灯亮度
原理:在1中LED灯只有关闭或开启两种状态,是无法控制 LED 灯亮度,如果要实现此功能,那么需要借助于 PWM(Pulse width modulation 脉冲宽度调制)技术,通过设置占空比为LED间歇性供电,PWM 的取值范围 [0,255]。
实现:
/*
* 需求:控制LED灯亮度
* 实现:
* 1.setup 中设置 led 灯的引脚为输出模式
* 2.设置不同的 PWM 并输出
*
*/
int led = 13;
int l1 = 255;
int l2 = 50;
int l3 = 0;
void setup() {
pinMode(led,OUTPUT);
}
void loop() {
analogWrite(led,l1);
delay(2000);
analogWrite(led,l2);
delay(2000);
analogWrite(led,l3);
delay(2000);
}
运行结果:在一个周期内LED灯亮度递减直至熄灭
8.2.5 arduino 基本语法演示03
需求:调用 millis() 函数获取程序当前已经执行的时间,调用delay()函数实现休眠
实现:
/*
* 需求:调用 millis() 函数获取程序当前已经执行的时间,调用delay()函数实现休眠
*
* 1.setup 中设置波特率
* 2.loop 中使用delay休眠,使用millis获取程序执行时间并输出
*
*/
unsigned long past_time;
void setup() {
Serial.begin(57600);
}
void loop() {
delay(2000);//休眠 2 秒
past_time = millis();
Serial.println(past_time);
}
通过串口监视器查看输出结果。
8.3 机器人平台设计之电机驱动
对于构建轮式机器人而言,电机驱动是一重要实现环节。
场景:在机器人架构中,如果要实现机器人移动,其中一种实现策略是:控制系统会先发布预期的车辆速度信息,然后驱动系统订阅到该信息,不断调整电机转速直至达到预期速度,调速过程中还需要时时获取实际速度并反馈给控制系统,控制系统会计算实际位移并生成里程计信息。
在上述流程中,控制系统(ROS端)其实就是典型的发布和订阅实现,而具体到驱动系统(Arduino)层面,需要解决的问题有如下几点:
-
一个周期伊始,Arduino 如何订阅控制系统发布的速度相关信息?
-
一个周期结束,Arduino 如何发布实际速度相关信息到控制系统?
-
一个周期之中,Arduino 如何驱动电机(正传、反转)?
-
一个周期之中,Arduino 如何实现电机测速?
-
一个周期之中,Arduino 如何实现电机调速?
在整个闭环实现中,前两个问题涉及到驱动系统与控制系统的通信,其中控制系统会将串口通信的相关实现封装,暂时不需要关注,而Arduino端数据的接收与发送都可以通过之前介绍的 Serial 相关API实现,本节主要介绍后面三个问题的解决方式也即电机基本控制、电机测速以及电机调速实现,主要内容如下:
-
硬件:主要介绍电机类型与结构以及电机驱动板;
-
电机转向控制与电机转速的控制;
-
电机测速实现;
-
电机调速实现。
8.3.1 硬件_电机与电机驱动板
如果要通过Arduino实现电机相关操作(比如:转向控制、转速控制、测速等),那么必须先要具备两点前提知识:
- 需要简单了解电机类型、机械结构以及各项参数,这些是和机器人的负载、极限速度、测速结果等休戚相关的;
- 还需要选配合适的电机驱动板,因为Arduino的输出电流不足以直接驱动电机,需要通过电机驱动板放大电机控制信号。
当前我们的机器人平台使用的电机为直流减速电机,电机驱动板为基于L298P实现的电路板。接下来就分别介绍这两个模块:
1.直流减速电机
如图所示,相当一部分ROS智能车中使用的直流减速电机与之类似,主要由三部分构成:
- 减速箱
- 电机主体
- 编码器
电机主体通过输入轴与减速箱相连接,通过减速箱的减速效果,最终外端的输出轴会按照比例(取决于减速箱减速比)降低电机输入轴的转速,当然速度降低之后,将提升电机的力矩。
尾部是AB相霍尔编码器,通过AB编码器输出的波形图,可以判断电机的转向以及计算电机转速
另外,即便电机外观相同,具体参数也可能存在差异,参数需要商家提供,需要了解的参数如下:
- 额定电压
- 额定电流
- 额定功率
- 额定扭矩
- 减速比
- 减速前转速
- 减速后转速
- 编码器精度
主要参数:
额定扭矩:额定扭矩和机器人质量以及有效负荷相关,二者正比例相关,额定扭矩越大,可支持的机器人质量以及有效负荷越高;
减速比:电机输入轴与输出轴的减速比例,比如: 减速比为90,意味着电机主体旋转90圈,输出轴旋转1圈。
减速后转速:与减速比相关,是电机减速箱输出轴的转速,单位是 rpm(转/分),减速后转速与减速前转速存在转换关系: 减速后转速 = 减速前转速 / 减速比。另外,可以根据官方给定的额定功率下的减速后转速结合车轮参数来确定小车最大速度。
编码器精度:是指编码器旋转一圈单相(当前编码器有AB两相)输出的脉冲数;
注意:电机输入轴旋转一圈的同时,编码器旋转一圈,如果输出轴旋转一圈,那么编码器的旋转圈数和减速比一致(比如减速比是90,那么输出轴旋转一圈,编码器旋转90圈)。
编码器输出的脉冲数计算公式则是:输出轴旋转一圈产生的脉冲数 = 减速比 * 编码器旋转一圈发送的脉冲数(比如:减速比为90,编码器旋转一圈输出11个脉冲,那么输出轴旋转一圈总共产生 11 * 90 也即990个脉冲)。
电机编码器
M1: 电机电源+(和M2对调可以正反转 )
GND: 编码器电源-
C2: 信号线
C1: 信号线
VCC:编码器电源+
M2: 电机电源-(和M1对调可以正反转)
2.电机驱动板
电机驱动板可选型号较多,比如:TB6612、L298N、L298P....但是这些电机驱动板与电机相连时,需要使用杜邦线,接线会显得凌乱,本节会采用一款基于L298P优化的电机驱动板,该驱动板可以使用端子线直接连接电机,接线更规整、美观。
端子线母头对应的引脚(自上而下)
母头1: 4、地线、21、20、5V输入、 5
母头2:7、地线、18、19、5V输入、 6
PS:电机驱动板使用时,需要打开USB接口处的电源开关。
3.准备工作
组装底盘:集成电池、Arduino、电机驱动板与电机
先安装Arduino、安装电机(接端子线)与万向轮,将电机驱动板与Arduino集成;
然后将电池的正负极分别接入电机驱动模块的12V与GND(注意:正负极不可接反,12V接红线,GND接黑线);
最后将电机通过端子线与驱动板相连。
8.3.2 电机基本控制实现
在ROS智能车中,控制车辆的前进、后退以及速度调节,那么就涉及到电机的转向与转速控制,本节主要就是介绍相关知识点。
需求:控制单个电机转动,先控制电机以某个速率正向转动N秒,再让电机停止N秒,再控制电机以某个速率逆向转动N秒,最后让电机停止N秒,如此循环。
实现流程:
- 编写Arduino程序,setup中设置引脚模式,loop中控制电机运动;
- 上传并查看运行结果。
1.编码
前提知识点:
- 左电机的M1与M2对应的是引脚4(DIRA)和引脚5(PWMA),引脚4控制转向,引脚5输出PWM。右电机的M1与M2对应的是引脚6(PWMB)和引脚7(DIRB),引脚7控制转向,引脚6输出PWM。
- 可以通过PWM控制电机转速。
代码:
/*
* 电机转动控制
* 1.定义接线中电机对应的引脚
* 2.setup 中设置引脚为输出模式
* 3.loop中控制电机转动
*
*/
int DIRA = 4;
int PWMA = 5;
void setup() {
//两个引脚都设置为 OUTPUT
pinMode(DIRA,OUTPUT);
pinMode(PWMA,OUTPUT);
}
void loop() {
//先正向转动3秒
digitalWrite(DIRA,HIGH);
analogWrite(PWMA,100);
delay(3000);
//停止3秒
digitalWrite(DIRA,HIGH);
analogWrite(PWMA,0);
delay(3000);
//再反向转动3秒
digitalWrite(DIRA,LOW);
analogWrite(PWMA,100);
delay(3000);
//停止3秒
digitalWrite(DIRA,LOW);
analogWrite(PWMA,0);
delay(3000);
/*
* 注意:
* 1.可以通过将DIRA设置为HIGH或LOW来控制电机转向,但是哪个标志位正转或反转需要根据需求判断,转向是相对的。
* 2.PWM的取值为 [0,255],该值可自己设置。
*
*/
}
2.运行
程序上传到Arduino上,如无异常,电机开始转动,转动结果与需求描述类似。