采用 Arduino Uno单片机作为主控单元,采用四轮式移动平台,四轮均可驱动,可以通过蓝牙控制小车前进、后退、原地转向等操作,可调节车速,可鸣笛警报,可自动识别并躲避障碍物,可遵循特定轨道自动行驶,且以上功能均可通过蓝牙进行控制的智能小车。
总体方案(硬件框图):
PCB板制作:
设计软件:Altium Designer 8.3
制作 :嘉立创公司(非广告,仅代表本人选择)
Arduino开发环境:Arduino 1.8.9
所需硬件:(本人于淘宝信泰微电子购买)
Arduino UNO(主控单片机):
4轮小车底座带马达(需要自行焊线):
L239D(电机驱动芯片):
两节18650电池:
K78L05(稳压器):
【注:若使用LM7805需要配合三节18650电池,本人并未做尝试, 可以参考文章:基于L293D的蓝牙、寻迹、避障、四驱遥控小车-Arduino中文社区 - Powered by Discuz!】
HC-05(蓝牙模组):
HC-SR04(超声波模组):
9g舵机(舵机,用以配合超声波模块在前方转动,做范围测量):
无源蜂鸣器:
TCRT5000(红外光电传感器):
PCB规格:10cm*10cm
元器件名称 |
库文件夹 |
所属的元器件库 |
L7805CV |
Library |
ST Power Mgt Voltage Regulator.IntLib |
SW-SPST |
Library |
Miscellaneous Devices.IntLib |
Res3 |
Library |
Miscellaneous Devices.IntLib |
Cap |
Library |
Miscellaneous Devices.IntLib |
Cap Pol1 |
Library |
Miscellaneous Devices.IntLib |
Header 2 |
Library |
Miscellaneous Connectors.IntLib |
Header 3 |
Library |
Miscellaneous Connectors.IntLib |
Header 4 |
Library |
Miscellaneous Connectors.IntLib |
L293D |
Library |
ST Interface DC & Stepper Motor Controller.IntLib |
PCB原理图:
PCB电路图:
PCB实物图:
软件框图:
代码:
maincontrol.ino:
#include "MOTOR.h" //自定义电机驱动库
#include "pitch.h"
#include //蓝牙库
MotorControl motorR(1); //右侧电机
MotorControl motorL(2); //左侧电机
led LED(12);
buzzeron BUZZER(9);
int motorspeed; //小车速度变量
int trac1 = 14; //从车头方向的最左边开始排序接红外寻迹模块
int trac2 = 15;
int trac3 = 16;
int trac4 = 17;
int trac5 = 18;
int val1; //寻迹模块储存值
int val2;
int val3;
int val4;
int val5;
int servopin = 10; //定义舵机接口数字接口10
int bl; //定义运行指针
int bll;
unsigned int L; //左距离存储
unsigned int R; //右距离存储
unsigned int S; //中距离存储
int trig=2; //发射信号
int echo=13; //接收信号
void setup() {
Serial.begin(9600);
LED.ledset();
pinMode(trac1, INPUT); //寻迹模块引脚初始化
pinMode(trac2, INPUT);
pinMode(trac3, INPUT);
pinMode(trac4, INPUT);
pinMode(trac5, INPUT);
pinMode(trig,OUTPUT); //超声波设置引脚模式
pinMode(echo,INPUT);
motorspeed=200;
pinMode(servopin,OUTPUT);//设定舵机v接口为输出接口
zw();//定义舵机中位
delay(500); //开机延时
bl=1;//定义运行指针值
bll=1;//定义运行指针记忆值
}
void loop() {
if(Serial.available()>0){ // 蓝牙串口有数据
chuspeed(); // 给小车速度赋值
lytest(); // 运行蓝牙解码判断
}
if(bl==2){
chuspeed(); // 给小车速度赋值
xunji();// 运行寻迹
BUZZER.tone1();
}
if(bl==3){
chuspeed();// 给小车速度赋值
motorun(); // 小车前进不停
delay(1000);
}
if(bl==4){
chuspeed();// 给小车速度赋值
bz(); // 小车避障
}
if(bl==5){
motostop();
BUZZER.tone3();
if(bll==2){bl=2;}// 喇叭响完以后继续之前程序指针
else if(bll==3){bl=3;}
else if(bll==4){bl=4;}
else {
bll=1;
bl=1;}
}
else{ motostop();}
}
/******************************************
电机
******************************************/
void chuspeed(void){ // 定义小车初始速度
motorR.motorsetSpeed(motorspeed);
motorL.motorsetSpeed(motorspeed);
}
void motostop(void){ // 定义小车停止
chuspeed();
motorR.motorrun(GORELEASE);
motorL.motorrun(GORELEASE);
}
void motorun(void){ // 定义小车前进
chuspeed();
motorR.motorrun(GOFORWARD);
motorL.motorrun(GOFORWARD);
}
void motodown(void){ // 定义小车后退
BUZZER.tone2();
chuspeed();
motorR.motorrun(GOBACKWARD);
motorL.motorrun(GOBACKWARD);
}
void motoleft(void){ // 定义小车原地左拐
chuspeed();
motorR.motorrun(GOFORWARD);
motorL.motorrun(GOBACKWARD);
}
void motoright(void){ // 定义小车原地右拐
chuspeed();
motorR.motorrun(GOBACKWARD);
motorL.motorrun(GOFORWARD);
}
void motorle(void){ // 定义小车左拐
chuspeed();
motorR.motorrun(GOFORWARD);
motorL.motorrun(GORELEASE);
}
void motorri(void){ // 定义小车右拐
chuspeed();
motorR.motorrun(GORELEASE);
motorL.motorrun(GOFORWARD);
}
/******************************************
蓝牙
******************************************/
void lytest(){// 定义蓝牙串口解码判断
int cmd = Serial.read();//读取蓝牙模块发送到串口的数据
LED.ledon();
BUZZER.tone1();
if(cmd==49){ // 手机蓝牙输出1,对应ascii数是49
Serial.println("Go forward"); //输出状态
motostop();
delay(100);
motorun();
delay(200);
}
if(cmd==50){ // 手机蓝牙输出2,对应ascii数是50,后面以此类推即加48
Serial.println("Go back"); //输出状态
motostop();
delay(100);
motodown();
delay(200);
}
if(cmd==51){
Serial.println("I say Ting Ting--"); //输出状态
motostop();
bl=1;
bll=1;
delay(100);
}
if(cmd==52){
Serial.println("Turn left"); //输出状态
motostop();
delay(100);
motoleft();
delay(200);
}
if(cmd==53){
Serial.println("Turn Right"); //输出状态
motostop();
delay(100);
motoright();
delay(200);
}
if(cmd==54){
Serial.println("Speed up");
motorspeed+=5;
if(motorspeed>255){motorspeed=255; } //不超过255最高值
Serial.print("speed=");
Serial.println(motorspeed);
}
if(cmd==55){
Serial.println("Speed down");
motorspeed-=5;
if(motorspeed<80){motorspeed=80;}//不低于0
Serial.print("speed=");
Serial.println(motorspeed);
}
if(cmd==56){ //指针寻迹
bl=2;
bll=2;
Serial.println("Follow your heart---");
delay(50);}
if(cmd==57){ //指针一直进
bl=3;
bll=3;
Serial.println("Go Forward---");
delay(50);
}
if(cmd==99){ //速度最小
Serial.println("Lowest Speed");
motorspeed =100;
Serial.print("speed=");
Serial.println(motorspeed);
}
if(cmd==100){ //速度最大
Serial.println("Highest Speed");
motorspeed =255;
Serial.print("speed=");
Serial.println(motorspeed);
}
if(cmd==97){//按健a,对应ASCII码是97 指针避障
bl=4;
bll=4;
Serial.println("Avoid---");
delay(50);}
if(cmd==98){ //按健b,对应ASCII码是98 指针喇叭
bl=5;
Serial.println("DiDiDi---"); }
}
/******************************************
红外线循迹
******************************************/
void xunji(){ //寻迹主函数
motostop();
delay(300);
val1 = digitalRead(trac1);
val2 = digitalRead(trac2); //寻迹模块返回值
val3 = digitalRead(trac3);
val4 = digitalRead(trac4);
val5 = digitalRead(trac5);
val1=!val1;
val2=!val2;
val3=!val3;
val4=!val4;
val5=!val5;
Serial.print(val1);
Serial.print(val2);
Serial.print(val3);
Serial.print(val4);
Serial.println(val5);
if(val1==1 && val2==1 && val3==0 && val4==1 && val5==1 ) //11011中间黑线,即0为黑线
{
motostop();
Serial.println("Go forward");
motorun();
delay(100);
}
else if(val1==1 && val2==0 && val3==0 && val4==0 && val5==1 ) //10001中间三黑线,十字路
{
motostop();
Serial.println("Go forward");
motorun();
delay(100);
}
else if(val1==0 && val2==0 && val3==0 && val4==0 && val5==0 ) //00000都检测到黑线
{
Serial.println("I say Ting Ting--");
motostop();
delay(500);
}
else if(val1==1 && val2==1 && val3==1 && val4==1 && val5==1 ) //11111都无检测到黑线
{
Serial.println("go...?");
motostop();
motorun();
delay(100);
}
else if(val1==1 && val2==0 && val3==0 && val4==1 && val5==1 ) //10011
{
motostop();
delay(200);
Serial.println("Turn left");
motoleft();
delay(100);
}
else if(val1==0 && val2==1 && val3==0 && val4==1 && val5==1 ) //01011
{
motostop();
delay(20);
Serial.println("Turn left");
motoleft();
delay(100);
}
else if(val1==1 && val2==0 && val3==1 && val4==1 && val5==1 ) //10111
{
motostop();
delay(20);
Serial.println("Turn left");
motoleft();
delay(100);
}
else if(val1==0 && val2==0 && val3==1 && val4==1 && val5==1 ) //00111
{
motostop();
delay(20);
Serial.println("Turn left");
motoleft();
delay(100);
}
else if(val1==0 && val2==0 && val3==0 && val4==1 && val5==1 ) //00011
{
motostop();
delay(20);
Serial.println("Turn left");
motoleft();
delay(100);
}
else if(val1==0 && val2==1 && val3==1 && val4==1 && val5==1 ) //01111
{
motostop();
delay(20);
Serial.println("Turn left");
motoleft();
delay(100);
}
else if(val1==1 && val2==1 && val3==0 && val4==0 && val5==1 ) //11001
{
motostop();
delay(20);
Serial.println("Turn right");
motoright();
delay(100);
}
else if(val1==1 && val2==1 && val3==0 && val4==1 && val5==0 ) //11010
{
motostop();
delay(20);
Serial.println("Turn right");
motoright();
delay(100);
}
else if(val1==1 && val2==1 && val3==1 && val4==0 && val5==1 ) //11101
{
motostop();
delay(20);
Serial.println("Turn rightt");
motoright();
delay(100);
}
else if(val1==1 && val2==1 && val3==1 && val4==0 && val5==0 ) //11100
{
motostop();
delay(20);
Serial.println("Turn right");
//motorri();
motoright();
delay(100);
}
else if(val1==1 && val2==1 && val3==0 && val4==0 && val5==0 ) //11000
{
motostop();
delay(20);
Serial.println("Turn right");
motoright();
delay(400);
}
else if(val1==1 && val2==1 && val3==1 && val4==1 && val5==0 ) //11110
{
motostop();
delay(20);
Serial.println("Turn right");
//motorri();
motoright();
delay(100);
}
else if(val1==1 && val2==0 && val3==1 && val4==0 && val5==1 ) //10101
{
motostop();
delay(20);
Serial.println("Turn right");
motoright();
delay(100);
}
else{
motostop();
delay(20);
}
}
/******************************************
避障
******************************************/
void bz(){//避障主程序
motostop();
delay(50);
range(); //先对中间测距值为S
if (S>60){ // 如果S大于60cm
motostop();
delay(20);
Serial.print("Distance:");
Serial.println(S);
Serial.println("Go forward"); //输出状态
motorun();//前进
delay(80);
}
else if(S<30){ // 如果S小于30cm
Serial.print("Distance:");
Serial.println(S);
Serial.println("Go backward"); //输出状态
motostop();
delay(200);
motodown();//后退
delay(400);
}
else{ // 即S小于60cm,大于30cm
Serial.print("Distance:");
Serial.println(S);
Serial.println("Stay...Detecting..."); //输出状态
turn(); //调出左右探测距离函数,判断左右距离值
Serial.print("Distance Left:"); //输出状态
Serial.println(L); //输出状态
Serial.print("Distance:"); //输出状态
Serial.println(S); //输出状态
Serial.print("Distance Right:"); //输出状态
Serial.println(R); //输出状态
if((L>R) && (L>S)){//左边比前方和右方距离大
Serial.println("Turn left"); //输出状态
motostop();
delay(100);
motoleft();//左转
delay(500);
}
else if ((R>L) && (R>S)){//右边比前方和左方距离大
Serial.println("Turn Right"); //输出状态
motostop();
delay(100);
motoright();//右转
delay(500);
}
else if ((L>R) && (LL) && (R
MOTOR.cpp:
//MOTOR.cpp
#include"MOTOR.h"
#include"Arduino.h"
/******************************************
电机
******************************************/
MotorControl::MotorControl(uint8_t num){//电机控制初始化
motornum=num;
switch (num) {
case 1:
pinMode(IN1,OUTPUT);
pinMode(IN2,OUTPUT);
pinMode(ENA,OUTPUT);
break;
case 2:
pinMode(IN3,OUTPUT);
pinMode(IN4,OUTPUT);
pinMode(ENB,OUTPUT);
break;
}
}
void MotorControl::motorrun(uint8_t cmd) {//车轮方向控制
uint8_t a, b;
switch(motornum){
case 1:
a=IN1;b=IN2;break;
case 2:
a=IN3;b=IN4;break;
}
switch(cmd){
case GOFORWARD:
digitalWrite(a,LOW);
digitalWrite(b,HIGH);
break;
case GOBACKWARD:
digitalWrite(a,HIGH);
digitalWrite(b,LOW);
break;
case GORELEASE:
digitalWrite(a,LOW);
digitalWrite(b,LOW);
break;
}
}
void MotorControl::motorsetSpeed(uint16_t motorspeed){//小车速度控制
switch(motornum){
case 1:
analogWrite(ENA, motorspeed);break;
case 2:
analogWrite(ENB, motorspeed);break;
//delay(20);
}
}
/******************************************
LED
******************************************/
led::led(uint8_t pin){
ledpin=pin;
pinMode(ledpin,OUTPUT);
}
void led::ledset(void){
digitalWrite(ledpin,LOW);
delay(200);
}
void led::ledon(void){
digitalWrite(ledpin,HIGH);
delay(200);
digitalWrite(ledpin,LOW);
digitalWrite(ledpin,HIGH);
delay(200);
digitalWrite(ledpin,LOW);
}
MOTOR.h:
//MOTOR.h
#ifndef _MOTOR_h_
#define _MOTOR_h_
//导入Arduino核心头文件
#include"Arduino.h"
//电机驱动使用的引脚
#define ENA 11
#define ENB 3
#define IN1 4
#define IN2 5
#define IN3 6
#define IN4 7
#define GOFORWARD 1
#define GOBACKWARD 2
#define GORELEASE 3
//电机
class MotorControl
{
public:
MotorControl(uint8_t motornum);
void motorrun(uint8_t);
void motorsetSpeed(uint16_t);
private:
uint8_t motornum; //motornum1为小车右侧轮子,2为左侧轮子
};
class led{
public:
led(uint8_t ledpin);
void ledset(void);
void ledon(void);
private:
uint8_t ledpin;
};
#endif
pitch.cpp:
#include"pitch.h"
#include"Arduino.h"
/******************************************
蜂鸣器
******************************************/
buzzeron::buzzeron(uint8_t pin){
buzzerpin=pin;
pinMode(buzzerpin,OUTPUT);
}
void buzzeron::tone1(void){ //提示音
int melodydoudizhu[] = {
NOTE_G4, NOTE_C5
};
int noteDurations[] = {
8, 8
};
for (int thisNote = 0; thisNote < 2; thisNote++) {
int noteDuration = 1000 / noteDurations[thisNote];
tone(buzzerpin, melodydoudizhu[thisNote], noteDuration);
int pauseBetweenNotes = noteDuration * 1.30;
delay(pauseBetweenNotes);
noTone(buzzerpin);
}
}
void buzzeron::tone2(void){ //倒车音
int melodydoudizhu[] = {
NOTE_G4, NOTE_C5
};
int noteDurations[] = {
8, 8
};
for (int thisNote = 0; thisNote < 2; thisNote++) {
int noteDuration = 1000 / noteDurations[thisNote];
tone(buzzerpin, melodydoudizhu[thisNote], noteDuration);
int pauseBetweenNotes = noteDuration * 1.30;
delay(pauseBetweenNotes);
noTone(buzzerpin);
}
}
void buzzeron::tone3(void){//斗地主
int melodydoudizhu[] = {
NOTE_G3, NOTE_G3, NOTE_A3, NOTE_C4, NOTE_G3, NOTE_A3, NOTE_C4,
NOTE_G4, NOTE_G4, NOTE_G4, NOTE_E4, NOTE_G4,
NOTE_G3, NOTE_G3, NOTE_A3, NOTE_C4, NOTE_G3, NOTE_A3, NOTE_E4,
NOTE_D4, NOTE_D4, NOTE_E4, NOTE_D4, NOTE_C4, NOTE_D4,
};
int noteDurations[] = {
2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1,
2, 4, 4, 4, 4, 4, 4, 4, 8, 8, 4, 4, 1
};
for (int thisNote = 0; thisNote < 25; thisNote++) {
int noteDuration = 1000 / noteDurations[thisNote];
tone(buzzerpin, melodydoudizhu[thisNote], noteDuration);
int pauseBetweenNotes = noteDuration * 1.30;
delay(pauseBetweenNotes);
noTone(buzzerpin);
}
}
void buzzeron::tone4(void){//爱情买卖
int melodydoudizhu[] = {
NOTE_E4, NOTE_A4, NOTE_C5, NOTE_C5, NOTE_E4, NOTE_A4, NOTE_C5,
NOTE_B4, NOTE_A4, NOTE_B4, NOTE_A4, NOTE_G4, NOTE_D4, NOTE_E4,
NOTE_D4, NOTE_D4, NOTE_D4, NOTE_A3, NOTE_D4, NOTE_E4, NOTE_G4,
NOTE_E4, NOTE_B4, NOTE_B4, NOTE_G4, NOTE_D4, NOTE_E4,
NOTE_E4, NOTE_A4, NOTE_C5, NOTE_C5, NOTE_E4, NOTE_A4, NOTE_C5,
NOTE_E5, NOTE_D5, NOTE_E5, NOTE_D5, NOTE_C5, NOTE_D5,
NOTE_E5, NOTE_E5, NOTE_D5, NOTE_C5, NOTE_D5, NOTE_D5, NOTE_C5, NOTE_B4,
NOTE_G4, NOTE_G4, NOTE_E4, NOTE_G4, NOTE_G4, NOTE_A4, NOTE_A4,
};
int noteDurations[] = {
4, 4, 4, 4, 4, 4, 2,
4, 8, 8, 4, 4, 4, 1.5,
4, 4, 4, 4, 4, 4, 2,
4, 4, 4, 4, 8, 1.5,
4, 4, 4, 4, 4, 4, 2,
4, 8, 8, 4, 4, 1,
3,8,4,4,3,8,4,4,
4,8,8,4,8,8,1
};
for (int thisNote = 0; thisNote < 55; thisNote++) {
int noteDuration = 1000 / noteDurations[thisNote];
tone(buzzerpin, melodydoudizhu[thisNote], noteDuration);
int pauseBetweenNotes = noteDuration * 1.30;
delay(pauseBetweenNotes);
noTone(buzzerpin);
}
}
void buzzeron::tonestop(void){
noTone(buzzerpin);
pinMode(buzzerpin,INPUT);
pinMode(buzzerpin,OUTPUT);
}
pitch.h:
/*************************************************
* Public Constants
*************************************************/
#ifndef _PITCH_h_
#define _PITCH_h_
#define NOTE_B0 31
#define NOTE_C1 33
#define NOTE_CS1 35
#define NOTE_D1 37
#define NOTE_DS1 39
#define NOTE_E1 41
#define NOTE_F1 44
#define NOTE_FS1 46
#define NOTE_G1 49
#define NOTE_GS1 52
#define NOTE_A1 55
#define NOTE_AS1 58
#define NOTE_B1 62
#define NOTE_C2 65
#define NOTE_CS2 69
#define NOTE_D2 73
#define NOTE_DS2 78
#define NOTE_E2 82
#define NOTE_F2 87
#define NOTE_FS2 93
#define NOTE_G2 98
#define NOTE_GS2 104
#define NOTE_A2 110
#define NOTE_AS2 117
#define NOTE_B2 123
#define NOTE_C3 131
#define NOTE_CS3 139
#define NOTE_D3 147
#define NOTE_DS3 156
#define NOTE_E3 165
#define NOTE_F3 175
#define NOTE_FS3 185
#define NOTE_G3 196
#define NOTE_GS3 208
#define NOTE_A3 220
#define NOTE_AS3 233
#define NOTE_B3 247
#define NOTE_C4 262
#define NOTE_CS4 277
#define NOTE_D4 294
#define NOTE_DS4 311
#define NOTE_E4 330
#define NOTE_F4 349
#define NOTE_FS4 370
#define NOTE_G4 392
#define NOTE_GS4 415
#define NOTE_A4 440
#define NOTE_AS4 466
#define NOTE_B4 494
#define NOTE_C5 523
#define NOTE_CS5 554
#define NOTE_D5 587
#define NOTE_DS5 622
#define NOTE_E5 659
#define NOTE_F5 698
#define NOTE_FS5 740
#define NOTE_G5 784
#define NOTE_GS5 831
#define NOTE_A5 880
#define NOTE_AS5 932
#define NOTE_B5 988
#define NOTE_C6 1047
#define NOTE_CS6 1109
#define NOTE_D6 1175
#define NOTE_DS6 1245
#define NOTE_E6 1319
#define NOTE_F6 1397
#define NOTE_FS6 1480
#define NOTE_G6 1568
#define NOTE_GS6 1661
#define NOTE_A6 1760
#define NOTE_AS6 1865
#define NOTE_B6 1976
#define NOTE_C7 2093
#define NOTE_CS7 2217
#define NOTE_D7 2349
#define NOTE_DS7 2489
#define NOTE_E7 2637
#define NOTE_F7 2794
#define NOTE_FS7 2960
#define NOTE_G7 3136
#define NOTE_GS7 3322
#define NOTE_A7 3520
#define NOTE_AS7 3729
#define NOTE_B7 3951
#define NOTE_C8 4186
#define NOTE_CS8 4435
#define NOTE_D8 4699
#define NOTE_DS8 4978
#include"Arduino.h"
class buzzeron
{
public:
buzzeron(uint8_t pin);
void tone1(void);//提示音
void tone2(void);//倒车音
void tone3(void);//斗地主
void tone4(void);//爱情买卖
void tonestop(void);
private:
uint8_t buzzerpin;
};
#endif
需要使用一个蓝牙助手适配蓝牙模块:
完成后界面: