本文将主要介绍以Arduino UNO R3为核心主板开发测试一款可利用手机进行蓝牙控制的遥控小车,文章将分为两部分,第一篇将详细的介绍利用Arduino UNO R3制作蓝牙小车所需硬件和软件配置以及使用Arduino IDE编写的总代码程序,第二篇将详细的介绍代码程序中各部分代码的功能和作用以及在测试过程中遇到的问题。
(1).在手机应用商店/APP Store中查找带有键盘功能的蓝牙串口软件
(2).百度网盘地址(安卓版): 蓝牙串口.apk|百度网盘https://pan.baidu.com/s/14FlalmvyKR2DaAD-TjB2sA?pwd=MJY6
参考文档:Arduino硬件介绍(一)|Arduino UNO R3开发板介绍、原理和功能-CSDN博客https://blog.csdn.net/2301_80771046/article/details/136465812?spm=1001.2014.3001.5502
HC-05/06 | Arduino UNO R3 | 说明 |
---|---|---|
VCC | 5V | 正极 |
GND | GND | 负极 |
TX | RX | 接收端,用于接收数据。 |
RX | TX | 发送端,用于发送数据。 |
1.接口是:TX -- RX,RX -- TX,注意不要接反;
2.在写入程序时需要将RX,TX引脚拔掉或者让蓝牙模块断电,否则会出现写入失败。
L298N | Arduino UNO R3 | 说明 |
---|---|---|
5V | 5V | 正极 |
12V | ------ ------ ------ | 接外12V接电源,必须与开发板主板处在同一个电源回路 |
GND | GND | 负极 |
OUT1、OUT2 | ------ ------ ------ | 接左侧电机 |
OUT3、OUT4 | ------ ------ ------ | 接右侧电机 |
ENA | D9 | 通道A使能 |
ENB | D10 | 通道B使能 |
IN1 | D2 | 信号输入口1(左侧电机) |
IN2 | D3 | 信号输入口2(左侧电机) |
IN3 | D4 | 信号输入口3(右侧电机) |
IN4 | D5 | 信号输入口4(右侧电机) |
1.L298N上的12V电源口必须要和Arduino UNO R3的电源处于同一回路下(可使用DC口电源为Arduino UNO R3供电并并联为L298N供电);
2.在测试过程中若出现电机旋转方向相反,尝试调换OUT接口即可。
以下代码是基于Arduino IDE开发环境下的代码程序
// 定义左右轮脉冲计数器和时间标记 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 = 2; int leftMotor2 = 3; int rightMotor1 = 4; int rightMotor2 = 5; bool speedLevel = 0; // 速度档位,0表示低速,1表示高速 // 定义PWM引脚 int leftPWM = 9; int rightPWM = 10; void setup() { // 初始化串口通信,波特率为9600 Serial.begin(9600); // 设置外部中断0,当引脚0电平从高到低变化时触发RightCount_CallBack函数 attachInterrupt(0, RightCount_CallBack, FALLING); // 设置外部中断1,当引脚1电平从高到低变化时触发LeftCount_CallBack函数 attachInterrupt(1, LeftCount_CallBack, FALLING); // 设置电机引脚为输出模式 pinMode(leftMotor1, OUTPUT); pinMode(leftMotor2, OUTPUT); pinMode(rightMotor1, OUTPUT); pinMode(rightMotor2, OUTPUT); // 设置PWM引脚为输出模式 pinMode(leftPWM, OUTPUT); pinMode(rightPWM, OUTPUT); } void loop() { // 调用速度检测函数 SpeedDetection(); // 如果串口有数据可读 if (Serial.available() > 0) { // 读取蓝牙模块发送到串口的数据 int cmd = Serial.read(); // 如果接收到的数据不是换行符,则进行控制 if (cmd != 10) { // 打印接收到的命令 Serial.print(cmd - 48); // 根据命令控制小车运动 motorRun(cmd - 48); } // 如果当前是高速档位 if (speedLevel) { // 设置左右轮PWM值为120,对应较低速度 analogWrite(leftPWM, 120); analogWrite(rightPWM, 120); } else { // 设置左右轮PWM值为250,对应较高速度 analogWrite(leftPWM, 250); analogWrite(rightPWM, 250); } } } // 速度计算函数 bool SpeedDetection() { // 获取当前时间(毫秒) time = millis(); // 如果计时时间达到1秒 if (abs(time - old_time) >= 1000) { // 关闭外部中断0和1 detachInterrupt(0); detachInterrupt(1); // 计算左右轮转速(转/分钟),并打印到串口 lv = (float)leftCounter * 60 / 20; rv = (float)rightCounter * 60 / 20; Serial.print("left:"); Serial.print(lv); Serial.print(" right:"); Serial.println(rv); // 重置左右轮脉冲计数器,记录当前时间,重新开启外部中断0和1 leftCounter = 0; rightCounter = 0; old_time = millis(); attachInterrupt(0, RightCount_CallBack, FALLING); attachInterrupt(1, LeftCount_CallBack, FALLING); return 1; } else { return 0; } } // 右轮编码器中断服务函数,当引脚0电平从高到低变化时触发,增加右轮脉冲计数器 void RightCount_CallBack() { rightCounter++; } // 左轮编码器中断服务函数,当引脚1电平从高到低变化时触发,增加左轮脉冲计数器 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); } }
以上为代码的所有内容,如需要每段代码的详细解释请看本系列第二篇文章
(1).打开Arduino IDE并写入代码程序
(2).选择开发板
(3).插入开发板并写入程序
(1).打开蓝牙串口APP,点击键盘,创建如下五个键位
(2).设置完成后如下图所示
完成以上操作并将代码写入到开发板中后可将开发板和各模块组装到汽车模型中,即可进行测试。
感谢以下文章为本篇文章提供文献参考及图片支持:
Arduino 上使用 HC06 蓝牙模块 – Arduino 实验室 (nxez.com)https://arduino.nxez.com/2019/02/18/arduino-uses-hc06-bluetooth-module.html?variant=zh-hkhttps://blog.csdn.net/mtobeiyf/article/details/52096966https://blog.csdn.net/qq_52785624/article/details/123865756https://zhuanlan.zhihu.com/p/138718488?utm_source=qq&utm_id=0
HC-05蓝牙模块使用教程[Arduino]_hc-05蓝牙模块的工作模式-CSDN博客https://blog.csdn.net/Ming2017123123/article/details/104222500
[Arduino]HC-06蓝牙模块使用小结_arduinohc06蓝牙模块详解-CSDN博客文章浏览阅读4.6w次,点赞30次,收藏175次。简介蓝牙,顾名思义,蓝色的牙齿,并不能用来咬人,而是一种无线数据传输标准。 HC-05和HC-06是现在使用较多的两种蓝牙模块。两者之间的区别是HC-05是主从一体机,既能向自己的’主子’打小报告,也可以接收下达的命令;而HC-06只能工作在从机模式下,那就只能乖乖接收上级的命令啦。 在很多情况下,我们都想当“霸道总裁”,让下级乖乖听话就OK了,不需要他多废话。那就用HC-06就够了。 下面是_arduinohc06蓝牙模块详解https://blog.csdn.net/mtobeiyf/article/details/52096966
L298N介绍 及PWM调速原理-CSDN博客文章浏览阅读4.2w次,点赞41次,收藏369次。L298N介绍 及PWM调速原理_l298nhttps://blog.csdn.net/qq_52785624/article/details/123865756
L298N电机驱动模块的接线使用与代码实现_l298n的ena连接pwm-CSDN博客https://blog.csdn.net/weixin_44751294/article/details/110503256
让步进电机动起来——L298N驱动步进电机 - 知乎步进电机特点:它是通过输入脉冲信号来进行控制的电机的总转动角度由输入脉冲数决定电机的转速由脉冲信号频率决定 步进电机主要用于一些有定位要求、进行精确控制的场合。特别适合要求运行平稳、低噪音、响应快、…https://zhuanlan.zhihu.com/p/138718488?utm_source=qq&utm_id=0
以上为本篇文章的所有内容,代码分段详细解释将在第二篇展示。如您对本篇文章存在疑问或提供有关改进意见,请在评论区指出,谢谢!!!
第二篇链接Arduino硬件设计(一)|利用Arduino UNO R3制作手机蓝牙遥控小车---02-CSDN博客https://blog.csdn.net/2301_80771046/article/details/136519380