@cd88882
2022-03-02T08:58:05.000000Z
字数 10582
阅读 4152
Arduino小车学习与研究
陈都
产品名称:
亚博智能 Arduino入门学习套件(arduino UNO R3开发套件)
具体的安装流程
安装驱动及开发环境
驱动安装
arduino IDE
LabView 下载地址
安装小车基本部件
配件安装[1]
-电机
-电池盒
-万向轮
-拓展面包板
-舵机云台(先单独安装不与底板连接)
-arduino uno开发板安装
小车硬件调试
电机模块调试:
-说明:电机正反转时只能接一个信号,比始IN1 IN2 只能接一个,不能同时接两个。
-要电机转动时要先接入EN1/EN2 使能信号。
IN1接到VCC(正5V 电源)(右电机反转信号线,高电平有效)
IN2接到VCC(正5V 电源)(右电机正转信号线,高电平有效)
IN3接到VCC(正5V 电源)(左电机正转信号线,高电平有效)
IN4接到VCC(正5V 电源)(左电机反转信号线,高电平有效)
光电传感器调试(左右)
-在实际使用中,由W1(W2)电位器,L4(L5)信号指示灯左(右)光电 传 感器共同组成避障模块,在调试中当L4信号灯没有接收到红外信号时 不亮(输出高电平1),当接到红外反馈信号后,指示灯亮起(输出低电 平0)。
-顺时针调节电位器是增加W1左光电信号检测的距离,逆时针调节电 位 器时减少检测距离(W2相同)。
光电传感器调试(底盘下方)
-调试时不要对着强光,建议在室内调试,环境光线对检测距离有比较大的影响
-在实际使用中,由W3(W4)电位器,L2(L3)信号指示灯左光电传感器组成黑白线识别模块。L2(L3)信号灯没有接接收到红外信号时会不亮(输出高电平1),当接到到红外反馈信号后,指示灯亮起(输出低电平0)。
-顺时针调节电位器是增加W3左光电信号强度调节检测距离,逆时针调节电位器时减少检测距离(w4相同)。
Arduino语言是建立在C/C++基础上的,其实也就是基础的C语言,Arduino语言只不过把AVR单片机(微控制器)相关的一些参数设置都函数化。
与C语言一致的语法就不多加赘述了,主要介绍一些C语言库中未定义的常量。
HIGH | LOW : 表示数字IO口的电平,HIGH 表示高电平(1),LOW 表示低电平(0)。 INPUT | OUTPUT
表示数字IO口的方向,INPUT 表示输入(高阻态),OUTPUT 表示输出(AVR能提供5V电压 40mA电流)。
Arduino库函数简介
1.基本函数:
- void setup():初始化变量,管脚模式,调用库函数等 。
- void loop():连续执行函数内的语句 。
2.功能函数:
(1).数字I/O
- pinMode(pin, mode):数字IO口输入输出模式定义函数,pin表示为0~13, mode表示为INPUT或OUTPUT。
- digitalWrite(pin, value):数字IO口输出电平定义函数,pin表示为0~13,value表示为HIGH或LOW。比如定义HIGH可以驱动LED。
- int digitalRead(pin):数字IO口读输入电平函数,pin表示为0~13,value表示为HIGH或LOW。比如可以读数字传感器。
(2).模拟 I/O
- int analogRead(pin):模拟IO口读函数,pin表示为0~5(Arduino Diecimila为0~5,Arduino nano为0~7)。比如可以读模拟传感器(10位AD,0~5V表示为0~1023)。
- analogWrite(pin, value)–PWM:数字IO口PWM输出函数,Arduino数字IO口标注了PWM的IO口可使用该函数,pin表示3, 5, 6, 9, 10,11,value表示为0~255。比如可用于电机PWM调速或音乐播放。
analogWrite函数常用与调整左右轮的pwm比率在板上都以符号标示。如:`6
(3).扩展 I/O
- shiftOut(dataPin, clockPin, bitOrder, value):SPI外部IO扩展函数,通常使用带SPI接口的74HC595做8个IO扩展,dataPin为数据口,clockPin为时钟口,bitOrder为数据传输方向(MSBFIRST高位在前,LSBFIRST低位在前),value表示所要传送的数据(0~255),另外还需要一个IO口做74HC595的使能控制。
- unsigned long pulseIn(pin, value):脉冲长度记录函数,返回时间参数(us),pin表示为0~13,value为HIGH或LOW。比如value为HIGH,那么当pin输入为高电平时,开始计时,当pin输入为低电平时,停止计时,然后返回该时间。
(4).时间函数
- unsigned long millis():返回时间函数(单位ms),该函数是指,当程序运行就开始计时并返回记录的参数,该参数溢出大概需要50天时间。
- delay(ms):延时函数(单位ms)。
- delayMicroseconds(us):延时函数(单位us)。
(5).数学库函数
- min(x, y):求最小值 。
- max(x, y):求最大值 。
- abs(x):计算绝对值 。
- constrain(x, a, b):约束函数,下限a,上限b,x必须在ab之间才能返回。
- map(value, fromLow, fromHigh, toLow, * toHigh):约束函数,value必须在fromLow与toLow之间和fromHigh与toHigh之间才能返回。
- pow(base, exponent):开方函数,base的exponent次方。
- sq(x):平方。
- sqrt(x):开根号 。
- 三角函数:sin(rad) ,cos(rad) ,tan(rad) 。
(6).随机数函数
- randomSeed(seed):随机数端口定义函数,seed表示读模拟口analogRead(pin)函数 。
- long random(max):随机数函数,返回数据大于等于0,小于max。
- long random(min,max):随机数函数,返回数据大于等于min,小于max。
(7).外部中断函数
- attachInterrupt(interrupt, , mode):外部中断只能用到数字IO口2和3,interrupt表示中断口初始0或1,表示一个功能函数,mode:LOW低电平中断,CHANGE有变化就中断,RISING上升沿中断,FALLING下降沿中断。
- detachInterrupt(interrupt):中断开关,interrupt=1 开,interrupt=0 关。
(8).中断使能函数
- interrupts():使能中断。
- noInterrupts():禁止中断。
(9).串口收发函数
- Serial.begin(speed): 串口定义波特率函数,speed表示波特率,如9600,19200等。
- int Serial.available():判断缓冲器状态。
- int Serial.read():读串口并返回收到参数。
- Serial.flush():清空缓冲器。
- Serial.print(data):串口输出数据。
- Serial.println(data):串口输出数据并带回车符。
#include <LiquidCrystal.h>
LiquidCrystal lcd(13,12,7,6,5,4,3);
int Echo = A1; // Echo回声脚(P2.0)
int Trig =A0; // Trig 触发脚(P2.1)
int Front_Distance = 0;
int Left_Distance = 0;
int Right_Distance = 0;
int Left_motor_back=8; //左电机后退(IN1)
int Left_motor_go=9; //左电机前进(IN2)
int Right_motor_go=10; // 右电机前进(IN3)
int Right_motor_back=11; // 右电机后退(IN4)
int key=A2;//定义按键 A2 接口
int beep=A3;//定义蜂鸣器 A3 接口
int servopin=2;//设置舵机驱动脚到数字口2
int myangle;//定义角度变量
int pulsewidth;//定义脉宽变量
int val;
void setup()
{
Serial.begin(9600); // 初始化串口
//初始化电机驱动IO为输出方式
pinMode(Left_motor_go,OUTPUT); // PIN 8 (PWM)
pinMode(Left_motor_back,OUTPUT); // PIN 9 (PWM)
pinMode(Right_motor_go,OUTPUT);// PIN 10 (PWM)
pinMode(Right_motor_back,OUTPUT);// PIN 11 (PWM)
pinMode(key,INPUT);//定义按键接口为输入接口
pinMode(beep,OUTPUT);
//初始化超声波引脚
pinMode(Echo, INPUT); // 定义超声波输入脚
pinMode(Trig, OUTPUT); // 定义超声波输出脚
lcd.begin(16,2); //初始化1602液晶工作 模式
//定义1602液晶显示范围为2行16列字符
pinMode(servopin,OUTPUT);//设定舵机接口为输出接口
}
void run() // 前进
{
digitalWrite(Right_motor_go,HIGH); // 右电机前进
digitalWrite(Right_motor_back,LOW);
analogWrite(Right_motor_go,92);//PWM比例0~255调速,左右轮差异略增减
analogWrite(Right_motor_back,0);
digitalWrite(Left_motor_go,HIGH); // 左电机前进
digitalWrite(Left_motor_back,LOW);
analogWrite(Left_motor_go,120);//PWM比例0~255调速,左右轮差异略增减
analogWrite(Left_motor_back,0);
}
void brake(int time) //刹车,停车
{
digitalWrite(Right_motor_go,LOW);
digitalWrite(Right_motor_back,LOW);
digitalWrite(Left_motor_go,LOW);
digitalWrite(Left_motor_back,LOW);
delay(time * 100);//执行时间,可以调整
}
void left(int time) //左转(左轮不动,右轮前进)
{
digitalWrite(Right_motor_go,HIGH); // 右电机前进
digitalWrite(Right_motor_back,LOW);
analogWrite(Right_motor_go,200);
analogWrite(Right_motor_back,0);//PWM比例0~255调速
digitalWrite(Left_motor_go,LOW); //左轮后退
digitalWrite(Left_motor_back,LOW);
analogWrite(Left_motor_go,0);
analogWrite(Left_motor_back,0);//PWM比例0~255调速
delay(time * 100); //执行时间,可以调整
}
void spin_left(int time) //左转(左轮后退,右轮前进)
{
digitalWrite(Right_motor_go,HIGH); // 右电机前进
digitalWrite(Right_motor_back,LOW);
analogWrite(Right_motor_go,150);
analogWrite(Right_motor_back,0);//PWM比例0~255调速
digitalWrite(Left_motor_go,LOW); //左轮后退
digitalWrite(Left_motor_back,HIGH);
analogWrite(Left_motor_go,0);
analogWrite(Left_motor_back,150);//PWM比例0~255调速
delay(time * 100); //执行时间,可以调整
}
void right(int time)
{
digitalWrite(Right_motor_go,LOW); //右电机后退
digitalWrite(Right_motor_back,LOW);
analogWrite(Right_motor_go,0);
analogWrite(Right_motor_back,0);//PWM比例0~255调速
digitalWrite(Left_motor_go,HIGH);//左电机前进
digitalWrite(Left_motor_back,LOW);
analogWrite(Left_motor_go,200);
analogWrite(Left_motor_back,0);//PWM比例0~255调速
delay(time * 100); //执行时间,可以调整
}
void spin_right(int time) //右转(右轮后退,左轮前进)
{
digitalWrite(Right_motor_go,LOW); //右电机后退
digitalWrite(Right_motor_back,HIGH);
analogWrite(Right_motor_go,0);
analogWrite(Right_motor_back,150);//PWM比例0~255调速
digitalWrite(Left_motor_go,HIGH);//左电机前进
digitalWrite(Left_motor_back,LOW);
analogWrite(Left_motor_go,150);
analogWrite(Left_motor_back,0);//PWM比例0~255调速
delay(time * 100); //执行时间,可以调整
}
void back(int time) //后退
{
digitalWrite(Right_motor_go,LOW); //右轮后退
digitalWrite(Right_motor_back,HIGH);
analogWrite(Right_motor_go,0);
analogWrite(Right_motor_back,200);//PWM比例0~255调速
digitalWrite(Left_motor_go,LOW); //左轮后退
digitalWrite(Left_motor_back,HIGH);
analogWrite(Left_motor_go,0);
analogWrite(Left_motor_back,200);//PWM比例0~255调速
delay(time * 100); //执行时间,可以调整
}
void keysacn()//按键扫描
{
int val;
val=digitalRead(key);//读取数字7 口电平值赋给val
while(!digitalRead(key))//当按键没被按下时,一直循环
{
val=digitalRead(key);//此句可省略,可让循环跑空
}
while(digitalRead(key))//当按键被按下时
{
delay(10); //延时10ms
val=digitalRead(key);//读取数字7 口电平值赋给val
if(val==HIGH) //第二次判断按键是否被按下
{
digitalWrite(beep,HIGH); //蜂鸣器响
while(!digitalRead(key)) //判断按键是否被松开
digitalWrite(beep,LOW); //蜂鸣器停止
}
else
digitalWrite(beep,LOW); //蜂鸣器停止
}
}
float Distance_test() // 量出前方距离
{
digitalWrite(Trig, LOW); // 给触发脚低电平2μs
delayMicroseconds(2);
digitalWrite(Trig, HIGH); // 给触发脚高电平10μs,这里至少是10μs
delayMicroseconds(10);
digitalWrite(Trig, LOW); // 持续给触发脚低电
float Fdistance = pulseIn(Echo, HIGH); // 读取高电平时间(单位:微秒)
Fdistance= Fdistance/58; //为什么除以58等于厘米, Y米=(X秒*344)/2
// X秒=( 2*Y米)/344 ==》X秒=0.0058*Y米 ==》厘米=微秒/58
//Serial.print("Distance:"); //输出距离(单位:厘米)
//Serial.println(Fdistance); //显示距离
//Distance = Fdistance;
return Fdistance;
}
void Distance_display(int Distance)//显示距离
{
if((2<Distance)&(Distance<400))
{
lcd.home(); //把光标移回左上角,即从头开始输出
lcd.print(" Distance: "); //显示
lcd.setCursor(6,2); //把光标定位在第2行,第6列
lcd.print(Distance); //显示距离
lcd.print("cm"); //显示
}
else
{
lcd.home(); //把光标移回左上角,即从头开始输出
lcd.print("!!! Out of range"); //显示
}
delay(250);
lcd.clear();
}
void servopulse(int servopin,int myangle)/*定义一个脉冲函数,用来模拟方式产生PWM值*/
{
pulsewidth=(myangle*11)+500;//将角度转化为500-2480 的脉宽值
digitalWrite(servopin,HIGH);//将舵机接口电平置高
delayMicroseconds(pulsewidth);//延时脉宽值的微秒数
digitalWrite(servopin,LOW);//将舵机接口电平置低
delay(20-pulsewidth/1000);//延时周期内剩余时间
}
void front_detection()
{
//此处循环次数减少,为了增加小车遇到障碍物的反应速度
for(int i=0;i<=5;i++) //产生PWM个数,等效延时以保证能转到响应角度
{
servopulse(servopin,90);//模拟产生PWM
}
Front_Distance = Distance_test();
}
void left_detection()
{
for(int i=0;i<=15;i++) //产生PWM个数,等效延时以保证能转到响应角度
{
servopulse(servopin,175);//模拟产生PWM
}
Left_Distance = Distance_test();
}
void right_detection()
{
for(int i=0;i<=15;i++) //产生PWM个数,等效延时以保证能转到响应角度
{
servopulse(servopin,5);//模拟产生PWM
}
Right_Distance = Distance_test();
}
//===========================================================
void loop()
{
keysacn(); //调用按键扫描函数
while(1)
{
front_detection();//测量前方距离
if(Front_Distance < 32)//当遇到障碍物时
{
back(2);//后退减速
brake(2);//停下来做测距
left_detection();//测量左边距障碍物距离
Distance_display(Left_Distance);//液晶屏显示距离
right_detection();//测量右边距障碍物距离
Distance_display(Right_Distance);//液晶屏显示距离
if((Left_Distance < 35 ) &&( Right_Distance < 35 ))//当左右两侧均有障碍物靠得比较近
spin_left(0.7);//旋转掉头
else if(Left_Distance > Right_Distance)//左边比右边空旷
{
left(3);//左转
brake(1);//刹车,稳定方向
}
else//右边比左边空旷
{
right(3);//右转
brake(1);//刹车,稳定方向
}
}
else
{
run(); //无障碍物,直行
}
}
}