在制作arduino小车之前,需要了解一些基础知识,虽然大部分的东西都在调库,以及调试,首先要明白arduino的代码基本上是由两部分组成的loop(循环部分)和set up(启动阶段),在我的学习的阶段我了解了digital系列的函数还有analog系列的函数以及Servo库的东西等一系列东西
1.pinMode(端口,模式)
在最初使用pinMode可以把接入的端口进行不同模式的设定,大概有三类:INPUT(输入模式),OUTPUT(输出模式),INPUT_PULLUP(输入上拉模式)
输入上拉模式,选择一个相应的接口,进行输入上拉,mega板子上默认的开始都为高电压,上拉到5V,可以使用digitalRead()读取高低电位,和按钮相结合可以控制相应的亮灭
void setup() {
// put your setup code here, to run once:
pinMode(2,INPUT_PULLUP);
pinMode(13,OUTPUT);
}
void loop() {
// put your main code here, to run repeatedly:
int val = digitalRead(2); //读取引脚2的状态,在mega板子上会上拉到5V(高电平)
if(val == HIGH)
{
digitalWrite(13,LOW);
}
else //按下开关,和GND相连,变为低电平
{
digitalWrite(13,HIGH);
}
}
2.digital系列
在使用pinMode将相应的引脚设置OUTPUT后需要digitalWrite()进行使其输出高电平或者低电平的输出。
digitalRead(),可以检测该引脚的的模式,返回相应的数字(高电平是1[HIGH],低电平是0[lLOW])
3.analog系列(digitalWrite()和digitalRead()函数已经完成了初始化,不需要在set up 进行初始化)
analogRead(PIN),这个接口只能选用模拟数字接口(eg. A0),简单理解就是将不可视的电压变为可视化,读取引脚的模拟值,在mega开发板上,可以将0-5v的电压分为0-255的形式,在uno开发板上因为板子的精度是10,所以可以将0-5V的电压分为0-1023的形式,这样就可以光敏电阻读取阻值从而知道目前光线的强度了。
analogWrite(PIN,Val),在制作小车的阶段需要使用这个函数进行PWM进行一个调速设置,mega就在0-255,uno就在0-1023之间,便可这个也就是呼吸灯的原理了(借助for循环进行操作)。
4.Serial系列
digital.avaliable()读出串口监视器的字节个数(一般是在蓝牙模块进行读取命令)
Serial.Read()读取串口的一个字节.
Serial.begin(),设置波特率,保证发出端和接收端的频率相同,保证信息的准确传送
Serial.println()在串口输出信息并换行,Serial.print()在串口输出信息
pulseIn用于读取引脚脉冲的时间长度,脉冲可以是HIGH或LOW。如果是HIGH,函数将先等引脚变为高电平,然后开始计时,一直到变为低电平为止。返回脉冲持续的时间长短, 单位为ms。如果超时还没有读到的话, 将返回0。
知识大概就是这些,还有一些小点.......
组装方面:我选用的是 arduino Mega 2560开发板,L298N电机,红外循迹模块,舵机,超声波模块,以及hc-05蓝牙模块,主要就这几个模块。
我选用的是四驱小车,因为是四驱所以使用了两个L298N的电机,但只有一个电源所以我选择将两个电机并联在一起,电源电压大概最低都要9V(不要问为什么,因为我有血的教训),别的就是接线了。
最后的效果图如下:
第一部分:小车的前进,后退,左右转弯
将小车四个轮子的直流电机驱动和L298N电机相连接,并且清楚哪个接口对应哪个轮子,借助PWM进行调速。
#define FORWARD 0
#define BACKWARD 1
#define LEFT 2
#define RIGHT 3
#define STOP 4
//前面的两个轮子
int rightMotor1 = 36;
int rightMotor2 = 34;
int leftMotor1 = 30;
int leftMotor2 = 32;
//后面两个轮子
int rightMotor3 = 22;
int rightMotor4 = 24;
int leftMotor3 = 28;
int leftMotor4 = 26;
//前面两个的PWM
int leftPWM1 = 10;
int rightPWM2 =11 ;
//后面两个轮子的PWM
int leftPWM3 = 8;
int rightPWM4 = 9;
注意:当拔掉PWM跳帽的时候,如果不进行使用,小车将无法运动(解决方法:1.把跳帽插上2.使用PWM进行调速)
void Control_direction(int dir,int val1,int val2,int val3,int val4) //val4右后轮 val3左后轮 val2右前轮 val1 左前轮
{
analogWrite(leftPWM1,val1); //设置PWM,设置速度
analogWrite(rightPWM2,val2);
analogWrite(leftPWM3,val3); //设置PWM,设置速度
analogWrite(rightPWM4,val4);
switch(dir)
{
case FORWARD:
Serial.println("FORWARD");
digitalWrite(leftMotor1,HIGH);
digitalWrite(leftMotor2,LOW);
digitalWrite(rightMotor1,HIGH);
digitalWrite(rightMotor2,LOW);
digitalWrite(leftMotor3,LOW);
digitalWrite(leftMotor4,HIGH);
digitalWrite(rightMotor3,LOW);
digitalWrite(rightMotor4,HIGH);
break;
case BACKWARD:
Serial.println("BACKWARD");
digitalWrite(leftMotor1,LOW);
digitalWrite(leftMotor2,HIGH);
digitalWrite(rightMotor1,LOW);
digitalWrite(rightMotor2,HIGH);
digitalWrite(leftMotor3,HIGH);
digitalWrite(leftMotor4,LOW);
digitalWrite(rightMotor3,HIGH);
digitalWrite(rightMotor4,LOW);
break;
case LEFT:
Serial.println("LEFT");
digitalWrite(leftMotor1,HIGH);
digitalWrite(leftMotor2,LOW);
digitalWrite(rightMotor1,HIGH);
digitalWrite(rightMotor2,LOW);
digitalWrite(leftMotor3,LOW);
digitalWrite(leftMotor4,HIGH);
digitalWrite(rightMotor3,LOW);
digitalWrite(rightMotor4,HIGH);
break;
case RIGHT:
Serial.println("RIGHT");
digitalWrite(leftMotor1,HIGH);
digitalWrite(leftMotor2,LOW);
digitalWrite(rightMotor1,HIGH);
digitalWrite(rightMotor2,LOW);
digitalWrite(leftMotor3,LOW);
digitalWrite(leftMotor4,HIGH);
digitalWrite(rightMotor3,LOW);
digitalWrite(rightMotor4,HIGH);
break;
}
}
虽然代码过于长,但实际大部分都是复制粘贴,只需要改一下(HIGHorLOW)。当你需要轮子前转的时候,需要将该轮子的两极一个置高,一个置低,形成电位差(电压)【后转则和前转刚好相反】,但在实际中,你需要调试看哪一极该置高,哪一极该置低。
当你需要轮子静止,则只需要将两端同时置高或者置低。
第二部分:(超声波避障)
原理(使用 Arduino 采用数字引脚给 SR04 的 Trig 引脚至少 10 μ s 的高电平信号,触发 SR04 模块测距功能,触发后,模块会自动发送 8 个 40KHz 的超声波脉冲,并自动检测是否有信号返回。这步会由模块内部自动完成,如有信号返回, Echo 引脚会输出高电平,高电平持续的时间就是超声波从发射到返回的时间。此时,我们能使用 pulseIn() 函数获取到测距的结果,并计算出距被测物的实际距离。因为声速在空气中的速度大约为340m/s,用时间/2再乘以速度,大约就是距离,然后将距离实时的返回给板子。
pulseln()检测高低电平的脉冲宽度。
int getDistance()
{
digitalWrite(outputPin, LOW); // 使发出发出超声波信号接口低电平2μs
delayMicroseconds(2);
digitalWrite(outputPin, HIGH); // 使发出发出超声波信号接口高电平10μs,这里是至少10μs
delayMicroseconds(10);
digitalWrite(outputPin, LOW); // 保持发出超声波信号接口低电平
int distance = pulseIn(inputPin, HIGH); // 读出脉冲时间
distance= distance/58; // 将脉冲时间转化为距离(单位:厘米)
Serial.println(distance); //输出距离值
if (distance >=50)
{
//如果距离小于50厘米返回数据
return 50;
}//如果距离小于50厘米小灯熄灭
else
return distance;
}
除此之外还需要舵机,通过舵机可以将SR04进行一个全方位的转动,从而可以测得各个方向的距离,从而让小车完成最优选择路径。
舵机的使用需要调用库函数#include <Servo.h>,而且需要初始化引脚myServo.attach(引脚)。还需要定义舵机变量
void avoidance()
{
int pos;
int dis[3];//距离
myServo.write(95); //将舵机正对前面
motorRun(FORWARD,60,60,60,60);
dis[1]=getDistance(); //中间
if(dis[1]<30)
{
motorRun(STOP,0,0,0,0);
for (pos = 95; pos <= 150; pos += 1)
{
myServo.write(pos);
delay(20);
}
dis[2]=getDistance(); //左边
for (pos = 150; pos >= 30; pos -= 1)
{
myServo.write(pos);
delay(20);
if(pos==95)
dis[1]=getDistance(); //中间
}
dis[0]=getDistance(); //右边
for (pos = 30; pos <= 95; pos += 1)
{
myServo.write(pos);
delay(20);
}
if(dis[0]<dis[2]) //右边距离障碍的距离比左边近
{
//左转
motorRun(TURNLEFT,0,60,0,60);
delay(1000);
}
else if(dis[0]>dis[2]) //右边距离障碍的距离比左边远
{
//右转
motorRun(TURNRIGHT,60,0,60,0);
delay(1000);
}
}
}
3.循迹部分(借助红外模块检测黑线,若检测到黑线返回1----低电平,否则返回0---高电平)
将每一个信号都存在数组里面
我做的小车只是用了三个红外模块
int date[3];
date[0]=digitalRead(left);
date[1]=digitalRead(mid);
date[2]=digitalRead(right);
if(date[0]==0&&date[1]==1&&date[2]==0)
go(60,60,60,60);
if(date[0]==1&&date[1]==1)
{
left_(0,60,0,60);
delay(50);
}
if(date[1]==0&&date[2]==1)
{
right_(60,0,60,0);
delay(50);
}
if(date[0]==1&&date[1]==1&&date[2]==1)
{
stop_(0,0,0,0);
delay(2000);
}
4.蓝牙部分,我使用的是HC-05蓝牙模块,首先需要明白蓝牙和小车之间借助串口通信的方式进行信息交互,手机和蓝牙模块相连接,就可以控制小车了。
Arduino 5V - VCC
Arduino GND - GND
Arduino Pin10 - TXD
Arduino Pin11 - RXD
第一步:蓝牙模块的AT模式:长按蓝牙模块上的小黑按钮,然后将usb接口插入电脑,此时蓝牙模块会两秒亮灭的形式(进入了AT模式)
#include <SoftwareSerial.h>
// Pin11为RX,接HC05的TXD
// Pin12为TX,接HC05的RXD
SoftwareSerial BT(11,12);
char val;
void setup() {
Serial.begin(38400);
Serial.println("BT is ready!");
// HC-05默认,38400
BT.begin(38400);
}
void loop() {
if (Serial.available()) {
val = Serial.read();
BT.print(val);
}
if (BT.available()) {
val = BT.read();
Serial.print(val);
}
}
借助这个代码则可以在arduino串口监视器进行AT指令的操作,当然你也可以借助Xcom或者sscom进行串口调试。记得将蓝牙模块设为从机
将蓝牙和小车连接好之后,代码的书写很简单(读取串口监视器的数字或者字母,然后将字母的对应功能设计出来就行)
if(Serial.available()>0)
{
char cmd = Serial.read();//读取蓝牙模块发送到串口的数据
switch(cmd)
{
/*相应的功能设计*/
}
}
大概思路模板就是这样(具体控制代码想要的可以私聊哦!!!)
在这里拓展一下,当你需要读入一个字符串的时候,可以定义一个字符串变量,然后将串口Serial.read()存到字符串中,然后每次读取后,将字符串数组置空就行了
string pp = "";
void loop()
{
while(Serial.available()>0)
{
pp += char(Serial.read());
delay(2);
}
target = pp.toInt(); //将(char)数字转化为(int/float/double)数字
if(pp.length>0)
{
pp = ""; //置空数组,进入下一次循环
}
}