Arduino智能小车系列教程4——调速篇
Arduino智能小车系列教程
- Arduino智能小车系列教程1——拼装篇
- Arduino智能小车系列教程2——测试篇
- Arduino智能小车系列教程3——调速篇
- Arduino智能小车系列教程4——超声波避障
- Arduino智能小车系列教程5——蓝牙小车
- Arduino智能小车系列教程6——循迹小车
- Arduino智能小车系列教程7——小车测速 文章目录
- Arduino智能小车——调速篇
- PWM
- 代码测试
- 修改蓝牙串口助手
- 结束语
在这一篇我们将对小车的行进速度进行调整,将驱动模块的作用发挥出来。首先大家要了解PWM这个概念。
PWM
脉宽调制(PWM)基本原理:控制方式就是对逆变电路开关器件的通断进行控制,使输出端得到一系列幅值相等的脉冲,用这些脉冲来代替正弦波或所需要的波形。也就是在输出波形的半个周期中产生多个脉冲,使各脉冲的等值电压为正弦波形,所获得的输出平滑且低次谐波少。按一定的规则对各脉冲的宽度进行调制,即可改变逆变电路输出电压的大小,也可改变输出频率。
驱动模块接线
在前面的教程中已经讲过如果想控制驱动的输出时,需要对驱动的“ENA”“ENB”进行控制,因此我们需要将图中被选中部分的两个跳线帽拔掉。并将“ENA”连接Arduino UNO开发板的“5”引脚,“ENB”连接“6”引脚。
代码测试
int leftCounter=0, rightCounter=0;
unsigned long time = 0, old_time = 0; // 时间标记
unsigned long time1 = 0; // 时间标记
float lv,rv;//左、右轮速度
#define STOP 0
#define FORWARD 1
#define BACKWARD 2
#define TURNLEFT 3
#define TURNRIGHT 4
#define CHANGESPEED 5
int leftMotor1 = 16;
int leftMotor2 = 17;
int rightMotor1 = 18;
int rightMotor2 = 19;
bool speedLevel=0;
int leftPWM = 5;
int rightPWM = 6;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
attachInterrupt(0,RightCount_CallBack, FALLING);
attachInterrupt(1,LeftCount_CallBack, FALLING);
pinMode(leftMotor1, OUTPUT);
pinMode(leftMotor2, OUTPUT);
pinMode(rightMotor1, OUTPUT);
pinMode(rightMotor2, OUTPUT);
pinMode(leftPWM, OUTPUT);
pinMode(rightPWM, OUTPUT);
}
void loop() {
// put your main code here, to run repeatedly:
SpeedDetection();
if(Serial.available()>0)
{
char cmd = Serial.read();
Serial.print(cmd);
motorRun(cmd);
if(speedLevel) //根据不通的档位输出不同速度
{
analogWrite(leftPWM, 120);
analogWrite(rightPWM, 120);
}
else
{
analogWrite(leftPWM, 250);
analogWrite(rightPWM, 250);
}
}
}
/*
* *速度计算
*/
bool SpeedDetection()
{
time = millis();//以毫秒为单位,计算当前时间
if(abs(time - old_time) >= 1000) // 如果计时时间已达1秒
{
detachInterrupt(0); // 关闭外部中断0
detachInterrupt(1); // 关闭外部中断1
//把每一秒钟编码器码盘计得的脉冲数,换算为当前转速值
//转速单位是每分钟多少转,即r/min。这个编码器码盘为20个空洞。
Serial.print("left:");
lv =(float)leftCounter*60/20;//小车车轮电机转速
rv =(float)rightCounter*60/20;//小车车轮电机转速
Serial.print("left:");
Serial.print(lv);//向上位计算机上传左车轮电机当前转速的高、低字节
Serial.print(" right:");
Serial.println(rv);//向上位计算机上传左车轮电机当前转速的高、低字节
//恢复到编码器测速的初始状态
leftCounter = 0; //把脉冲计数值清零,以便计算下一秒的脉冲计数
rightCounter = 0;
old_time= millis(); // 记录每秒测速时的时间节点
attachInterrupt(0, RightCount_CallBack,FALLING); // 重新开放外部中断0
attachInterrupt(1, LeftCount_CallBack,FALLING); // 重新开放外部中断0
return 1;
}
else
return 0;
}
/*
* *右轮编码器中断服务函数
*/
void RightCount_CallBack()
{
rightCounter++;
}
/*
* *左轮编码器中断服务函数
*/
void LeftCount_CallBack()
{
leftCounter++;
}
/*
* *小车运动控制函数
*/
void motorRun(int cmd)
{
switch(cmd){
case FORWARD:
Serial.println("FORWARD"); //输出状态
digitalWrite(leftMotor1, HIGH);
digitalWrite(leftMotor2, LOW);
digitalWrite(rightMotor1, HIGH);
digitalWrite(rightMotor2, LOW);
break;
case BACKWARD:
Serial.println("BACKWARD"); //输出状态
digitalWrite(leftMotor1, LOW);
digitalWrite(leftMotor2, HIGH);
digitalWrite(rightMotor1, LOW);
digitalWrite(rightMotor2, HIGH);
break;
case TURNLEFT:
Serial.println("TURN LEFT"); //输出状态
digitalWrite(leftMotor1, HIGH);
digitalWrite(leftMotor2, LOW);
digitalWrite(rightMotor1, LOW);
digitalWrite(rightMotor2, HIGH);
break;
case TURNRIGHT:
Serial.println("TURN RIGHT"); //输出状态
digitalWrite(leftMotor1, LOW);
digitalWrite(leftMotor2, HIGH);
digitalWrite(rightMotor1, HIGH);
digitalWrite(rightMotor2, LOW);
break;
case CHANGESPEED:
Serial.println("CHANGE SPEED"); //输出状态
if(speedLevel) //接收到换挡命令的时候切换档位
speedLevel=0;
else
speedLevel=1;
break;
default:
Serial.println("STOP"); //输出状态
digitalWrite(leftMotor1, LOW);
digitalWrite(leftMotor2, LOW);
digitalWrite(rightMotor1, LOW);
digitalWrite(rightMotor2, LOW);
}
}
在前面的宏定义中加入换挡的定义#define CHANGESPEED 5
#define STOP 0
#define FORWARD 1
#define BACKWARD 2
#define TURNLEFT 3
#define TURNRIGHT 4
#define CHANGESPEED 5
Arduion的PWM引脚需要和正常引脚一样,在void setup()
函数中初始化为输出模式
pinMode(leftPWM, OUTPUT);
pinMode(rightPWM, OUTPUT);
在小车的控制状态函数void motorRun(int cmd)
中添加多一个选择项,用来切换速度。
case CHANGESPEED:
Serial.println("CHANGE SPEED"); //输出状态
if(speedLevel) //接收到换挡命令的时候切换档位
speedLevel=0;
else
speedLevel=1;
break;
在主函数void loop()
中添加PWM输出的函数,analogWrite(pin, value)
函数中“pin”代表使用的引脚,“value”代表输出PWM值的大小,范围是0~255。
if(speedLevel) //根据不通的档位输出不同速度
{
analogWrite(leftPWM, 120);
analogWrite(rightPWM, 120);
}
else
{
analogWrite(leftPWM, 250);
analogWrite(rightPWM, 250);
}
修改蓝牙串口助手
在串口助手中,将“按键1”修改为“换挡”键,蓝牙串口助手的使用方法和使用详细的修改过程可以参考前面的《Arduino智能小车——蓝牙小车》教程,修改后效果如下:
结束语
大家快连接蓝牙,测试下我们的变速小车吧。大家有兴趣的话可以使用蓝牙串口助手上面的滑动条来控制小车速度,不妨下去试试吧~