一、先让小车动起来
1.用到的函数
定义引脚的输入/输出函数
pinMode(pin, OUT/INPUT);
通过使用pinMode()函数,可以将Arduino的引脚配置为以下三种模式:
输出(OUTPUT)模式
输入(INPUT)模式
输入上拉(INPUT_PULLUP)模式 (这个本片文章不涉及,先不讨论)
pin是要定义输入输出的引脚
例:
int leftMotor1 = 16; //定义16引脚为leftMotor1使之成为输出端
pinMode(leftMotor1, OUTPUT);
将引脚写高(HIGH)低(LOW)电平
digitalWrite(Pin, LOW/HIGH);
例:
digitalWrite(leftMotor1, LOW);//将leftMotor1端置为低电平
digitalWrite(leftMotor1, HIGH);//将leftMotor1端置为高电平
控制电机的转速即控制PWM
analogWrite(pin, value);
例:
analogWrite(10, 200);//设置10端口的PWM值为200
特别说明:
首先,Arduino Uno的5,6,9,10,3,11端口可以使用analogWrite(pin, value)来实现一个指定占空比的PWM。其中pin值的选择(5,6,9,10,3,11),value的值在0~255之间,0为占空比0%,255为占空比100%。
引入的SoftwareSerial函数库
#include <SoftwareSerial.h>//软串口函数库
SoftwareSerial softSerial(2,3);//建立SofwareSerial对象softSerial 且定义
//rx引脚为2 tx引脚为3
read()//该函数可用于从设备接收到数据中读取一个字节的数据。
begin(value);//设置波特率 一般设置为9600
available()//该函数可用于检查设备是否接收到数据。该函数将会返回等待读取的数据字节数。
使用以上函数基本就可以实现用HC05蓝牙控制小车的移动
思路:通过手机端给蓝牙发送指令–>蓝牙接收指令来控制单片机来完成基本动作
使用模块
电机驱动L298N和HC-05蓝牙模块
接线规则和基本原理参考上篇文章
基于51单片机的遥控小车
注意:如果l298n模块的ENA和ENB的引脚键帽没有去掉是短路状态,小车是全速行驶此时不需要使用analogWrite(pin, value)函数即不能实现调速功能
代码如下(示例):
#include <SoftwareSerial.h>
//定义小车各个电机的引脚
int leftMotor1 = 16;
int leftMotor2 = 17;
int rightMotor1 = 18;
int rightMotor2 = 19;
//定义L298n的ENA ENB引脚
int leftPWM = 5;
int rightPWM = 6;
//rx引脚为2 tx引脚为3
SoftwareSerial softSerial(2,3);
char cmdChar='5';//小车停止状态 可见motorRun()中的switch函数
int flag=1;//定义变量flag来控制小车的初始速度
void setup() {
// put your setup code here, to run once:
//串口初始化
Serial.begin(9600); //硬串口波特率为9600
//便于通过串口监视器查看小车的状态及后续调试
softSerial.begin(9600);//软串口波特率9600
//各个引脚的初始化均为输出状态
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:
if(softSerial.available()){ // 如果软件串口收到信息
cmdChar = softSerial.read(); // 将信息传递给cmdChar变量
Serial.print("cmdChar = "); // 硬件串口输出cmdChar变量信息,
Serial.println(cmdChar); // 通过串口监视器输出read函数读取的信息
}
motorRun();
if(flag==1)//原速
{
analogWrite(leftPWM, 200);
analogWrite(rightPWM, 200);
}
else if(flag==2)//加速
{
analogWrite(leftPWM, 255);
analogWrite(rightPWM, 255);
}
else if(flag==3)//降速
{
analogWrite(leftPWM, 80);
analogWrite(rightPWM, 80);
}
}
void motorRun()
{
switch(cmdChar){ //通过cmdChar来确定小车的状态同时串口监视器会输出对应的状态
case '1':
Serial.println("FORWARD");
FORWARD();
break;
case '2':
Serial.println("BACKWARD");
BACKWARD();
break;
case '3':
Serial.println("TURNLEFT");
TURNLEFT();
break;
case '4':
Serial.println("TURNRIGHT");
TURNRIGHT();
break;
case '5':
Serial.println("STOP");
STOP();
break;
case'7':
Serial.println("up speed");
flag=2;
break;
case'8':
Serial.println("low speed");
flag=3;
break;
case'9':
Serial.println("re speed");
flag=1;
break;
}
}
void FORWARD()
{
digitalWrite(leftMotor1, HIGH);
digitalWrite(leftMotor2, LOW);
digitalWrite(rightMotor1, HIGH);
digitalWrite(rightMotor2, LOW);
}
void BACKWARD()
{
digitalWrite(leftMotor1, LOW);
digitalWrite(leftMotor2, HIGH);
digitalWrite(rightMotor1, LOW);
digitalWrite(rightMotor2, HIGH);
}
void TURNLEFT()
{
;
digitalWrite(leftMotor1, LOW);
digitalWrite(leftMotor2, HIGH);
digitalWrite(rightMotor1, HIGH);
digitalWrite(rightMotor2, LOW);
}
void TURNRIGHT()
{
digitalWrite(leftMotor1,HIGH);
digitalWrite(leftMotor2, LOW);
digitalWrite(rightMotor1, LOW);
digitalWrite(rightMotor2, HIGH);
}
void STOP()
{
digitalWrite(leftMotor1, LOW);
digitalWrite(leftMotor2, LOW);
digitalWrite(rightMotor1, LOW);
digitalWrite(rightMotor2, LOW);
}
二、加入对应模块实现对应功能
1.HC-SR04及SG90舵机
接线规则及相应原理参考上篇
基于51单片机的超声波避障小车(HC-SR04,SG90舵机)
舵机库及函数的使用
#include <Servo.h>//引用舵机库
Servo myServo; //定义舵机对象myServo
myServo.write(value);// value值为舵机转动的角度 0-180度
HC-SR04需要使用的函数
delayMicroseconds(value);//延迟us级函数
pulseIn(Pin, HIGH/LOW);
读引脚的脉冲信号, 被读取的脉冲信号可以是 HIGH 或 LOW. 例如要检测HIGH脉冲信号, Arduino将在引脚变为高电平时开始计时, 当引脚变为低电平时停止记时,并返回脉冲持续时长(时间单位:微秒)。如果在超时时间内没有读到脉冲信号的话, 将返回0
代码如下(示例):
void avoidance()//该函数用于检测前方及左右方向距离 根据距离做出应答
{
int pos;//定义一个变量用于舵机旋转相应的角度
int dis[3];//将距离储存到数组中方便比较
myServo.write(90);//舵机初始为90度
FORWARD();
dis[1]=getDistance(); //测量前方距离
if(dis[1]<30) //比较距离是否超过30cm
{
STOP();
for (pos = 90; pos <= 150; pos += 1) 舵机旋转至150度
{
myServo.write(pos);
delay(15);
}
dis[2]=getDistance(); //测量左边
for (pos = 150; pos >= 30; pos -= 1) //舵机旋转至30度
{
myServo.write(pos);
delay(15);
if(pos==90)
dis[1]=getDistance(); //在旋转途中再次测量中间距离
}
dis[0]=getDistance(); //当旋转至30度时测量右边距离
for (pos = 30; pos <= 90; pos += 1)
{
myServo.write(pos);
delay(15);
}
if(dis[0]<dis[2]) //右边距离障碍的距离比左边近
{
//左转
TURNLEFT();
delay(200);
}
else //右边距离障碍的距离比左边远
{
//右转
TURNRIGHT();
delay(200);
}
}
}
int getDistance()//该函数用于HC-SR04测量距离
{
digitalWrite(TrigPin, LOW); // 使发出发出超声波信号接口低电平2μs
delayMicroseconds(2);
digitalWrite(TrigPin, HIGH); // 使发出发出超声波信号接口高电平10μs 至少10μs
delayMicroseconds(10);
digitalWrite(TrigPin, LOW); // 保持发出超声波信号接口低电平
int distance = pulseIn(EchoPin, HIGH); // 读出脉冲时间
distance= distance/58; // 将脉冲时间转化为距离(单位:厘米)
Serial.println(distance); //输出距离值
return distance;
}
2.完整程序编写
只需要将测距相关函数添加即可,在motorRun()的switch(cmdChar)中添加case‘6’:
case '6':
Serial.println("AVOID");
avoidance();
void avoidance()和int getDistance()函数添加至motorRun()后方即可
总结
相对于51单片机来说,arduino单片机更加简便自带有许多库可供调用,但是要明白其中的原理还是需要基于51来学习然后可通过arduino来实现。程序及原理方面如有错误或者需要修改请各位车友提出建议