arduino小车制作心得
时间:2022-09-20 10:30:00
在制作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将5拉到板上V(高电平) 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),简单的理解是将不可视电压变为可视化,读取引脚的模拟值mega0-5v在uno由于开发板的精度为10,0-5V电压分为0-1023,这样,光敏电阻就可以读取电阻值,从而知道当前光的强度。
analogWrite(PIN,Val),这个函数需要用于制汽车的阶段使用PWM调速设置,mega就在0-255,uno就在0-1023之间,这就是呼吸灯的原理(借助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蓝牙模块是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); dgitalWrite(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
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(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
// 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 = ""; //置空数组,进入下一次循环
}
}

