Arduino nano的制作智能小车
1.引脚配置
首先是板子的图片
Nano | 技术参数 |
---|---|
控制器 | ATmega328P |
Flash | 32KB |
Sram | 2KB |
EEPROM | 1KB |
Sram | 2KB |
模拟输入引脚 | 8个 |
数字IO | 22个 |
PWM | 6个 |
时钟频率 | 16MHz |
ATmega328P 总共32个引脚,有三组功能接口,分别为PortB、PortC、PortD,后面会详细提到。单片机引脚数量有限,都是多个功能共同复用同一个引脚,通过软件配置来实现特定的功能。
Nano板上引脚(1)(2)为串口输出输入引脚,板上通过CH340芯片转为了USB信号,方便主机下载程序、通信用。 这两个脚尽量不做其它用途。(在烧录程序时,Nano板上引脚(1)(2)TX和RX不能接线)
(4)(29)为信号地、电源地共用引脚。
(30)为外部电源输入引脚,推荐输入范围7~12V,电池供电的情况下使用。
(27)引脚为双向电源引脚,外部有5V电源时,此脚可做输入,省掉了电池。如果有电池,而外部没有5V电源时,此引脚可以给外部提供5V电源。
(17)3V3电源输出,此电源由CH340 USB芯片转换而来,给外部3.3V系统供电。
(18)AREF,模拟参考电压输入,一般不用连,此脚空置的情况下,328P微控制默认使用IC内部的1.1V做AD(模拟转数字)电路的参考电压。
复用接口引脚
下面详细介绍一下(5)到(16)、(19)到(26)这几个引脚。分别对应D[2:13]、A[0:7],D代表digital,数字接口;A代表analog,模拟接口。
紫色名称的代表数字功能,绿色名称的代表模拟功能,深灰色部分代表对应的微控制328P的芯片引脚,注意事项如下:
A6、A7只能做模拟功能。
A4、A5除模拟功能外,可以做IO用,也可以做I2C总线用
D10到D13,可以做SPI总线用
D3、D5、D6、D9、D10、D11 可以做PWM输出用。
注意:每个引脚只能用作一个用途,比如用了SPI总线后,D10、D11就不可以再做PWM用。
注意:上传程序是TX,RX不能接线。
2. 使用Arduino NANO一步步完善智能小车
1. 第一步实现小车正反向运动
首先画出电路图,我使用的是立创IDE作图(可以使用用户贡献)
这是根据已经接线的小车进行作图
程序
void setup() {
//初始化各IO,模式为OUTPUT 输出模式
pinMode(2,OUTPUT);
pinMode(4,OUTPUT);
pinMode(7,OUTPUT);
pinMode(8,OUTPUT);
//默认电机停止转动,全部设为低电平
digitalWrite(2,0);
digitalWrite(4,LOW);
digitalWrite(7,LOW);
digitalWrite(8,LOW);
}
void loop() {
qianjin(); //前进
delay(500); //延时500ms
daotui(); //后退
delay(500); //延时500ms
}
void qianjin(){
digitalWrite(2,1); //给高电平
digitalWrite(4,0); //给低电平
digitalWrite(7,1); //给高电平
digitalWrite(8,0); //给低电平
}
void daotui(){
digitalWrite(2,0); //给低电平
digitalWrite(4,1); //给高电平
digitalWrite(7,0); //给低电平
digitalWrite(8,1); //给高电平
}
我使用的是直流减速电机,共四个电机,使用一个L298控制,Arduino nano输出高低电平引脚为DA2,DA4,DA7,DA8用杜邦线与L298N的IN1,IN2,IN3,IN4相连,为L298N提供12V作为输入电压,5V作为输出为Arduino nano供电(注意使能)(Arduino与L298N共地),L298N的OUT1,OUT2,OUT3,OUT4作为输出与直流减速电机相连。将上图程序烧录到Arduino nano中,小车即可实现简单的正反向运动。
2. HC-05蓝牙串口通信模块的学习
首先是蓝牙模块的调试工作。
1.USB转TTL模块与HC-05蓝牙模块的接线:
GND接GND,VCC接VCC,RX接TX,TX接RX
这个时候就要将转换模块连接到电脑上,然后利用串口调试助手进行蓝牙模块的调试。
2.HC-05蓝牙串口通讯模块具有两种工作模式:命令响应工作模式和自动连接工作模式。在自动连接工作模式下模块又可分为主(Master)、从(Slave)和回环(Loopback)三种工作角色。
当模块处于自动连接工作模式时,将自动根据事先设定的方式连接的数据传输;
当模块处于命令响应工作模式时能执行AT命令,用户可向模块发送各种AT 指令,为模块设定控制参数或发布控制命令。
怎么进入命令响应工作模式?
进入命令响应工作模式有两种方法:
模块上电,未配对情况下就是AT模式,波特率为模块本身的波特率,默认:9600,发送一次AT指令时需要置高一次PIO11;
PIO11 置高电平后,再给模块上电,此时模块进入AT 模式,波特率固定为:38400,可以直接发送AT指令。
什么叫做置高一次PIO11?
在蓝牙模块中有一个小按键,按一下就置高一次PIO11。也就是说,第一种方法需要每发送一次AT指令按一次;而第二种方式是长按的过程中上电,之后就无需再管了,直接发送AT命令即可。
需要注意一下,两种进入命令响应工作模式的方式使用的波特率是不一样的,建议使用第二种方式。
怎么区分进了命令响应工作模式呢?
在蓝牙模块上有灯,当灯快闪的时候,就是自动连接工作模式;当灯慢闪的时候,就是命令响应工作模式。
AT命令
进入到命令响应工作模式之后,就可以使用串口调试助手进行蓝牙调试了。
首先有一点,AT指令不区分大小写,均以回车、换行结尾。下面介绍常用的AT指令:
常用AT指令
指令名 响应 含义
AT OK 测试指令
AT+RESET OK 模块复位
AT+VERSION? +VERSION:OK 获得软件版本号
AT+ORGL OK 恢复默认状态
AT+ADDR? +ADDR: OK 获得蓝牙模块地址
AT+NAME= OK 设置设备名称
AT+NAME? +NAME: OK 获得设备名称
AT+PSWD= OK 设置模块密码
AT+PSWD? +PSWD: OK 获得模块密码
AT+UART=,, OK 设置串口参数
AT+UART? +UART:,, OK 获得串口参数
对于AT指令,有几点注意:
AT+NAME?:获得设备名称,这个AT指令有很大可能性是没有返回的,但是其他的指令都是没有问题的,直接设置设备名称就行了;
AT+UART?:获得串口参数,串口的参数一共有三个,波特率、停止位、检验位。其取值如下:
串口参数
参数名称 取值
波特率
2400、4800、9600、19200、38400、5760、
115200、230400、460800、921600、1382400
停止位
0:1位
1:2位
校验位 0:NONE 1:Odd 2:Even
重要重要重要:如果HC05搜索不到,记得设置主从模式,蓝牙是主机模式时,无法被搜索到和配对(从机模式:AT+ROLE=0\r\n)
3.OLED的学习
针脚说明
VCC 接3.3v电源
GND 接地(GND)
SCL(SCK) 时钟线
SDA 数据线
Arduino与OLED接线## 标题
3.实现蓝牙控制小车前后左右并进行调速功能
首先是利用蓝牙模块实现手机与Arduino nano之间的通信
补充 map()函数的用法
x = map( t , fromMIN ,fromMAX , toMIN, toMAX);
t是需要映射的参数,
fromMIN ,fromMAX是按照比例转换前的范围值。
toMIN, toMAX是按照比例转换后的范围值。
举个例子,假设t是5, (fromMIN ,fromMAX )是(0,10),
( toMIN, toMAX)是(0,100)。那么最终,X的值为50。
1.字符串操作函数
Arduino 将 String 转化为 int
函数:toInt()
实例:
String my_str = "123";
int my_int = my_str.toInt();
寻找字符串第几个
str.charAT(n)
描述
获取字符串的第n个字符
参数
n :是一个索引,作为下标
截取字符串
描述
用来截取字符串中间的某一位置。另外是决定那里结束
用法:
string1.substring(from); //返回 from 之后的
string1.substring(from,to); //返回 from 和 to 之间的
参数:
string1:原本的字符串
from:要截取的字符串从第几个字开始。
to:要截取后面的第几个字
实战
#include "String.h"
String a_1,a_2,S;
void setup()
{
Serial.begin(9600);//打开串口,设置波特率9600
a_1 = "hello";
}
void loop()
{
S = a_1.charAt(3); //取对象里面的方法charAt
a_2=a_1.substring(0,3);
Serial.print(a_2);
Serial.println();//输出换行符
delay(200);
}
2.串口接收字符串程序
String comdata = "";
void setup()
{
Serial.begin(9600);
}
void loop()
{
while (Serial.available() > 0)
{
comdata += char(Serial.read());
delay(2);
}
if (comdata.length() > 0)
{
Serial.println(comdata);
comdata = "";
}
}
3.OLED显示
程序
#include <SPI.h> // 加载SPI库
#include <Wire.h> // 加载Wire库
#include <Adafruit_GFX.h> // 加载Adafruit_GFX库
#include <Adafruit_SSD1306.h> // 加载Adafruit_SSD1306库
// 定义 OLED屏幕的分辨率
Adafruit_SSD1306 display = Adafruit_SSD1306(128, 64, &Wire);
void setup() {
Serial.begin(9600); // 设置串口波特率
Serial.println("OLED FeatherWing test"); // 串口输出
display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // 设置OLED的I2C地址
display.clearDisplay(); // 清空屏幕
display.setTextSize(1); // 设置字体大小
display.setTextColor(SSD1306_WHITE); // 设置字体颜色
display.setCursor(0,0); // 设置开始显示文字的坐标
display.println("Hello World!"); // 输出的字符
display.println(" by Lingshunlab.com");
display.display(); // 使更改的显示生效
}
void loop() {
}
4.调速
程序
void setup() {
Serial.begin(115200);
//初始化各IO,模式为OUTPUT 输出模式
pinMode(2,OUTPUT);
pinMode(3,OUTPUT);
pinMode(4,OUTPUT);
pinMode(5,OUTPUT);
//默认电机停止转动,全部设为低电平
digitalWrite(2,LOW);
digitalWrite(3,LOW);
digitalWrite(4,LOW);
digitalWrite(5,LOW);
analogWrite(9,255);//左轮速运行(0~255)
analogWrite(10,255);//右轮速运行(0~255)
}
void loop() {
if (Serial.available() > 0)
{
Serial.println(char(Serial.read()))
if(char(Serial.read())=='a'){a1();}
if(char(Serial.read())=='b'){a2();}
if(char(Serial.read())=='c'){a3();}
if(char(Serial.read())=='d'){a4();}
if(char(Serial.read())=='e'){a5();}
if(char(Serial.read())=='f'){a6();}
if(char(Serial.read())=='g'){a7();}
if(char(Serial.read())=='i'){a8();}
delay(2);
}
注意字符与变量的区别。如Serial.println(“a”);是串口打印a这个字符,而Serial.println(a);则是串口打印a这个变量。
穿插一个牛批的知识——软串口
除HardwareSerial外,Arduino还提供了SoftwareSerial类库,它可以将你的其他数字引脚通过程序模拟成串口通信引脚。
通常我们将Arduino UNO上自带的串口称为硬件串口,而使用SoftwareSerial类库模拟成的串口,称为软件模拟串口(简称软串口)。
在Arduino UNO上,提供了0(RX)、1(TX)一组硬件串口,可与外围串口设备通信,如果要连接更多的串口设备,可以使用软串口。
软串口是由程序模拟实现的,使用方法类似硬件串口,但有一定局限性:在Arduino UNO MEGA上部分引脚不能被作为软串口接收引脚,且软串口接收引脚波特率建议不要超过57600。
#include <SoftwareSerial.h>
//实例化软串口
SoftwareSerial mySerial(2, 3); // RX, TX
void setup()
{
Serial.begin(115200);
while (!Serial) {
}
Serial.println("Goodnight moon!");
mySerial.begin(9600);
mySerial.println("Hello, world?");
}
void loop()
{
if (mySerial.available())
Serial.write(mySerial.read());
if (Serial.available())
mySerial.write(Serial.read());
}
当需要连接多个串口设备时,可以建立多个软串口,但限于软串口的实现原理,Arduino UNO只能同时监听一个软串口,当存在多个软串口设备时,你需要使用listen() 函数指定需要监听的设备。如程序中存在portOne、portTwo两个软串口对象时,你欲监听portOne,便需要使用portOne.listen() 语句,要切换监听port2,便使用portTwo.listen() 语句。
示例程序如下:
/*
Arduino UNO软串口通信
通过listen()切换监听软串口
*/
#include <SoftwareSerial.h>
SoftwareSerial portOne(10, 11);
SoftwareSerial portTwo(8, 9);
void setup() {
Serial.begin(9600);
while (!Serial) {
}
portOne.begin(9600);
portTwo.begin(9600);
}
void loop() {
//监听1号软串口
portOne.listen();
Serial.println("Data from port one:");
while (portOne.available() > 0) {
char inByte = portOne.read();
Serial.write(inByte);
}
Serial.println();
//监听2号软串口
portTwo.listen();
Serial.println("Data from port two:");
while (portTwo.available() > 0) {
char inByte = portTwo.read();
Serial.write(inByte);
}
Serial.println();
}
总程序
#include <SPI.h> // 加载SPI库
#include <Wire.h> // 加载Wire库
#include <Adafruit_GFX.h> // 加载Adafruit_GFX库
#include <Adafruit_SSD1306.h> // 加载Adafruit_SSD1306库
#include "String.h"
// 定义 OLED屏幕的分辨率
Adafruit_SSD1306 display = Adafruit_SSD1306(128, 64, &Wire);
String comdata = "";
int a=100;
int a_1=100;
int b=0;
int c=0;
int x=0;
//String a_3;
//String a_4;
void setup() {
Serial.begin(9600); // 设置串口波特率
Serial.println("OLED FeatherWing test"); // 串口输出
display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // 设置OLED的I2C地址
display.setTextSize(1); // 设置字体大小
display.setTextColor(SSD1306_WHITE); // 设置字体颜色
//初始化各IO,模式为OUTPUT 输出模式
pinMode(2,OUTPUT);
pinMode(4,OUTPUT);
pinMode(7,OUTPUT);
pinMode(8,OUTPUT);
//默认电机停止转动,全部设为低电平
digitalWrite(2,0);
digitalWrite(4,LOW);
digitalWrite(7,LOW);
digitalWrite(8,LOW);
}
void loop() {
display.clearDisplay(); // 清空屏幕
chukou();
xianshi();
analogWrite(3,a);//左轮速运行
analogWrite(5,a_1);//右轮速运行
display.display(); // 使更改的显示生效
}
void xianshi(){
display.setCursor(20,0); // 设置开始显示文字的坐标
display.println("xiaoche");
display.setCursor(0,10); // 设置开始显示文字的坐标
display.println("moshi:");
display.setCursor(50,10); // 设置开始显示文字的坐标
if(x==0){display.println("zhidong");}
if(x==1){display.println("qianjin");}
if(x==2){display.println("huotui");}
if(x==3){display.println("zuozhuan");}
if(x==4){display.println("youzhuan");}
display.setCursor(0,20); // 设置开始显示文字的坐标
display.println("zuosudu:");
display.setCursor(50,20); // 设置开始显示文字的坐标
display.println(String(a));
display.setCursor(0,30); // 设置开始显示文字的坐标
display.println("yousudu:");
display.setCursor(50,30); // 设置开始显示文字的坐标
display.println(String(a_1));
display.setCursor(0,40); // 设置开始显示文字的坐标
display.println("kaiguan:");
display.setCursor(50,40); // 设置开始显示文字的坐标
if(c==1) {display.println("ON");}
if(c==0) {display.println("OFF");}
}
void chukou(){
while (Serial.available() > 0)
{
comdata += char(Serial.read());
delay(2);
}
if (comdata.length() > 0)
{
Serial.println(comdata);
if(comdata=="ON"){c=1;}
if(comdata=="OFF"){c=0;}
if(c==1){
if(comdata=="a"){a=a+10;if(a>255){a=255;}}
if(comdata=="b"){a=a-10;if(a<0){a=0;}}
if(comdata=="c"){a_1=a_1+10;if(a_1>255){a_1=255;}}
if(comdata=="d"){a_1=a_1-10;if(a_1<0){a_1=0;}}
if(comdata=="e"){zhidong();}
if(comdata=="f"){qianjin();}
if(comdata=="g"){huotui();}
if(comdata=="h"){zuozhuan();}
if(comdata=="r"){youzhuan();}
}
comdata = "";
Serial.println(x);
}
}
void qianjin(){
digitalWrite(2,1); //给高电平
digitalWrite(4,0); //给高电平
digitalWrite(7,1); //给高电平
digitalWrite(8,0);
Serial.println("前进"); // 串口输出
x=1;} //给高电平
void huotui(){
digitalWrite(2,0); //给高电平
digitalWrite(4,1); //给高电平
digitalWrite(7,0); //给高电平
digitalWrite(8,1);
Serial.println("后退"); // 串口输出
x=2;} //给高电平
void zuozhuan(){
digitalWrite(2,0); //给高电平
digitalWrite(4,0); //给高电平
digitalWrite(7,1); //给高电平
digitalWrite(8,0);
Serial.println("左转"); // 串口输出
x=3;} //给高电平
void youzhuan(){
digitalWrite(2,1); //给高电平
digitalWrite(4,0); //给高电平
digitalWrite(7,0); //给高电平
digitalWrite(8,0);
Serial.println("右转"); // 串口输出
x=4;} //给高电平
void zhidong(){
digitalWrite(2,1); //给高电平
digitalWrite(4,1); //给高电平
digitalWrite(7,1); //给高电平
digitalWrite(8,1);
Serial.println("制动"); // 串口输出
x=0;} //给高电平
对应的电路图
手机蓝牙串口控制界面
![在这里插入图片描述]
4.加入灰度传感器
模块编程原理
灰度传感器共引出三个引脚,分别是电源正Vcc、电源地GND、信号端OUT,实际使用时可以直接将传感器连接到 Arduino 控制器的模拟接口,例如模拟口 A0,给 Arduino 通电后,传感器白色高亮 LED 亮起,将传感器扣放在灰度不同的纸张上,通过 Arduino 控制器自带的 AD 转换进行数据的读取,然后通过串口打印出测量的模拟量即可。
发光二极管与1K电阻串联,发光二极管作为光源,照射在检测物体上,1K电阻起限流作用。光敏电阻与10K电阻串联,光敏电阻具有光越强阻值越小的特性。当发光二极管照在白色物体上时,白色物体反射所有光,亮度强,光敏电阻阻值小,分压小,out点输出的电压值高;当发光二极管照在黑色物体上时,黑色物体吸收所有光,亮度弱,光敏电阻阻值大,分压大,out点输出的电压值低。
在小车上固定两个灰度传感器,可以实现简单的寻迹功能,但是如直角转弯就无法做到,如果在增加一个到多个灰度传感器则可以实现该功能。
在实现寻迹功能的道路是曲折的。首先,使用的是12路的模拟灰度传感器,但是这个传感器以接电源就发烫,于是就将这个传感器的芯片拆除重装其他芯片,然后传感器就失去正常工作的能力。其次,由于动手能力差在小车各个模块的布局接线显得杂乱无章,在最开始由于短路问题烧毁一个双L298N的板子(导致电池也短路了)。之后将各个模块接好发现小车蓝牙接受不到信息,后来发现是没有接降压模块的原因,arduino与电机都接在L298N上导致故障,然后找到数块降压模块,由于接反输入输出导致烧毁一块,其中还有两块原本就是坏的(降压模块在调试的时候一定要多拧几圈,我用的那块拧了十多圈才开始降压的),最后加入两个灰度传感器,到此蓝牙寻迹小车差不多搭建完毕。
程序
String comdata = "";
int a=100;
int a_1=100;
int b=0;
int c=0;
int y_1,y_2,y_3;
int z=0;
int z_1=0;
void loop() {
chuankou();
xianshi();
if(z==1){xunji();}
analogWrite(3,a);//左轮速运行
analogWrite(5,a_1);//右轮速运行
}
void chuankou(){
while (Serial.available() > 0)
{
comdata += char(Serial.read());
delay(2);
}
if (comdata.length() > 0)
{
Serial.println(comdata);
if(comdata=="ON"){c=1;}
if(comdata=="OFF"){c=0;}
if(c==1){
if(comdata=="lin"){z=1;Serial.println("循迹");}
if(comdata=="xu"){z=0;Serial.println("控制");}
if(z==0){
if(comdata=="a"){a=a+5;if(a>255){a=255;}}
if(comdata=="b"){a=a-5;if(a<0){a=0;}}
if(comdata=="c"){a_1=a_1+5;if(a_1>255){a_1=255;}}
if(comdata=="d"){a_1=a_1-5;if(a_1<0){a_1=0;}}
if(comdata=="e"){zhidong();}
if(comdata=="f"){qianjin();}
if(comdata=="g"){houtui();}
if(comdata=="h"){zuozhuan();}
if(comdata=="r"){youzhuan();}
}}
comdata = "";
// Serial.println(x);
}
}
void xunji(){
z_1=1;
y_1=digitalRead(9);//传感器接收到红外信号输出高电平,传感器没有接收到红外信号输出低电平
y_2=digitalRead(10);
Serial.println(y_1);
Serial.println(y_2);
if(y_1==0 and y_2==0){qianjin();Serial.println("前进");}
if(y_1==0 and y_2==1){youzhuan();Serial.println("左转");}
if(y_1==1 and y_2==0){zuozhuan();Serial.println("右转");}
if(y_1==1 and y_2==1){zhidong();Serial.println("制动");}
}
5.加入超声波传感器
超声波传感器我使用的是HC-SR04,T是发送,E是接收
在使用该模块时因为没有将其固定在小车上,采用手持,所以导致传感器跳动导致测距误差较大,在这个过程中只使用了
程序`
#include <SPI.h> // 加载SPI库
#include <Wire.h> // 加载Wire库
#include <Adafruit_GFX.h> // 加载Adafruit_GFX库3
#include <Adafruit_SSD1306.h> // 加载Adafruit_SSD1306库
#include "String.h"
// 定义 OLED屏幕的分辨率
#include <DFRobot_URM10.h>//超声波测距
Adafruit_SSD1306 display = Adafruit_SSD1306(128, 64, &Wire);
DFRobot_URM10 urm10;
String comdata = "";//接收到的字符串
int a=100; //使能1初始脉冲
int a_1=100; //使能2初始脉冲
int b=0;
int c=0;
int x=0;
int y_1,y_2,y_3; //寻迹变量
int z=0;
int z_1=0;
int ceju_2=0;
int ceju_1=0;
int ceju_0=0;
void setup() {
Serial.begin(9600); // 设置串口波特率
Serial.println("OLED FeatherWing test"); // 串口输出
display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // 设置OLED的I2C地址
display.setTextSize(1); // 设置字体大小
display.setTextColor(SSD1306_WHITE); // 设置字体颜色
//初始化各IO,模式为OUTPUT 输出模式
pinMode(2,OUTPUT);
pinMode(4,OUTPUT);
pinMode(7,OUTPUT);
pinMode(8,OUTPUT);
//初始化各IO,模式为INPUT 输入模式
pinMode(9,INPUT);
pinMode(10,INPUT);
pinMode(11,INPUT);
//默认电机停止转动,全部设为低电平
digitalWrite(2,0);
digitalWrite(4,LOW);
digitalWrite(7,LOW);
digitalWrite(8,LOW);
}
void loop() {
ceju_0=(urm10.getDistanceCM(11, 12)); //超声波测距
display.clearDisplay(); // 清空屏幕
Serial.println(ceju_0); //串口打印距离
chuankou(); //调用串口程序
xianshi(); //调用显示程序
if(z==1){xunji();Serial.println("11111");} //当z==1时,执行寻迹程序,并且串口打印11111
if(ceju_1==1){ceju();Serial.println("ceju");}
analogWrite(3,a);//左轮速运行
analogWrite(5,a_1);//右轮速运行
display.display(); // 使更改的显示生效
}
void xianshi(){
display.setCursor(20,0); // 设置开始显示文字的坐标
display.println("xiaoche");
display.setCursor(0,10); // 设置开始显示文字的坐标
display.println("moshi:");
display.setCursor(50,10);
if(x==0) {display.println("zhidong");} //当x不同值时,OLED打印不同状态
if(x==1) {display.println("qianjin");}
if(x==2) {display.println("houtui");}
if(x==3) {display.println("zuozhuan");}
if(x==4) {display.println("youzhuan");}
if(x==5) {display.println("dazuozhuan");}
if(x==6) {display.println("dayouzhuan");}
display.setCursor(0,20);
display.println("zuo:");
display.setCursor(30,20);
display.println(String(a));
display.setCursor(64,20);
display.println("you:");
display.setCursor(94,20);
display.println(String(a_1));
display.setCursor(0,30);
display.println("kaiguan:");
display.setCursor(50,30);
if(c==1) {display.println("ON");}
if(c==0) {display.println("OFF");}
display.setCursor(0,40); // 设置开始显示文字的坐标
display.println("xunji");
display.setCursor(50,40); // 设置开始显示文字的坐标
if(z_1==1) {display.println("yes");}
if(z_1==0) {display.println("no");}
display.setCursor(0,50); // 设置开始显示文字的坐标
display.println("ceju");
display.setCursor(50,50); // 设置开始显示文字的坐标
if(ceju_2==1){display.println("wuxiao");}
if(ceju_2==0){display.println(ceju_0);}
}
void ceju(){
if(ceju_0<=1100){ceju_2=0; //当超声波测距小于等于1100时,则ceju_2=0,并执行以下程序
if(ceju_0<=10) {houtui();Serial.println("后退");}
if(ceju_0>=15) {qianjin();Serial.println("前进");}
if(10<ceju_0 and ceju_0<15) {zhidong();Serial.println("制动");}
}
if(ceju_0>1100){ceju_2=1;}
}
void chuankou(){
while (Serial.available() > 0) // 串口收到字符数大于零
{
comdata += char(Serial.read()); //每次读一个char字符,并相加
delay(2);
}
if (comdata.length() > 0) //当字符串长度大于零时
{
Serial.println(comdata); //打印接收到的字符串
if(comdata=="ON"){c=1;}
if(comdata=="OFF"){c=0;}
if(c==1){
if(comdata=="lin"){z=1;Serial.println("循迹");}
if(comdata=="xu"){z=0;Serial.println("控制");}
if(z==0){
if(comdata=="a"){a=a+5;if(a>255){a=255;}} //接收到a时,则a+5,当a>255时a=255
if(comdata=="b"){a=a-5;if(a<0){a=0;}}
if(comdata=="c"){a_1=a_1+5;if(a_1>255){a_1=255;}}
if(comdata=="d"){a_1=a_1-5;if(a_1<0){a_1=0;}}
if(comdata=="e"){zhidong();} //接收到e时,则执行zhidong();
if(comdata=="f"){qianjin();}
if(comdata=="g"){houtui();}
if(comdata=="h"){zuozhuan();}
if(comdata=="r"){youzhuan();}
if(comdata=="ce"){ceju_1=1;}
}}
comdata = ""; //清空字符串
}
}
void xunji(){
z_1=1;
y_1=digitalRead(9);//传感器接收到红外信号输出高电平,传感器没有接收到红外信号输出低电平
y_2=digitalRead(10);
Serial.println(y_1);
Serial.println(y_2);
if(y_1==0 and y_2==0){qianjin();Serial.println("前进");}
if(y_1==0 and y_2==1){youzhuan();Serial.println("左转");}
if(y_1==1 and y_2==0){zuozhuan();Serial.println("右转");}
if(y_1==1 and y_2==1){zhidong();Serial.println("制动");}
}
void qianjin(){
digitalWrite(2,0); //给低电平
digitalWrite(4,1); //给高电平
digitalWrite(7,0);
digitalWrite(8,1);
Serial.println("前进"); // 串口输出
x=1;}
void houtui(){
digitalWrite(2,1); //给高电平
digitalWrite(4,0); //给低电平
digitalWrite(7,1);
digitalWrite(8,0);
Serial.println("后退");
x=2;}
void zuozhuan(){
digitalWrite(2,0);
digitalWrite(4,0); //给低电平
digitalWrite(7,1); //给高电平
digitalWrite(8,0);
Serial.println("左转");
x=3;}
void dazuozhuan(){
digitalWrite(2,0); //给低电平
digitalWrite(4,1); //给高电平
digitalWrite(7,1);
digitalWrite(8,0);
Serial.println("左转");
x=5;}
void youzhuan(){
digitalWrite(2,1); //给高电平
digitalWrite(4,0); //给低电平
digitalWrite(7,0);
digitalWrite(8,0);
Serial.println("右转");
x=4;}
void dayouzhuan(){
digitalWrite(2,1); //给高电平
digitalWrite(4,0); //给低电平
digitalWrite(7,0);
digitalWrite(8,1);
Serial.println("右转");
x=5;}
void zhidong(){
digitalWrite(2,1); //给高电平
digitalWrite(4,1);
digitalWrite(7,1);
digitalWrite(8,1);
Serial.println("制动");
x=0;}
该项程序可实现用手机蓝牙串口调试基于arduino的小车前后左右,加减速,寻迹,超声波测距避障。
注意:串口接收数据可以保留,但是程序中的字符串comdata会清空。
由于小车硬件搭建问题,电路图与程序中引脚有一定差异。
至此基于arduino的智能小车就告一段落了。