/* * Copyright (c) 2015,小二极客科技有限公司 * All rights reserved. * * 文件名称:wifi-robots * 文件标识: * 摘 要:wifi机器人智能小车控制 * * 当前版本:1.0 * 作 者:小R团队 * 完成日期:2015年4月1日 */ #include //#include #include int ledpin = 13;//设置系统启动指示灯 int ENA = 5;//L298使能A int ENB = 6;//L298使能B int INPUT2 = 7;//电机接口1 int INPUT1 = 8;//电机接口2 int INPUT3 = 12;//电机接口3 int INPUT4 = 13;//电机接口4 int num;//定义电机标志位 int Echo = A5; // 定义超音波信号接收脚位 int Trig = A4; // 定义超音波信号发射脚位 int Input_Detect_LEFT = A3; //定义小车左侧红外 int Input_Detect_RIGHT = A2; //定义小车右侧红外 int Input_Detect = A1;//定义小车前方红外 int Carled = A0;//定义小车车灯接口 int Cruising_Flag = 0; int Pre_Cruising_Flag = 0 ; int Left_Speed_Hold = 200;//定义左侧速度变量 int Right_Speed_Hold = 200;//定义右侧速度变量 #define MOTOR_GO_FORWARD {digitalWrite(INPUT1,LOW);digitalWrite(INPUT2,HIGH);digitalWrite(INPUT3,LOW);digitalWrite(INPUT4,HIGH);} //车体前进 #define MOTOR_GO_BACK {digitalWrite(INPUT1,HIGH);digitalWrite(INPUT2,LOW);digitalWrite(INPUT3,HIGH);digitalWrite(INPUT4,LOW);} //车体前进 #define MOTOR_GO_RIGHT {digitalWrite(INPUT1,HIGH);digitalWrite(INPUT2,LOW);digitalWrite(INPUT3,LOW);digitalWrite(INPUT4,HIGH);} //车体前进 #define MOTOR_GO_LEFT {digitalWrite(INPUT1,LOW);digitalWrite(INPUT2,HIGH);digitalWrite(INPUT3,HIGH);digitalWrite(INPUT4,LOW);} //车体前进 #define MOTOR_GO_STOP {digitalWrite(INPUT1,LOW);digitalWrite(INPUT2,LOW);digitalWrite(INPUT3,LOW);digitalWrite(INPUT4,LOW);} //车体前进 void forward(int num) { switch(num) { case 1:MOTOR_GO_FORWARD;return; case 2:MOTOR_GO_FORWARD;return; case 3:MOTOR_GO_BACK;return; case 4:MOTOR_GO_BACK;return; case 5:MOTOR_GO_LEFT;return; case 6:MOTOR_GO_LEFT;return; case 7:MOTOR_GO_RIGHT;return; case 8:MOTOR_GO_RIGHT;return; default:return; } } void back(int num) { switch(num) { case 1:MOTOR_GO_BACK;return; case 2:MOTOR_GO_BACK;return; case 3:MOTOR_GO_FORWARD;return; case 4:MOTOR_GO_FORWARD;return; case 5:MOTOR_GO_RIGHT;return; case 6:MOTOR_GO_RIGHT;return; case 7:MOTOR_GO_LEFT;return; case 8:MOTOR_GO_LEFT;return; default:return; } } void left(int num) { switch(num) { case 1:MOTOR_GO_LEFT;return; case 2:MOTOR_GO_RIGHT;return; case 3:MOTOR_GO_LEFT;return; case 4:MOTOR_GO_RIGHT;return; case 5:MOTOR_GO_FORWARD;return; case 6:MOTOR_GO_BACK;return; case 7:MOTOR_GO_FORWARD;return; case 8:MOTOR_GO_BACK;return; default:return; } } void right(int num) { switch(num) { case 1:MOTOR_GO_RIGHT;return; case 2:MOTOR_GO_LEFT;return; case 3:MOTOR_GO_RIGHT;return; case 4:MOTOR_GO_LEFT;return; case 5:MOTOR_GO_BACK;return; case 6:MOTOR_GO_FORWARD;return; case 7:MOTOR_GO_BACK;return; case 8:MOTOR_GO_FORWARD;return; default:return; } } int Left_Speed[11]={90,106,122,138,154,170,186,203,218,234,255};//左侧速度档位值 int Right_Speed[11]={90,106,122,138,154,170,186,203,218,234,255};//右侧速度档位值 //Servo servo1;// 创建舵机#1号 //Servo servo2;// 创建舵机#2号 Servo servo3;// 创建舵机#3号 Servo servo4;// 创建舵机#4号 Servo servo5;// 创建舵机#5号 Servo servo6;// 创建舵机#6号 Servo servo7;// 创建舵机#7号 Servo servo8;// 创建舵机#8号 //byte angle1=60;//舵机#1初始值 //byte angle2=60;//舵机#2初始值 byte angle3=60;//舵机#3初始值 byte angle4=60;//舵机#4初始值 byte angle5=60;//舵机#5初始值 byte angle6=120;//舵机#6初始值 byte angle7=60;//舵机#7初始值 byte angle8=60;//舵机#8初始值 int buffer[3]; //串口接收数据缓存 int rec_flag; //串口接收标志位 int serial_data; int Uartcount; int IR_R; int IR_L; int IR; unsigned long Pretime; unsigned long Nowtime; unsigned long Costtime; float Ldistance; void Open_Light()//开大灯 { digitalWrite(Carled,HIGH); //拉低电平,正极接电源,负极接Io口 delay(1000); } void Close_Light()//关大灯 { digitalWrite(Carled, LOW); //拉低电平,正极接电源,负极接Io口 delay(1000); } void Avoiding()//红外避障函数 { IR = digitalRead(Input_Detect); if((IR == HIGH)) { forward(num);;//直行 return; } if((IR == LOW)) { MOTOR_GO_STOP;//停止 return; } } void FollowLine() // 巡线模式 { IR_L = digitalRead(Input_Detect_LEFT);//读取左边传感器数值 IR_R = digitalRead(Input_Detect_RIGHT);//读取右边传感器数值 if((IR_L == LOW) && (IR_R == LOW))//两边同时探测到障碍物 { forward(num);//直行 return; } if((IR_L == LOW) && (IR_R == HIGH))//右侧遇到障碍 { left(num);//左转 return; } if((IR_L == HIGH) &&( IR_R == LOW))//左侧遇到障碍 { right(num);//右转 return; } if((IR_L == HIGH) && (IR_R == HIGH))//左右都检测到,就如视频中的那样遇到一道横的胶带 { MOTOR_GO_STOP;//停止 return; } } char Get_Distence()//测出距离 { digitalWrite(Trig, LOW); // 让超声波发射低电压2μs delayMicroseconds(2); digitalWrite(Trig, HIGH); // 让超声波发射高电压10μs,这里至少是10μs delayMicroseconds(10); digitalWrite(Trig, LOW); // 维持超声波发射低电压 Ldistance = pulseIn(Echo, HIGH); // 读差相差时间 Ldistance= Ldistance/5.8/10; // 将时间转为距离距离(单位:公分) // Serial.println(Ldistance); //显示距离 return Ldistance; } void Avoid_wave()//超声波避障函数 { Get_Distence(); if(Ldistance < 15) { MOTOR_GO_STOP; } else { forward(num); } } void Avoid_wave_auto() { Get_Distence(); if(Ldistance < 15) { back(num);; delay(300); MOTOR_GO_STOP; } } void Send_Distance()//超声波距离PC端显示 { int dis= Get_Distence(); Serial.write(0xff); Serial.write(0x03); Serial.write(0x00); Serial.write(dis); Serial.write(0xff); delay(1000); } /* ********************************************************************************************************* ** 函数名称 :Delayed() ** 函数功能 :延时程序 ** 入口参数 :无 ** 出口参数 :无 ********************************************************************************************************* */ void Delayed() //延迟40秒等WIFI模块启动完毕 { int i; for(i=0;i<20;i++) { digitalWrite(ledpin,LOW); delay(1000); digitalWrite(ledpin,HIGH); delay(1000); } } /* ********************************************************************************************************* ** 函数名称 :setup().Init_Steer() ** 函数功能 :系统初始化(串口、电机、舵机、指示灯初始化)。 ** 入口参数 :无 ** 出口参数 :无 ********************************************************************************************************* */ void Init_Steer()//舵机初始化(角度为上次保存数值) { // angle1 = EEPROM.read(0x01);//读取寄存器0x01里面的值 // angle2 = EEPROM.read(0x02);//读取寄存器0x02里面的值 angle3 = EEPROM.read(0x03);//读取寄存器0x03里面的值 angle4 = EEPROM.read(0x04);//读取寄存器0x04里面的值 angle5 = EEPROM.read(0x05);//读取寄存器0x05里面的值 angle6 = EEPROM.read(0x06);//读取寄存器0x06里面的值 angle7 = EEPROM.read(0x07);//读取寄存器0x07里面的值 angle8 = EEPROM.read(0x08);//读取寄存器0x08里面的值 if(angle7 == 255 && angle8 == 255) { // EEPROM.write(0x01,60);//把初始角度存入地址0x01里面 // EEPROM.write(0x02,60);//把初始角度存入地址0x02里面 EEPROM.write(0x03,60);//把初始角度存入地址0x03里面 EEPROM.write(0x04,60);//把初始角度存入地址0x04里面 EEPROM.write(0x05,60);//把初始角度存入地址0x05里面 EEPROM.write(0x06,120);//把初始角度存入地址0x06里面 EEPROM.write(0x07,60);//把初始角度存入地址0x07里面 EEPROM.write(0x08,60);//把初始角度存入地址0x08里面 return; } // servo1.write(angle1);//把保存角度赋值给舵机1 // servo2.write(angle2);//把保存角度赋值给舵机2 servo3.write(angle3);//把保存角度赋值给舵机3 servo4.write(angle4);//把保存角度赋值给舵机4 servo5.write(angle5);//把保存角度赋值给舵机5 servo6.write(angle6);//把保存角度赋值给舵机6 servo7.write(angle7);//把保存角度赋值给舵机7 servo8.write(angle8);//把保存角度赋值给舵机8 num = EEPROM.read(0x10);//读取寄存器0x10里面的值 if(num==0xff)EEPROM.write(0x10,1); } void setup() { pinMode(ledpin,OUTPUT); pinMode(ENA,OUTPUT); pinMode(ENB,OUTPUT); pinMode(INPUT1,OUTPUT); pinMode(INPUT2,OUTPUT); pinMode(INPUT3,OUTPUT); pinMode(INPUT4,OUTPUT); pinMode(Input_Detect_LEFT,INPUT); pinMode(Input_Detect_RIGHT,INPUT); pinMode(Carled, OUTPUT); pinMode(Input_Detect,INPUT); pinMode(Echo,INPUT); pinMode(Trig,OUTPUT); Delayed();//延迟40秒等WIFI模块启动完毕 analogWrite(ENB,Left_Speed_Hold);//给L298使能端B赋值 analogWrite(ENA,Right_Speed_Hold);//给L298使能端A赋值 digitalWrite(ledpin,LOW); //servo1.attach(SDA);//定义舵机1控制口 //servo2.attach(SCL);//定义舵机2控制口 servo3.attach(3);//定义舵机3控制口 servo4.attach(4);//定义舵机4控制口 servo5.attach(2);//定义舵机5控制口 servo6.attach(11);//定义舵机6控制口 servo7.attach(9);//定义舵机7控制口 servo8.attach(10);//定义舵机8控制口 Serial.begin(9600);//串口波特率设置为9600 bps Init_Steer(); } /* ********************************************************************************************************* ** 函数名称 :loop() ** 函数功能 :主函数 ** 入口参数 :无 ** 出口参数 :无 ********************************************************************************************************* */ void Cruising_Mod()//模式功能切换函数 { if(Pre_Cruising_Flag != Cruising_Flag) { if(Pre_Cruising_Flag != 0) { MOTOR_GO_STOP; } Pre_Cruising_Flag = Cruising_Flag; } switch(Cruising_Flag) { case 2:FollowLine(); return;//巡线模式 case 3:Avoiding(); return;//避障模式 case 4:Avoid_wave();return;//超声波避障模式 case 5:Send_Distance();//超声波距离PC端显示 default:return; } } void loop() { while(1) { Get_uartdata(); UartTimeoutCheck(); Cruising_Mod(); } } /* ********************************************************************************************************* ** 函数名称 :Communication_Decode() ** 函数功能 :串口命令解码 ** 入口参数 :无 ** 出口参数 :无 ********************************************************************************************************* */ void Communication_Decode() { if(buffer[0]==0x00) { switch(buffer[1]) //电机命令 { case 0x01:MOTOR_GO_FORWARD; return; case 0x02:MOTOR_GO_BACK; return; case 0x03:MOTOR_GO_LEFT; return; case 0x04:MOTOR_GO_RIGHT; return; case 0x00:MOTOR_GO_STOP; return; default: return; } } else if(buffer[0]==0x01)//舵机命令 { if(buffer[2]<1)return; switch(buffer[1]) { // case 0x01:angle1 = buffer[2];servo1.write(angle1);return; // case 0x02:angle2 = buffer[2];servo2.write(angle2);return; case 0x01:if(buffer[2]>170)return;angle3 = buffer[2];servo3.write(angle3);return; case 0x02:if(buffer[2]>170)return;angle4 = buffer[2];servo4.write(angle4);return; case 0x03:if(buffer[2]>170)return;angle5 = buffer[2];servo5.write(angle5);return; case 0x04:if((buffer[2]<105)||(buffer[2]>178))return;angle6 = buffer[2];servo6.write(angle6);return; case 0x07:if(buffer[2]>170)return;angle7 = buffer[2];servo7.write(angle7);return; case 0x08:if(buffer[2]>170)return;angle8 = buffer[2];servo8.write(angle8);return; default:return; } } else if(buffer[0]==0x02)//调速 { int i,j; if(buffer[2]>10)return; if(buffer[1]==0x01)//左侧调档 { i=buffer[2]; Left_Speed_Hold=Left_Speed[i] ; analogWrite(ENB,Left_Speed_Hold); } if(buffer[1]==0x02)//右侧调档 { j=buffer[2]; Right_Speed_Hold=Right_Speed[j] ; analogWrite(ENA,Right_Speed_Hold); }else return; } else if(buffer[0]==0x33)//读取舵机角度并赋值 { Init_Steer();return; } else if(buffer[0]==0x32)//保存命令 { // EEPROM.write(0x01,angle1); // EEPROM.write(0x02,angle2); EEPROM.write(0x03,angle3); EEPROM.write(0x04,angle4); EEPROM.write(0x05,angle5); EEPROM.write(0x06,angle6); EEPROM.write(0x07,angle7); EEPROM.write(0x08,angle8); return; } else if(buffer[0]==0x13)//模式切换开关 { switch(buffer[1]) { case 0x02: Cruising_Flag = 2; return;//巡线 case 0x03: Cruising_Flag = 3; return;//避障 case 0x04: Cruising_Flag = 4; return;//雷达避障 case 0x05: Cruising_Flag = 5; return;//超声波距离PC端显示 case 0x00: Cruising_Flag = 0; return;//正常模式 default:Cruising_Flag = 0; return;//正常模式 } } else if(buffer[0]==0x05) { switch(buffer[1]) // { case 0x00:Open_Light(); return; case 0x02:Close_Light(); return; default: return; } } else if(buffer[0]==0x40)//存储电机标志 { num=buffer[1]; EEPROM.write(0x10,num); } } /* ********************************************************************************************************* ** 函数名称 :Get_uartdata() ** 函数功能 :读取串口命令 ** 入口参数 :无 ** 出口参数 :无 ********************************************************************************************************* */ void Get_uartdata(void) { static int i; if (Serial.available() > 0) //判断串口缓冲器是否有数据装入 { serial_data = Serial.read();//读取串口 if(rec_flag==0) { if(serial_data==0xff) { rec_flag = 1; i = 0; Costtime = 0; } } else { if(serial_data==0xff) { rec_flag = 0; if(i==3) { Communication_Decode(); } i = 0; } else { buffer[i]=serial_data; i++; } } } } /* ********************************************************************************************************* ** 函数名称 :UartTimeoutCheck() ** 函数功能 :串口超时检测 ** 入口参数 :无 ** 出口参数 :无 ********************************************************************************************************* */ void UartTimeoutCheck(void) { if(rec_flag == 1) { Costtime++; if(Costtime == 100000) { rec_flag = 0; } } }