Arduino智能小车——调速篇
Arduino智能小车——调速篇
Arduino智能小车系列教程时空门:
- Arduino智能小车——拼装篇 点击跳转
- Arduino智能小车——测试篇 点击跳转
- Arduino智能小车——调速篇 点击跳转
- Arduino智能小车——超声波避障 点击跳转
- Arduino智能小车——蓝牙小车 点击跳转
- Arduino智能小车——循迹篇 点击跳转
- Arduino智能小车——小车测速 点击跳转
文章目录
- Arduino智能小车——调速篇
- PWM
- 代码测试
- 修改蓝牙串口助手
- 结束语
在这一篇我们将对小车的行进速度进行调整,将驱动模块的作用发挥出来。首先大家要了解PWM这个概念。
PWM
脉宽调制(PWM)基本原理:控制方式就是对逆变电路开关器件的通断进行控制,使输出端得到一系列幅值相等的脉冲,用这些脉冲来代替正弦波或所需要的波形。也就是在输出波形的半个周期中产生多个脉冲,使各脉冲的等值电压为正弦波形,所获得的输出平滑且低次谐波少。按一定的规则对各脉冲的宽度进行调制,即可改变逆变电路输出电压的大小,也可改变输出频率。
通俗一点讲那,就是当如果我们想输出5V电压时,只需一直输出高电平即可;当我们想输出3.75V电压时,那我们就需要在一个周期内(一个高电平和一个低电平为一个周期)3.75÷5=75%时间输出高电平,25%时间输出低电平;同理,如果想输出2.5V电压时,我们需要在一个周期内50%时间输出高电平,50%时间输出低电平。
Arduino UNO开发板上只有带有“~”表示的引脚才具有PWM功能,因此我们在控制驱动时可以使用这几个引脚。 ##驱动模块接线 在前面的[教程](http://blog.csdn.net/qq_16775293/article/details/77438499)中已经讲过如果想控制驱动的输出时,需要对驱动的“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 5int 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); // 关闭外部中断0detachInterrupt(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); // 重新开放外部中断0attachInterrupt(1, LeftCount_CallBack,FALLING); // 重新开放外部中断0return 1;}elsereturn 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;elsespeedLevel=1;break;default:Serial.println("STOP"); //输出状态digitalWrite(leftMotor1, LOW);digitalWrite(leftMotor2, LOW);digitalWrite(rightMotor1, LOW);digitalWrite(rightMotor2, LOW);}
}
由于之前设计不太合理,占用了太多的PWM引脚,因此在代码里对控制小车电机的引脚做了点小改动,如下所示
int leftMotor1 = 5;
int leftMotor2 = 6;
int rightMotor1 = 7;
int rightMotor2 = 8;
现在改为
int leftMotor1 = 16;
int leftMotor2 = 17;
int rightMotor1 = 18;
int rightMotor2 = 19;
改完代码大家记得要把对应的接线也改过来哦!!
在前面的宏定义中加入换挡的定义#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;elsespeedLevel=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智能小车——蓝牙小车》教程,修改后效果如下:
结束语
大家快连接蓝牙,测试下我们的变速小车吧。大家有兴趣的话可以使用蓝牙串口助手上面的滑动条来控制小车速度,不妨下去试试吧~
欢迎各位有兴趣的朋友加入Q群1:789127261点评、交流
Arduino智能小车——调速篇相关推荐
- Arduino智能小车——循迹篇
Arduino智能小车--循迹篇 Arduino智能小车系列教程时空门: Arduino智能小车--拼装篇 点击跳转 Arduino智能小车--测试篇 点击跳转 Arduino智能小车--调速篇 点击 ...
- Arduino智能小车——拼装篇
Arduino智能小车--拼装篇 Arduino智能小车系列教程时空门: Arduino智能小车--拼装篇 点击跳转 Arduino智能小车--测试篇 点击跳转 Arduino智能小车--调速篇 点击 ...
- Arduino智能小车——测试篇
Arduino智能小车--测试篇 Arduino智能小车系列教程时空门: Arduino智能小车--拼装篇 点击跳转 Arduino智能小车--测试篇 点击跳转 Arduino智能小车--调速篇 点击 ...
- Arduino智能小车——蓝牙小车
Arduino智能小车--蓝牙小车 Arduino智能小车系列教程时空门: Arduino智能小车--拼装篇 点击跳转 Arduino智能小车--测试篇 点击跳转 Arduino智能小车--调速篇 点 ...
- Arduino智能小车——超声波避障
Arduino智能小车--超声波避障 Arduino智能小车系列教程时空门: Arduino智能小车--拼装篇 点击跳转 Arduino智能小车--测试篇 点击跳转 Arduino智能小车--调速篇 ...
- 智能小车之PWM脉冲控制小车调速
目录 一.PWM脉冲控制小车调速 二.代码实现 一.PWM脉冲控制小车调速 原理:全速前进是LeftCon1A = 0:LeftCon1B = 1:完全停止是LeftCon1A = 0:LeftCon ...
- matlab智能小车避障,Arduino智能小车系列教程4——超声波避障
Arduino智能小车系列教程4--超声波避障 Arduino智能小车系列教程 准备材料 超声波模块HC-SR04 舵机固定架 舵机安装 超声波接线 代码测试 代码详解 int getDistance ...
- 亚博 Arduino智能小车实验报告
亚博 Arduino智能小车实践报告 一. 程序安装准备 首先安装了Arduino板载USB转串口CH340驱动安装包, 若上述程序安装成功,则可以在我的电脑中找到相应的端口 本机端口号为CO ...
- 基于ros_arduino_bridge的智能小车----下位机篇
基于ros_arduino_bridge的智能小车----下位机篇 参考文章: 基于ros_arduino_bridge的智能小车----上位机篇 基于ros_arduino_bridge的智能小车- ...
最新文章
- 北京交大计算机学院王浩业,双胞胎双双“吹”进北交大
- CentOS 6.5使用yum快速搭建LAMP环境
- SDK location not found. Define location with sdk.dir in the local.properties file or with an ANDROID
- linux系统不关机添加硬盘吗,CentOS中不重启添加硬盘
- ajax和jsonp
- python列表推导式_聊一聊:python的各种推导式(列表推导式、字典推导式、集合推导式)...
- 迷宫问题pascal程序
- php从大到小排列数字,php输入几个数从大到小排序
- python安全攻防---scapy基础---计算机网络各层协议
- 表情符号mysql utf8mb4_mysql utf8mb4与emoji表情
- SpringMvc 文件上传后台处理
- activiti7对接springboot
- Excel数据分析—折线图
- 计算机屏幕显示电缆借口,电脑打不开,显示电缆线没有连接是什么意思?
- 技术QA:如何找回丢失的证书模板或将独立CA转换成企业CA?
- Ajax学习日志(五)—— 如何传递json格式请求参数
- 现在写Android,性能优化太重要了!
- 基于MATLAB APP Designer 和 Python 的音视频剪辑
- 详解sklearn——CountVectorizer
- 英语时态:一般、否定疑问句、现表将来(中文练到无停顿)
热门文章
- 华为电脑录屏,3个方法,轻松录屏
- 上海交大计算机本科保研率,上海9所211大学2018-2020保研率对比!附交大等5所大学2021保研率...
- 吴恩达机器学习 - 神经网络笔记
- 贯穿设计模式第一话--单一职责原则
- attempted relative import with no known parent package
- 【王喆-推荐系统】(task4)Graph Embedding(特征工程篇)
- CAD二次开发--如何通过代码禁止“CAD对象捕捉”捕捉到指定实体(含源代码)
- 计算机专业就业方向分析
- ts实现去除字符串空格
- IT运维人员必看!超全信息化建设之运维资料