include <SCoop.h>
int leftMotor1=9;//设置不同电机串口
int leftMotor2=8;
int rightMotor3=11;
int rightMotor4=10;
int track1=7;//设置红外线串口从左向右依次为1 2 3 4
int track2=6;
int track3=5;
int track4=4;
int ECH=12;//设置超声波串口
int TRI=13;
void forward();//声明函数前进
void backword();//声明函数后退
void right();//声明函数左转
void left();//声明函数右转
void stop1();//声明函数停止
void trackright();//声明函数单侧右转
void trackleft();//声明函数单侧左转
void turnon(char cmd);//声明电机启动状态并可赋值
void tracing();//声明函数循迹
int TE();//声明函数超声波测距,返回距离“d”
#define NOTE_F1 350
#define NOTE_F2 393
#define NOTE_F3 441
#define NOTE_F4 495
#define NOTE_F5 556
#define NOTE_F6 624
#define NOTE_F7 661
#define NOTE_0 0
#define NOTE_FL1 175
#define NOTE_FL2 196
#define NOTE_FL3 221
#define NOTE_FL4 234
#define NOTE_FL5 262
#define NOTE_FL6 294
#define NOTE_FL7 330
#define NOTE_FH1 700
#define NOTE_FH2 786
#define NOTE_FH3 882
#define NOTE_FH4 935
#define NOTE_FH5 1049
#define NOTE_FH6 1178
#define NOTE_FH7 1322
#define WHOLE 1
#define HALF 0.5
#define QUARTER 0.25
#define EIGHTH 0.25
#define SIXTEENTH 0.625
int tune[] = //简谱频率
{
NOTE_F4,NOTE_F4,NOTE_F4,NOTE_F4,NOTE_F6,NOTE_F6,NOTE_F6,NOTE_F6,
NOTE_F5,NOTE_F5,NOTE_F5,NOTE_F5,NOTE_FH1,NOTE_FH1,NOTE_FH1,NOTE_FH1,
NOTE_FH2,NOTE_FH2,NOTE_FH2,NOTE_FH2,NOTE_FH2,NOTE_FH2,NOTE_FH2,NOTE_FH2,
NOTE_F5,NOTE_F4,NOTE_F3,NOTE_F1,NOTE_F2,NOTE_0,NOTE_F2,NOTE_F6,
NOTE_F5,NOTE_0,NOTE_F4,NOTE_0,NOTE_F3,NOTE_0,NOTE_F3,NOTE_F3,NOTE_F5,NOTE_0,NOTE_F4,NOTE_F3,NOTE_F2,NOTE_0,NOTE_F2,NOTE_FH4,
NOTE_FH3, NOTE_FH4, NOTE_FH3, NOTE_FH4, NOTE_F2, NOTE_0,NOTE_F2,NOTE_FH4, NOTE_FH3, NOTE_FH4, NOTE_FH3, NOTE_FH4, NOTE_F2, NOTE_0,NOTE_F2,NOTE_F6,
NOTE_F5,NOTE_0,NOTE_F4,NOTE_0,NOTE_F3,NOTE_0,NOTE_F3,NOTE_F3,NOTE_F5,NOTE_0,NOTE_F4,NOTE_F3,NOTE_F2,NOTE_0,NOTE_F2,NOTE_FH4,
NOTE_FH3, NOTE_FH4, NOTE_FH3, NOTE_FH4, NOTE_F2, NOTE_0,NOTE_F2,NOTE_FH4,NOTE_FH3, NOTE_FH4, NOTE_FH3, NOTE_FH4,
};
float durt[]= //根据简谱列出各节拍
{
0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,
0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,
0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,
0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,
0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,
0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,
0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,
0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,
0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,
0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,
0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,
0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5
};
int length;//这里定义一个变量,后面用来表示共有多少个音符
int tonepin=3;//蜂鸣器的pin
defineTask(TaskTest1);//定义子线程1
defineTask(TaskTest2);//定义子线程2
void TaskTest1::setup()//线程1设定
{
Serial.begin(9600);
pinMode(leftMotor1,OUTPUT);//设置直流电机串口为输出
pinMode(leftMotor2,OUTPUT);
pinMode(rightMotor3,OUTPUT);
pinMode(rightMotor4,OUTPUT);
pinMode(track1,INPUT);//设置红外线串口为输入
pinMode(track2,INPUT);
pinMode(track3,INPUT);
pinMode(track4,INPUT);
//pinMode(track5,INPUT);
//pinMode(track6,INPUT);
pinMode(ECH,INPUT);//要检测引脚输入的脉冲宽度,需先设置为输入状态
pinMode(TRI,OUTPUT);
}
void TaskTest1::loop()//线程1循环(快速定义)
{
a://跳转的终止位置
if(Serial.available())//如果串口缓冲区有数据则执行
{
char cmd=Serial.read();//将读取串口缓冲区一个字节的数据赋值给cmd
if(cmd=='T')//如果读取数据为“T”
{
tracing();
}
else if (cmd=='K')//如果读取数据为“K”
{
while(TE())//如果超声波测距返回有值进行指令
{
if(TE()<=35)
{
stop1();
left();
delay(300);
}
else if(Serial.read()=='Q')//如果在串口缓冲区读到的值为‘Q’则执行
{
goto a;//跳转
}
else
{
forward();
}
}
}
else
{
turnon(cmd);//电机激活但并不启动
}
}
}
void TaskTest2::setup()//线程2设定
{
pinMode(tonepin,OUTPUT);//设置蜂鸣器的pin为输出模式
length = sizeof(tune)/sizeof(tune[0]);//这里用了一个sizeof函数,可以查出
}
void TaskTest2::loop()//线程2循环
{
b:
if(Serial.read()=='M')
{
for(int x=0;x<length;x++)
{
tone(tonepin,tune[x]);
delay(500*durt[x]); //这里用来根据节拍调节延时,500这个指数可以自己调整,在该音乐中,我发现用500比较合适。
noTone(tonepin);
}
}
else if(Serial.read()=='C')
{
Serial.println("12i");
goto b;
}
}
void setup()
{
mySCoop.start();
}
void loop()
{
yield();
}
void turnon(char cmd)//电机启动并输入一个值
{
switch(cmd)
{
case'W':
forward();
break;
case'S':
backward();
break;
case'Q':
stop1();
break;
case'D':
right();
break;
case'A':
left();
break;
}
}
void tracing()//红外循迹
{
int t1;
int t2;
int t3;
int t4;
红外线循迹///
while(Serial.available()==0)//如果串口缓冲区值为零进行指令
{
t1=digitalRead(track1);
t2=digitalRead(track2);
t3=digitalRead(track3);
t4=digitalRead(track4);
if(t1==1&&t2==1&&t3==1&&t4==1)//从左至右依次为t1 t2 t3 t4
{
stop1();//停止
}
else if(t1==1||t2==1)
{
trackleft(); //单侧左转
}
else if(t3==1||t4==1)
{
trackright();
}
else if(t1==0&&t2==0&&t3==0&&t4==0)
{
forward();
}
}
}
子函数
void forward()//前进
{
Serial.println("FORWARD");//输出状态
digitalWrite(leftMotor1,HIGH);
digitalWrite(leftMotor2,LOW);
digitalWrite(rightMotor3,HIGH);
digitalWrite(rightMotor4,LOW);
}
void backward()//后退
{
Serial.println("BACKWORD");//输出状态
digitalWrite(leftMotor1,LOW);
digitalWrite(leftMotor2,HIGH);
digitalWrite(rightMotor3,LOW);
digitalWrite(rightMotor4,HIGH);}
void right()
{
Serial.println("RIGHT");//输出状态
digitalWrite(leftMotor1,HIGH);
digitalWrite(leftMotor2,LOW);
digitalWrite(rightMotor3,LOW);
digitalWrite(rightMotor4,HIGH);}
void left()//左转
{
Serial.println("LEFT");//输出状态
digitalWrite(leftMotor1,LOW);
digitalWrite(leftMotor2,HIGH);
digitalWrite(rightMotor3,HIGH);
digitalWrite(rightMotor4,LOW);}
void stop1()//停止
{
Serial.println("STOP");//输出状态
digitalWrite(leftMotor1,LOW);
digitalWrite(leftMotor2,LOW);
digitalWrite(rightMotor3,LOW);
digitalWrite(rightMotor4,LOW);
}
void trackright()//单侧右转
{
digitalWrite(leftMotor1,HIGH);
digitalWrite(leftMotor2,LOW);
digitalWrite(rightMotor3,HIGH);
digitalWrite(rightMotor4,HIGH);}
void trackleft()//单侧左转
{
digitalWrite(leftMotor1,HIGH);
digitalWrite(leftMotor2,HIGH);
digitalWrite(rightMotor3,HIGH);
digitalWrite(rightMotor4,LOW);
}
int TE()//超声波测距并返回距离“d”
{
float d;
digitalWrite(TRI,LOW);
delayMicroseconds(8);
digitalWrite(TRI,HIGH);
delayMicroseconds(10);
digitalWrite(TRI,LOW);
d=pulseIn(ECH,HIGH)/58.30;
Serial.print("Distance:");
Serial.print(d);
Serial.println("cm");
return d;
}
# 实现了超声波避障,蓝牙,红外循迹(功能一般),蜂鸣器,忘记是否改过,可能是单片机功能问题,在执行循迹以及避障时播放音乐会卡住,主体结构没问题,最多就是电机正反转有问题