Arduino智能避障小车避障程序首先建立一个名为modulecar.ino的主程序。
// modulecar.ino,玩转智能小车主程序#include <Servo.h> //导入舵机库#include <NewPing.h> //导入NwePing库// 对照系统配线方案依次指定各I/Oconst int ENA = 3 ; //左电机PWMconst int IN1 = 4 ; //左电机正const int IN2 = 5 ; //左电机负const int ENB = 6 ; //右电机PWMconst int IN3 = 7 ; //右电机正const int IN4 = 8 ; //右电机负const int trigger = 9 ; //定义超声波传感器发射脚为D9 const int echo = 10 ; //定义传感器接收脚为D10 const int max_read = 300; //设定传感器最大探测距离。
int no_good = 35; //*设定35cm警戒距离。
int read_ahead; //实际距离读数。
Servo sensorStation; //设定传感器平台。
NewPing sensor(trigger, echo, max_read); //设定传感器引脚和最大读数//系统初始化void setup(){Serial.begin(9600); //启用串行监视器可以给调试带来极大便利sensorStation.attach(11); //把D11分配给舵机pinMode(ENA, OUTPUT); //依次设定各I/O属性pinMode(IN1, OUTPUT);pinMode(IN2, OUTPUT);pinMode(ENB, OUTPUT);pinMode(IN3, OUTPUT);pinMode(IN4, OUTPUT);pinMode(trigger, OUTPUT);pinMode(echo, INPUT);sensorStation.write(90); //舵机复位至90?delay(6000); //上电等待6s后进入主循环}//主程序void loop(){read_ahead = readDistance(); //调用readDistance()函数读出前方距离Serial.println("AHEAD:");Serial.println(read_ahead); //串行监视器显示机器人前方距离if (read_ahead < no_good) //如果前方距离小于警戒值{fastStop(); //就令机器人紧急刹车waTch(); //然后左右查看,分析得出最佳路线goForward(); //*此处调用看似多余,但可以确保机器人高速运转下动作的连贯性}else goForward(); //否则就一直向前行驶}主程序用到了两个库,Servo库是IDE自带的,NwePing库是第三方库,需要下载安装。
接下来建立一个名为move.ino的标签。
//move.ino,机动模块。
//刹车void fastStop(){Serial.println("STOP"); //串行监视器显示机器人状态为STOP(停止)//左电机急停(注:L298N和L293D均带有刹车功能,在使能成立的条件下,同时向两相写入高电平可令电机急停,详见芯片手册)digitalWrite(ENA, HIGH);digitalWrite(IN1, HIGH);digitalWrite(IN2, HIGH);//右电机急停digitalWrite(ENB, HIGH);digitalWrite(IN3, HIGH);digitalWrite(IN4, HIGH); }//前进void goForward(){Serial.println("FORWARD"); //串行监视器显示机器人状态为FORWARD(前进) //左电机逆时针旋转analogWrite(ENA,106); //左电机PWM,可微调这个数值使小车左右两侧车轮转速相等,右电机同理digitalWrite(IN1, LOW);digitalWrite(IN2, HIGH);//右电机顺时针旋转analogWrite(ENB,118);digitalWrite(IN3, HIGH);digitalWrite(IN4, LOW);}//原地左转void turnLeft(){Serial.println("LEFT"); //串行监视器显示机器人状态为LEFT(向左转) //左电机正转analogWrite(ENA,106);digitalWrite(IN1, HIGH);digitalWrite(IN2, LOW);//右电机正转analogWrite(ENB,59); //*微调这个数值,使转弯时内侧车轮起主导作用。
相当于让小车向后打一把轮再拐弯。
右转同理digitalWrite(IN3, HIGH);digitalWrite(IN4, LOW);delay (205); //*延迟,数值以毫秒为单位,调节此值可使机器人动作连贯}//原地右转void turnRight(){Serial.println("RIGHT"); //串行监视器显示机器人状态为RIGHT(向右转) //左电机反转analogWrite(ENA,53);digitalWrite(IN1, LOW);digitalWrite(IN2, HIGH);//右电机反转analogWrite(ENB,118);digitalWrite(IN3, LOW);digitalWrite(IN4, HIGH);delay (205); //*调节此值可使机器人动作连贯}//原地掉头(暂时用不到)void turnAround(){Serial.println("TURN 180"); //串行监视器显示机器人状态为TURN 180(原地顺时针旋转180?)//左电机反转analogWrite(ENA,106);digitalWrite(IN1, LOW);digitalWrite(IN2, HIGH);//右电机反转analogWrite(ENB,118);digitalWrite(IN3, LOW);digitalWrite(IN4, HIGH);delay (500); //*}// ping.ino,测距模块int readDistance(){delay(30); //声波发送间隔30ms,大约每秒探测33次。
受系统所限,此值不可小于29msint cm = sensor.ping() / US_ROUNDTRIP_CM; //把Ping值(μs)转换为cm return(cm); //readDistance()返回的数值是cm}最后是驱动云台扫描并分析左右两侧距离的watch.ino模块。
//watch.ino,查看模块void waTch(){//测量右前方距离。
//*注意舵机旋转方向,SG5010为逆时针旋转sensorStation.write(20); //*舵机右转至20?。
调节此值会影响传感器扫描区域,夹角越小,机器人转弯越谨慎delay(1200); //延迟1.2s待舵机稳定int read_right = readDistance(); //调用readDistance()函数读出右前方距离Serial.print("RIGHT:");Serial.println(read_right);//sensorStation.write(90); //*舵机复位至90度。
廉价舵机大角度旋转会产生抖动,要加上这两行以求读数准确。
//delay (500); //延迟0.5s//测量左前方距离sensorStation.write(160); //舵机左转至160?delay(1200); // 延迟1.2s待舵机稳定。
int read_left = readDistance(); //调用函数读出距离左前方距离。
Serial.print("LEFT:");Serial.println(read_left);sensorStation.write(90); //这一行确保只要小车处于行驶状态,传感器就面向正前方delay (500); //延迟0.5s。
// 分析得出最佳行进路线。
if (read_right > read_left) //如果右前方距离比较大{turnRight(); //就向右转,}else turnLeft(); //否则就向左转//此处也可以加入另一层逻辑:如果左右两侧读数相等就调用turnAround()原地掉头。
但实际上触发的几率不大。
}2C液晶测试程序,Arduino版本1.5.6-r2,LiquidCrystal_I2C库版本2.0 // I#include <Wire.h> 2#include "LiquidCrystal_I2C.h" //导入IC液晶库2LiquidCrystal_I2C lcd(0x27,16,2); //设定IC地址及液晶屏参数void setup(){lcd.init(); // 始化液晶屏lcd.backlight();lcd.print("Hello, world!"); //开始打印信息lcd.setCursor(3,1); //设定显示位置,第3列,第1行lcd.print("ZANG.HAIBO"); }void loop(){}//前进void goForward(){Serial.println("FORWARD"); //串行监视器显示机器人状态为FORWARD(前进) //左电机逆时针旋转int val1 = analogRead(A0); //手动调整左电机转速。
电位器两端分别接至+5V和GND,中心抽头接至A0int leftSpeed = map(val1,0,1023,0,255); //把读数映射为PWManalogWrite(ENA,leftSpeed); //写入速度。
下面的右电机同理digitalWrite(IN1, LOW);digitalWrite(IN2, HIGH);// 右电机顺时针旋转int val2 = analogRead(A1);int rightSpeed = map(val2,0,1023,0,255);analogWrite(ENB,rightSpeed);digitalWrite(IN3, HIGH);digitalWrite(IN4, LOW); }// ping.ino,红外测距模块// trigger脚沿用D9,echo脚换成A3int readDistance(){digitalWrite(trigger,HIGH); //点亮红外发射管delayMicroseconds(200); //给接收管留出200μs响应时间IRvalue=analogRead(echo); //读取自然光和红外线下反射值的总和digitalWrite(trigger,LOW); //关闭红外发射管以读取自然光下的反射值delayMicroseconds(200); //留出200μs响应时间IRvalue=IRvalue-analogRead(echo); //刨除自然光得出实际值(红外发射管产生的部分)return map(IRvalue,120,930,30,0); //用map()函数把读数转换为距离 }代码1:HC-SR04超声波传感器典型代码digitalWrite(TrigPin, LOW);delayMicroseconds(2);digitalWrite(TrigPin, HIGH);//发送10μs的高电平触发信号delayMicroseconds(10);digitalWrite(TrigPin, LOW);distance = pulseIn(EchoPin, HIGH)*340/60/2; // 检测脉冲宽度即为超声波往返时间代码2:简易超声波测距代码const int TrigPin = 2;const int EchoPin = 3; //设定SR04连接的Arduino引脚float distance;void setup() {// 初始化串口通信及连接SR04的引脚Serial.begin(9600);pinMode(TrigPin, OUTPUT);// 要检测引脚上输入的脉冲宽度,需要先设置为输入状态pinMode(EchoPin, INPUT);Serial.println("Ultrasonic sensor:");}void loop() {//产生一个10μs的高脉冲去触发TrigPindigitalWrite(TrigPin, LOW);delayMicroseconds(2);digitalWrite(TrigPin, HIGH);delayMicroseconds(10);digitalWrite(TrigPin, LOW);// 检测脉冲宽度,并计算出距离distance = pulseIn(EchoPin, HIGH) /58.00;Serial.print(distance);Serial.print("cm");Serial.println();delay(1000);}代码3:具有温度补偿的超声波测距代码#include <OneWire.h>#include <DallasTemperature.h> //设定SR04连接的Arduino引脚const int TrigPin = 2;const int EchoPin = 3;float distance;float temperature_value; #define ONE_WIRE_BUS 4OneWire oneWire(ONE_WIRE_BUS); DallasTemperature sensors(&oneWire); void setup() { //初始化串口通信及连接SR04的引脚Serial.begin(9600);pinMode(TrigPin, OUTPUT);//要检测引脚上输入的脉冲宽度,需要先设置为输入状态pinMode(EchoPin, INPUT);sensors.begin();}void loop() {//产生一个10μs的高脉冲去触发TrigPinsensors.requestTemperatures();temperature_value = sensors.getTempCByIndex(0);Serial.print("temperature = ");Serial.print(temperature_value);Serial.print("C ");digitalWrite(TrigPin, LOW);delayMicroseconds(2);digitalWrite(TrigPin, HIGH);delayMicroseconds(10);digitalWrite(TrigPin, LOW);//检测脉冲宽度,并计算出距离distance = pulseIn(EchoPin, HIGH) *(331.4+0.6*temperature_value)/2; Serial.print("distance = ");Serial.print(distance);Serial.print("cm");Serial.println();delay(1000);}代码4:基于GP2D12的红外测距系统代码int i;float val;void setup(){Serial.begin(9600);}void loop(){i=analogRead(A0);val=2547.8/((float)i*0.49-10.41)-0.42;Serial.println(val,2);}//蓝牙遥控小车//Arduino 源程序//定稿日期:2016-3-16//程序功能简介://程序采用软件PWM方式,控制两支直流电机的运行行为,实现直行、后退、左转和右转动作。