今年国庆是建国 70 周年,麦昆有幸参加了国庆花车游行,我们一起来看看吧。
步骤1 场地设计
场地是一个椭圆形巡线轨迹,中间有四个停止点,用白色纸条标记。制作方法是用电工绝缘胶带贴到瓷砖上,停止点贴白色纸条。
小车在第一个停止点需要完成转圈表演。第二个停止点需要停下来播放《歌唱祖国》。第三个停止点需要播放《解放军进行曲》并闪烁车灯。第四个停止点需要播放《没有党就没有新中国》,车灯闪烁,底灯交替变换颜色。
步骤2 造型设计
用 3D 打印机打印了一个火箭的模型,放到麦昆背上。通过电池两侧和 Microbit 上的双面胶固定。
步骤3 编写代码
主程序为巡线算法。遇到停止点后判断处于第几个停止点。第一个停止点直接转圈,后面三个停止点分别播放不同歌曲。第三停止点需要加上车灯闪烁效果。第四个停止点还要加上底灯变色效果。
转圈算法通过等待时间控制转圈的角度。运行的时候需要不断调试。
下面分别是歌曲简谱和对应的音乐代码。
第一句标志性不够,听不出来。编程调试后去掉了。
子线程 1 控制车灯有规律的亮灭。子线程 2 控制底灯随机变色。
步骤4 运行调试
由于整个项目步骤繁多,所以代码需要一部分一部分实现。首先设计巡线算法。由于传感器个数限制,采用白色纸条作为停止点。设计好后先完成了定点转圈功能。每完成一部分功能应该及时保存,调试。下面是定点转圈的调试画面。
通过时间来控制转圈的次数和角度,想法很美好,现实很骨感。麦昆空载情况下一切正常。背上火箭后就总转不到正确的角度,需要不断修改时间。有时候第一轮正常转圈,第二轮就脱轨了。所以调试的时候还是比较麻烦的,加上火箭已经被双面胶固定了,拆卸不是很方便。
停止点三运行效果
停止点四运行效果
#include <Microbit_Sound.h>
#include <Maqueen_Motor.h>
#include <DFRobot_Task.h>
#include <DFRobot_NeoPixel.h>
double mind_n_flag;
double mind_n_R;
double mind_n_G;
double mind_n_B;
Maqueen_Motor motor;
DFRobot_NeoPixel rgb_display_15;
void GeChangZuGuo();
void JieFangJunJinXingQu();
void ZhuanQuan();
void MeiYouGongChanDangJiuMeiYouXinZhongGuo();
void GeChangZuGuo()
{
MSound.playTone(0, 196, BEAT_1);
MSound.playTone(0, 392, BEAT_1_2);
MSound.playTone(0, 262, BEAT_1);
MSound.playTone(0, 196, BEAT_1);
MSound.playTone(0, 330, BEAT_1);
MSound.playTone(0, 262, BEAT_1);
MSound.playTone(0, 392, BEAT_2);
MSound.playTone(0, 440, BEAT_1_2);
MSound.playTone(0, 392, BEAT_1_2);
MSound.playTone(0, 392, BEAT_1);
MSound.playTone(0, 392, BEAT_1_4);
MSound.playTone(0, 523, BEAT_1);
MSound.playTone(0, 523, BEAT_1);
MSound.playTone(0, 440, BEAT_1_2);
MSound.playTone(0, 392, BEAT_1_4);
MSound.playTone(0, 349, BEAT_1_4);
MSound.playTone(0, 392, BEAT_2);
MSound.playTone(0, 392, BEAT_1);
MSound.playTone(0, 392, BEAT_1_2);
MSound.playTone(0, 440, BEAT_1);
MSound.playTone(0, 440, BEAT_1);
MSound.playTone(0, 294, BEAT_1);
MSound.playTone(0, 294, BEAT_1_2);
MSound.playTone(0, 294, BEAT_1_2);
MSound.playTone(0, 392, BEAT_1);
MSound.playTone(0, 349, BEAT_1_2);
MSound.playTone(0, 330, BEAT_1);
MSound.playTone(0, 196, BEAT_1_2);
MSound.playTone(0, 392, BEAT_1_2);
MSound.playTone(0, 392, BEAT_1);
MSound.playTone(0, 392, BEAT_1_2);
MSound.playTone(0, 440, BEAT_1_2);
MSound.playTone(0, 392, BEAT_1_2);
MSound.playTone(0, 349, BEAT_1_2);
MSound.playTone(0, 330, BEAT_1_2);
MSound.playTone(0, 294, BEAT_1_2);
MSound.playTone(0, 262, BEAT_2);
MSound.playTone(0, 392, BEAT_1);
MSound.playTone(0, 392, BEAT_1_2);
MSound.playTone(0, 523, BEAT_1);
MSound.playTone(0, 523, BEAT_1);
MSound.playTone(0, 440, BEAT_1);
MSound.playTone(0, 440, BEAT_1_2);
MSound.playTone(0, 392, BEAT_1_2);
MSound.playTone(0, 349, BEAT_1);
MSound.playTone(0, 392, BEAT_1_2);
MSound.playTone(0, 440, BEAT_1);
MSound.playTone(0, 294, BEAT_1_2);
MSound.playTone(0, 294, BEAT_1_2);
MSound.playTone(0, 392, BEAT_1);
MSound.playTone(0, 392, BEAT_1_2);
MSound.playTone(0, 440, BEAT_1_2);
MSound.playTone(0, 392, BEAT_1_2);
MSound.playTone(0, 349, BEAT_1_2);
MSound.playTone(0, 330, BEAT_1_2);
MSound.playTone(0, 294, BEAT_1_2);
MSound.playTone(0, 262, BEAT_2);
}
void JieFangJunJinXingQu()
{
MSound.playTone(0, 262, BEAT_1_2);
MSound.playTone(0, 262, BEAT_1);
MSound.playTone(0, 330, BEAT_1_2);
MSound.playTone(0, 392, BEAT_1_2);
MSound.playTone(0, 392, BEAT_1);
MSound.playTone(0, 440, BEAT_1_2);
MSound.playTone(0, 523, BEAT_1);
MSound.playTone(0, 440, BEAT_1_2);
MSound.playTone(0, 392, BEAT_1);
delay(500);
MSound.playTone(0, 262, BEAT_1_2);
MSound.playTone(0, 262, BEAT_1);
MSound.playTone(0, 330, BEAT_1_2);
MSound.playTone(0, 440, BEAT_1);
MSound.playTone(0, 392, BEAT_1_2);
MSound.playTone(0, 330, BEAT_1_4);
MSound.playTone(0, 294, BEAT_2);
MSound.playTone(0, 294, BEAT_1);
delay(500);
MSound.playTone(0, 262, BEAT_1_2);
MSound.playTone(0, 262, BEAT_1);
MSound.playTone(0, 330, BEAT_1_2);
MSound.playTone(0, 392, BEAT_1_2);
MSound.playTone(0, 392, BEAT_1);
MSound.playTone(0, 440, BEAT_1_2);
MSound.playTone(0, 523, BEAT_1);
MSound.playTone(0, 440, BEAT_1_2);
MSound.playTone(0, 392, BEAT_1);
delay(500);
MSound.playTone(0, 262, BEAT_1_2);
MSound.playTone(0, 262, BEAT_1_4);
MSound.playTone(0, 330, BEAT_1_4);
MSound.playTone(0, 392, BEAT_1_2);
MSound.playTone(0, 392, BEAT_1_2);
MSound.playTone(0, 440, BEAT_1_2);
MSound.playTone(0, 440, BEAT_1_2);
MSound.playTone(0, 392, BEAT_1_2);
MSound.playTone(0, 330, BEAT_1_4);
MSound.playTone(0, 330, BEAT_1_4);
MSound.playTone(0, 294, BEAT_2);
MSound.playTone(0, 262, BEAT_1);
}
void ZhuanQuan()
{
motor.motorRun(motor.LEFT,motor.CW,200);
motor.motorRun(motor.RIGHT,motor.CW,200);
delay(200);
motor.motorRun(motor.LEFT,motor.CW,200);
motor.motorRun(motor.RIGHT,motor.CCW,200);
delay(4380);
motor.motorStop(motor.LEFT);
motor.motorStop(motor.RIGHT);
}
void MeiYouGongChanDangJiuMeiYouXinZhongGuo()
{
MSound.playTone(0, 262, BEAT_1);
MSound.playTone(0, 196, BEAT_1);
MSound.playTone(0, 220, BEAT_1_2);
MSound.playTone(0, 220, BEAT_1_2);
MSound.playTone(0, 196, BEAT_1_2);
MSound.playTone(0, 220, BEAT_1_2);
MSound.playTone(0, 262, BEAT_1_2);
MSound.playTone(0, 262, BEAT_1_2);
MSound.playTone(0, 220, BEAT_1_2);
MSound.playTone(0, 262, BEAT_1_2);
MSound.playTone(0, 294, BEAT_2);
MSound.playTone(0, 330, BEAT_1);
MSound.playTone(0, 294, BEAT_1);
MSound.playTone(0, 262, BEAT_1_2);
MSound.playTone(0, 330, BEAT_1_2);
MSound.playTone(0, 294, BEAT_1_2);
MSound.playTone(0, 262, BEAT_1_2);
MSound.playTone(0, 220, BEAT_1_2);
MSound.playTone(0, 294, BEAT_1_2);
MSound.playTone(0, 247, BEAT_1_2);
MSound.playTone(0, 220, BEAT_1_2);
MSound.playTone(0, 196, BEAT_2);
}
newTask(task1);
void task1::setup() {
MSound.playTone(0, 440, BEAT_1_4);
}
void task1::loop() {
digitalWrite(8,HIGH);
digitalWrite(12,LOW);
delay(500);
digitalWrite(8,LOW);
digitalWrite(12,HIGH);
delay(500);
digitalWrite(8,HIGH);
digitalWrite(12,HIGH);
delay(500);
}
newTask(task2);
void task2::setup() {
rgb_display_15.begin(15, 4, 255);
}
void task2::loop() {
mind_n_R = (random(0, 255+1));
mind_n_G = (random(0, 255+1));
mind_n_B = (random(0, 255+1));
rgb_display_15.setRangeColor(-1, -1, rgb_display_15.rgbToColor(round(mind_n_R), round(mind_n_G), round(mind_n_B)));
delay(500);
}
void setup() {
taskStart();
mind_n_flag = 1;
taskFree();
rgb_display_15.begin(15, 4, 255);
dfrobotRandomSeed();
}
void loop() {
if (((digitalRead(13) == 0) && (digitalRead(14) == 0))) {
motor.motorRun(motor.LEFT,motor.CW,200);
motor.motorRun(motor.RIGHT,motor.CW,200);
}
else {
if (((digitalRead(13) == 1) && (digitalRead(14) == 0))) {
motor.motorRun(motor.LEFT,motor.CW,100);
motor.motorRun(motor.RIGHT,motor.CW,0);
}
else {
if (((digitalRead(13) == 0) && (digitalRead(14) == 1))) {
motor.motorRun(motor.LEFT,motor.CW,0);
motor.motorRun(motor.RIGHT,motor.CW,100);
}
else {
if (((digitalRead(13) == 1) && (digitalRead(14) == 1))) {
motor.motorStop(motor.LEFT);
motor.motorStop(motor.RIGHT);
if ((mind_n_flag == 1)) {
ZhuanQuan();
}
if ((mind_n_flag == 2)) {
GeChangZuGuo();
}
if ((mind_n_flag == 3)) {
taskStart(task1);
JieFangJunJinXingQu();
}
if ((mind_n_flag == 4)) {
taskStart(task2);
MeiYouGongChanDangJiuMeiYouXinZhongGuo();
mind_n_flag = 0;
taskFree();
rgb_display_15.clear();
digitalWrite(8,LOW);
digitalWrite(12,LOW);
}
delay(500);
motor.motorRun(motor.LEFT,motor.CW,200);
motor.motorRun(motor.RIGHT,motor.CW,200);
delay(500);
mind_n_flag = mind_n_flag + 1;
}
}
}
}
}
附件
后记
第一次尝试复杂路线巡线,一开始完全没头绪。原本想着两个巡线传感器来巡用电工绝缘胶布制作的轨迹可能不够用,就去买了一个巡线传感器。我想把传感器装在一侧,这样就可以检测到路口了。不过这个想法被其他老师采用了,我就放弃了。后来还是改用白色纸条作为停止点。
转圈真是个坑。加了火箭以后可能这次能转回来,下次就不行了。不知道是不是电量变化的原因。调试挺费劲的。
ASH腻2019.10.16
真棒