该文章做为51单片机最后一个项目,这里记录一下项目的过程。同时记录项目的坑,以便下次规避。
一、语音控制模块
语音控制模块使用的是su-03T,只能使用离线模式的语音模块。语音的命令控制可以通过智能公元
这个网站进行配置,因为51单片机IO口和定时器有限,所以支持的小车模式功能不多,这里只处理了小车的循迹,避障和跟随三种模式。首先语音模块使用之前要进行固件烧录,另外因为需要配置自定义命令,所以最好在智能公元这个见面上设置好命令之后,再生成固件进行烧录。这里只使用了三种模式,所以只是简单的利用模块的A25,A26,A27三个引脚进行了配置,配置如下图。
另外正常情况下我设置的是三个引脚都输出高电平,设置完成之后会生成一个固件包,然后按照流程烧录即可。
这里碰到的第一个坑是因为我用的USB转TTL中未进行任何短接,直接将语音模块的VCC拉到USB转TTL的VCC上,导致一直烧录不成功,后又换到了5V引脚,可以正常烧录。
第二个坑,USB供电正常可以通过语音切换模式,用电池供电单片机老是重启,原因不是电池电压不够,而是避障模式需要驱动电机,而电机的运行可能导致电压不稳,导致单片机重启。
第二个坑分析如下:
正常情况单片机用USB供电,是5V,4节电池只给电机供电,模式切换都正常运行。但是只用4节电池供电,那么单片机其实用的就是6V(因为各模块内部肯定会有电压转换的,所以稍微高点的电压对各模块影响不大)。
- 电池电压问题,当时电池用了一段时间,怀疑电压不够(没有万能表),充了一晚上,结果第二天还是一样
- 定时器问题,在避障模式下把定时器关了,电机开着,结果还是一样的,排除定时器干扰
- 定时器开关,把电机部分关掉,模式正常切换,不会有单片机重启的现象
所以解决方法还是只能给单片机单独供电,电机也单独供电,或给单片机加个稳压模块。
理论上三个模式都用到的电机都应该出问题,因为避障模式用的电机可能比较频繁,出问题的机率最大。可以稍加延时,但是延时并不能解决问题。
语音识别获取三种模式的代码如下:
enum Mode mode = stopMode;
enum Mode getMode() {
if(a25 == 0 && a26 == 1 && a27 == 1) {
mode = tracingMode;
}
if(a25 == 1 && a26 == 0 && a27 == 1) {
mode = followMode;
}
if(a25 == 1 && a26 == 1 && a27 == 0) {
mode = avoidMode;
}
if(a25 == 0 && a26 == 0 && a27 == 0) {
mode = stopMode;
}
return mode;
}
二、循迹模块
循迹模块使用的是TCRT5000,这里主要用到引脚是DO口,用来检测高低电平,发射的红外如果未返回引脚输出高电平,红外返回了引脚输出低电平。循迹的原理就是根据左右模块的DO输出来改变左右轮子的速度来调整等位置。该项目只是用了两个简单的模块,所以在精准度上会有偏差,比如,在弯道处可能冲出轨道等,另外刚开始轨道用的是16mm宽的,但是在弯道经常脱轨,后来换成32mm, 效果就好多了。
具体代码如下:
void traceing() {
if(mode != lastMode) {
lastMode = mode;
oled_clear();
Oled_Show_Str(2, 0, "----trace----");
}
if(leftTracing == 0 && rightTracing == 0) {
/*
leftSpeed = Phase;
rightSpeed = Phase-10;
*/
forward();
}
if(leftTracing == 1 && rightTracing == 0) {
/*
leftSpeed = Phase - 70;
rightSpeed = Phase;
*/
leftward();
}
if(leftTracing == 0 && rightTracing == 1) {
/*
leftSpeed = Phase;
rightSpeed = Phase - 70;
*/
rightward();
}
if(leftTracing == 1 && rightTracing == 1) {
stop();
}
}
这里没有用定时器模块PWM来控制车子的速度,因为定时器不够用。
三、避障模块
用到的模块就是超声波模块HC-SR04和舵机sg90。检测的原理就是舵机联动着HC-SR04, 在左、前、右三个方向检测障碍物的距离,根据距离来判断是否继续前进还是左转,右转等。
代码如下:
void avoid() {
if(mode != lastMode) {
lastMode = mode;
oled_clear();
Oled_Show_Str(2, 0, "----avoid----");
}
if(dir != MIDDLE) {
dir = MIDDLE;
turn90degree();
Delay300ms();
}
disMiddle = getDistanceByUltrasonicWave();
if(disMiddle > 35) {
forward();
} else if(disMiddle < 10) {
backward();
} else {
stop();
turn180degree();
Delay300ms();
disLeft = getDistanceByUltrasonicWave();
turn90degree();
Delay300ms();
turn0degree();
dir = RIGHT;
Delay300ms();
disRight = getDistanceByUltrasonicWave();
if(disLeft < disRight) {
rightward();
Delay150ms();
stop();
}
if(disLeft > disRight){
leftward();
Delay150ms();
stop();
}
}
}
四、跟随模块
跟随模块用的是也是红外模块。原理和循迹一样。
代码实现如下:
void follow() {
if(mode != lastMode) {
lastMode = mode;
oled_clear();
Oled_Show_Str(2, 0, "----follow----");
}
if(leftFollow == 0 && rightFollow == 0) {
forward();
}
if(leftFollow == 1 && rightFollow == 0) {
rightward();
}
if(leftFollow == 0 && rightFollow == 1) {
leftward();
}
if(leftFollow == 1 && rightFollow == 1) {
stop();
}
}
五、效果
循迹
避障
跟随