“无限交互,全新驾驶体验!智能语音小车,与您共同开创未来出行。”#51单片机最终项目《智能语音小车》【中】

这篇具有很好参考价值的文章主要介绍了“无限交互,全新驾驶体验!智能语音小车,与您共同开创未来出行。”#51单片机最终项目《智能语音小车》【中】。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

  本篇博文介绍的是用51单片机的最终项目《智能语音小车》【中】,包含循迹小车基本原理和方案,根据循迹原理实现循迹功能代码编写,解决冲出赛道不转弯问题,优化转弯平滑。加入电机调速,跟随小车,摇头测距小车01_舵机和超声波封装,摇头测距小车02_实现疯狂摇头,摇头测距小车03_测距摇头,摇头测距小车04_摇头测距和行驶bug调试。看到这篇博文的朋友,可以先赞再看吗?

预备知识

  一、需要我之前写的所有博文的知识,如果还没看我之前的的博文,可以去看看后再看本篇博文
“无限交互,全新驾驶体验!智能语音小车,与您共同开创未来出行。”#51单片机最终项目《智能语音小车》【中】,学习嵌入式笔记,嵌入式硬件,单片机,51单片机,c语言,学习
  二、C变量
  三、基本输入输出
  四、流程控制
  五、函数

  六、指针
  七、字符串

  如果以上知识不清楚,请自行学习后再来浏览。如果我有没例出的,请在评论区写一下。谢谢啦!

1.循迹小车基本原理和方案

1.1循迹模块简介

  循迹模块也叫TCRT5000传感器,他的红外发射二极管不断发射红外线 ,当发射出的红外线没有被反射回来被反射回来但强度不够大时, 红外接收管一直处于关断状态,此时模块的输出端为高电平,指示二极管一直处于熄灭状态 。被检测物体出现在检测范围内时,红外线被反射回来且强度足够大,红外接收管饱和,此时模块的输出端为低电平,指示二极管被点亮

  总结:没反射回来,D0输出高电平,灭灯

“无限交互,全新驾驶体验!智能语音小车,与您共同开创未来出行。”#51单片机最终项目《智能语音小车》【中】,学习嵌入式笔记,嵌入式硬件,单片机,51单片机,c语言,学习

1.2循迹模块的接线方式

  接线方式
  VCC:接电源正极(3-5V
  GND:接电源负极
  DO:TTL开关信号输出0、1
  AO:模拟信号输出(不同距离输出不同的电压,此脚一般可以不接

1.3循迹小车原理

  由于黑色具有较强的吸收能力,当循迹模块发射的红外线照射到黑线时,红外线将会被黑线吸收,导致循迹模块上光敏三极管处于关闭状态,此时模块上一个LED熄灭。在没有检测到黑线时,模块上两个LED常亮

  总结:有感应到黑线,D0输出高电平 ,灭灯

“无限交互,全新驾驶体验!智能语音小车,与您共同开创未来出行。”#51单片机最终项目《智能语音小车》【中】,学习嵌入式笔记,嵌入式硬件,单片机,51单片机,c语言,学习

  循迹模块安装在小车车头两侧

  下方小车两个模块都能反射回来红外,输出低电平,灯亮,直走

  上方小车左模块遇到黑线,红外被吸收,左模块输出高电平,右模块输出低电平,左转,反之右转

2.根据循迹原理实现循迹功能代码编写

2.1根据循迹原理实现循迹功能代码编写核心思路

  • 在主C文件中声明循迹模块所需引脚

  • 在主C文件while(1)死循环内进行循迹模块返回数据判断,并执行相应代码

  • 通过智能小车赛道验证代码可信性

  注:此程序基于电机相关代码封装_分文件工程开发

2.2在主C文件中声明循迹模块所需引脚

  • 左轮循迹模块接单片机P2.7口,右轮循迹模块接单片机P2.6口。
  • 代码体现
sbit leftTracking = P2^7;     //左边轮子的循迹模块接单片机P2.7口
sbit rightTracking = P2^6;    //右边轮子的循迹模块接单片机P2.6口

2.3在主C文件while(1)死循环内进行循迹模块返回数据判断,并执行相应代码

  • 根据1.3的结论进行对循迹模块的判断。
  • 代码体现
f(leftTracking==0 && rightTracking==0)
{
    goFront();
}
//上方小车左模块遇到黑线,红外被吸收,左模块输出高电平,右模块输出低电平,左转,反之右转
if(leftTracking==1 && rightTracking==0)
{
    goLeft();
}

if(leftTracking==0 && rightTracking==1)
{
    goRight();
}

if(leftTracking==1 && rightTracking==1)
{
    stop();
}
  • 在motor.c文件中封装停止函数

  封装思路:将左右轮变量赋0即可停止

  代码体现:

void stop()
{
	RightControA = 0;
	RightControB = 0;
	
	LeftControA  = 0;
	LeftControB  = 0;
}
  • 在motor.h文件中声明stop函数

void goLeft();

void goRight();

void goBack();

void goFront();

void stop();
  • 主C文件代码为
#include "motor.h"
#include "delay.h"
#include "reg52.h3"

sbit leftTracking = P2^7;     //左边轮子的循迹模块接单片机P2.7口
sbit rightTracking = P2^6;    //右边轮子的循迹模块接单片机P2.6口

void main()
{
	while(1)
	{
		//下方小车两个模块都能反射回来红外,输出低电平,灯亮,直走
     
		if(leftTracking==0 && rightTracking==0)
		{
			goFront();
		}
		//上方小车左模块遇到黑线,红外被吸收,左模块输出高电平,右模块输出低电平,左转,反之右转
		if(leftTracking==1 && rightTracking==0)
		{
			goLeft();
		}
		
		if(leftTracking==0 && rightTracking==1)
		{
			goRight();
		}
		
		if(leftTracking==1 && rightTracking==1)
		{
			stop();
		}
	}
}

2.4通过智能小车赛道验证代码可信性

  • 赛道建设建议

  材料可以准备A4纸(可用作业本没写过的背面替代),黑色电工胶布,白色纸胶布或者白色电工胶布。

  将A4纸纵向拼接在一起,纸与纸之间用白色纸脚布或者白色电工胶布粘住。最后构成一个矩形即可。

  在构成的矩形边中间位置贴黑色电工胶布,拐弯处注意圆角处理。这样赛道就完工了。

  使用时找重物按住即可

  • 智能小车赛道验证结果

  当把小车放在赛道上时,小车能走直线,但拐弯会跑出赛道。原因有两个:

  一、小车速度过快

  二、循迹模块太灵敏,很容易接收地面反光。

  解决办法:

  一、使用PWM调速使小车减速通过弯道

  二、通过调节循迹模块上的十字电位器,调低灵敏度

3.解决冲出赛道不转弯问题,优化转弯平滑。加入电机调速

3.1解决冲出赛道不转弯问题,优化转弯平滑。加入电机调速核心思路

  • 在主C文件中添加左右轮循迹模块声明
  • 在主C文件主函数内添加判断左右循迹模块返回参数判断并设置左右轮转速。
  • 调试优化,使小车循迹

  注:此程序基于左右电机的各自调速管理工程开发

3.2在主C文件中添加左右轮循迹模块声明

  • 代码声明
sbit leftTracking = P2^7;     //左边轮子的循迹模块接单片机P2.7口
sbit rightTracking = P2^6;    //右边轮子的循迹模块接单片机P2.6口

3.3在主C文件主函数内添加判断左右循迹模块返回参数判断并设置左右轮转速。

  • 判断循迹模块返回参数思路和1.3一样
  • 代码体现
while(1)
{
    //下方小车两个模块都能反射回来红外,输出低电平,灯亮,直走

    if(leftTracking==0 && rightTracking==0)
    {
        speedRight = 25;
        speedLeft  = 25;
    }
    //上方小车左模块遇到黑线,红外被吸收,左模块输出高电平,右模块输出低电平,左转,反之右转
    if(leftTracking==1 && rightTracking==0)
    {
        speedLeft = 10;
        speedRight = 40;
    }

    if(leftTracking==0 && rightTracking==1)
    {
        speedLeft = 40;
        speedRight = 10;
    }

    if(leftTracking==1 && rightTracking==1)
    {
        speedLeft = 0;
        speedRight = 0;
    }
}
  • 主C文件代码
#include "motor.h"
#include "delay.h"
#include "uart.h"
#include "time0.h"
#include "time1.h"
#include "reg52.h"

extern char speedRight;
extern char speedLeft;

sbit leftTracking = P2^7;     //左边轮子的循迹模块接单片机P2.7口
sbit rightTracking = P2^6;    //右边轮子的循迹模块接单片机P2.6口


void main()
{
	initTime0();
	initTime1();
	UartInit();
	while(1)
	{
		//下方小车两个模块都能反射回来红外,输出低电平,灯亮,直走
     
		if(leftTracking==0 && rightTracking==0)
		{
			speedRight = 25;
			speedLeft  = 25;
		}
		//上方小车左模块遇到黑线,红外被吸收,左模块输出高电平,右模块输出低电平,左转,反之右转
		if(leftTracking==1 && rightTracking==0)
		{
			speedLeft = 10;
			speedRight = 40;
		}
		
		if(leftTracking==0 && rightTracking==1)
		{
			speedLeft = 40;
			speedRight = 10;
		}
		
		if(leftTracking==1 && rightTracking==1)
		{
			speedLeft = 0;
			speedRight = 0;
		}
	}
}

3.4调试优化,使小车循迹

  • 调试思路

  冲出地图可以通过增大左右轮转向差数来解决,直线走不直可以通过调剂走直线左右轮速度变量控制左右轮速。

  • 调试结果

  一、地图长这样,和2.4的赛道有所区别,这版赛道我采用纸板,上面用毛笔蘸墨水画出赛道即可。

“无限交互,全新驾驶体验!智能语音小车,与您共同开创未来出行。”#51单片机最终项目《智能语音小车》【中】,学习嵌入式笔记,嵌入式硬件,单片机,51单片机,c语言,学习

  二、调试结果为设置小车直线行驶时左右轮速为35,拐弯轮速差为30。即可完美实现循迹。

  三、调试后的代码

#include "motor.h"
#include "delay.h"
#include "uart.h"
#include "time0.h"
#include "time1.h"
#include "reg52.h"

extern char speedRight;
extern char speedLeft;

sbit leftTracking = P2^7;     //左边轮子的循迹模块接单片机P2.7口
sbit rightTracking = P2^6;    //右边轮子的循迹模块接单片机P2.6口


void main()
{
	initTime0();
	initTime1();
	UartInit();
	while(1)
	{
		//下方小车两个模块都能反射回来红外,输出低电平,灯亮,直走
     
		if(leftTracking==0 && rightTracking==0)
		{
			speedRight = 35;
			speedLeft  = 35;
		}
		//上方小车左模块遇到黑线,红外被吸收,左模块输出高电平,右模块输出低电平,左转,反之右转
		if(leftTracking==1 && rightTracking==0)
		{
			speedLeft = 10;
			speedRight = 40;
		}
		
		if(leftTracking==0 && rightTracking==1)
		{
			speedLeft = 40;
			speedRight = 10;
		}
		
		if(leftTracking==1 && rightTracking==1)
		{
			speedLeft = 0;
			speedRight = 0;
		}
	}
}

4.跟随小车

4.1跟随小车实现原理

  • 跟随小车实现原理和1.1一样,只不过传感器探头朝外。
  • 跟随小车跟随原理:左边跟随模块能返回红外,输出低电平,右边不能返回,输出高电平,说明物体在左边,需要左转右边跟随模块能返回红外,输出低电平,左边不能返回,输出高电平,说明物体在右边,需要右转

4.2跟随小车代码实现

  • 基于根据循迹原理实现循迹功能代码编写工程开发
  • 跟随算法实现代码
while(1)
{
    //小车两个模块都能反射回来红外,输出低电平,灯亮,直走

    if(leftFollow==0 && rightFollow==0)
    {
        goFront();
    }

    //右边跟随模块能返回红外,输出低电平,左边不能返回,输出高电平,说明物体在右边,需要右转
    if(leftFollow==1 && rightFollow==0)
    {
        goRight();`
    }

    //左边跟随模块能返回红外,输出低电平,右边不能返回,输出高电平,说明物体在左边,需要左转
    if(leftFollow==0 && rightFollow==1)
    {
        goLeft();
    }

    if(leftFollow==1 && rightFollow==1)
    {
        stop();
    }
}
  • 主C文件代码
#include "motor.h"
#include "delay.h"
#include "reg52.h"

//sbit leftTracking = P2^7;     //左边轮子的循迹模块接单片机P2.7口
//sbit rightTracking = P2^6;    //右边轮子的循迹模块接单片机P2.6口

sbit leftFollow = P2^5;     //左边轮子的跟随模块接单片机P2.5口
sbit rightFollow = P2^4;    //右边轮子的跟随模块接单片机P2.4口

void main()
{
	while(1)
	{
		//小车两个模块都能反射回来红外,输出低电平,灯亮,直走
     
		if(leftFollow==0 && rightFollow==0)
		{
			goFront();
		}
		
		//右边跟随模块能返回红外,输出低电平,左边不能返回,输出高电平,说明物体在右边,需要右转
		if(leftFollow==1 && rightFollow==0)
		{
			goRight();`
		}
		
		//左边跟随模块能返回红外,输出低电平,右边不能返回,输出高电平,说明物体在左边,需要左转
		if(leftFollow==0 && rightFollow==1)
		{
			goLeft();
		}
		
		if(leftFollow==1 && rightFollow==1)
		{
			stop();
		}
	}
}

4.3跟随红外模块使用注意事项

  • 在关闭窗帘的室内使用,因为阳光中有部分红外线,会导致模块异常,实验结果出错。

5.摇头测距小车01_舵机和超声波封装

5.1摇头测距小车01_舵机和超声波封装核心思路

  • 分别建立hc04.chc04.hdelay.cdelay.hsg90.csg90.h文件
  • 拷贝以上相应代码去相应文件
  • 在主C文件和其他文件中调用相应的.h文件。

  注:此程序基于感应开关盖垃圾桶项目_实现距离感应开盖工程开发

5.2分别建立hc04.c,hc04.h,delay.c,delay.h,sg90.c,sg90.h文件

  • 建立的文件如下:

“无限交互,全新驾驶体验!智能语音小车,与您共同开创未来出行。”#51单片机最终项目《智能语音小车》【中】,学习嵌入式笔记,嵌入式硬件,单片机,51单片机,c语言,学习

5.3拷贝以上相应代码去相应文件

  1. hc04.c对应代码为
#include "reg52.h"
#include "delay.h"

sbit Trig     = P2^3;  //超声波测距的控制Trig接单片机2.3口
sbit Echo     = P2^2;  //超声波测距的控制Echo接单片机2.2口

void startHC()     //给超声波模块控制为Trig一个10us的触发信息
{
	Trig = 0;
	Trig = 1;
	Delay10us();
	Trig = 0;
}

void initTime1() //设置定时器T0为16位模式,从0开始数数,不忙启动定时器
{
	TMOD &= 0x0F;
	TMOD |= 0x10;
	TL1   = 0;
	TH1   = 0;
}

double getDistance()
{
	double time;
	
	//重新给初值,重新计时
		TL1 = 0;
		TH1 = 0;
	
	//1.Trig ,给Trig端口至少10us的高电平
	startHC();
	//2.Echo信号,由低电平跳转到高电平,表示开始发送波
	while(Echo == 0);
	//     波发出去的那一下,开始启动定时器
	TR1 = 1;  //启动定时器T0
	//3.Echo,由高电平跳转回低电平,表示波回来了
	while(Echo == 1);
	//     波回来的那一下,我们开始停止定时器,计算出中间经过多少时间
	TR1 = 0;  //关闭定时器
	time = ((TH1 * 256) + TL1)*1.085; //单位为us。
	/*
		256的含义:
		对于十进制数2向左移一位位20,相当于乘以10
		那么对于二进制数2向左移移一位,相当于乘以2。移动8位,乘以2的8次方256
	*/
	//4.距离 = 速度 (340m/s)* 时间/2
	//dis = 340m/s = 34000cm/s = 34cm/ms = 0.034cm/us
	//dis = 0.034 * time/2; <==> 0.017*time;
		
  return (0.017 * time);
}
  1. hc04.h对应代码为


void initTime1();

double getDistance();
  1. delay.c对应代码为

void Delay10us()		//@11.0592MHz 软件延时10us
{
	unsigned char i;

	i = 2;
	while (--i);
}

void Delay2000ms()		//@11.0592MHz 软件延时2秒
{
	unsigned char i, j, k;

	i = 15;
	j = 2;
	k = 235;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}

void Delay150ms()		//@11.0592MHz
{
	unsigned char i, j, k;

	i = 2;
	j = 13;
	k = 237;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}

void Delay300ms()		//@11.0592MHz  软件延时300毫秒
{
	unsigned char i, j, k;

	i = 3;
	j = 26;
	k = 223;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}
  1. delay.h对应代码为


void Delay10us();

void Delay2000ms();

void Delay150ms();

void Delay300ms();
  1. sg90.c对应代码为
#include "reg52.h"
#include "delay.h"

sbit D5       = P3^7;  //根据原理图D5 led灯接单片机3.7口
sbit D6       = P3^6;  //根据原理图D6 led灯接单片机3.6口
sbit sg90_con = P1^1; //sg90舵机PWM控制线接单片机P1.1口,用于模拟PWM波形。

char cnt = 0;     //记录爆表次数
char angle;       //记录舵机角度变量

void initTime0() //初始化定时器T0
{
	//1.设置定时器为T0,16位模式
	TMOD &= 0xF0;
	TMOD |= 0x01;
	
	//2.设置初值,定时0.5毫秒
	TL0 = 0x33;
	TH0 = 0xFE;
	
	//3.启动定时器,开始计时
	TR0 = 1; //TR0为启动定时器标志,值为1启动定时器
	TF0 = 0;
	//4.打开定时器0的中断 赋1打开
	ET0 = 1;
	//5.打开总中断EA  赋1打开
	EA  = 1;
}

void initSG90_0() //SG90舵机初始化函数。
{
	sg90_con = 1; //单片机上电,给sg90舵机控制线一个高电平。
	angle    = 1; //给角度控制变量初始化为0度,因为0.5毫秒的高电平PWM波为0度,angle = 1;时定时器刚好定时0.5毫秒
  cnt      = 0; //初始化爆表变量
}



void openCoverLight()  //开盖灯的状态
{
	D5 = 0;
	D6 = 1;
}

void closeCoverLight() //关盖垃圾桶的状态
{
	D5 = 1;
	D6 = 0;
}

void openCoverDustbin() //垃圾桶开盖函数
{
	angle    = 3;       //舵机开盖
	cnt      = 0;
	Delay2000ms();
}

void closeCoverDustbin()//垃圾桶关盖函数
{
	angle    = 1;       //舵机关盖
	cnt      = 0;
	Delay150ms();
}

void Time0Handler() interrupt 1 //定时器T0中断函数,中断号为interrupt 1
{
	cnt++;
	//重新给定时器赋初值,定时0.5毫秒
	TL0 = 0x33;
	TH0 = 0xFE;
	
	//判读记录爆表变量cnt的值是否小于角度变量的值,小于继续给sg90舵机控制线高电平,大于等于则给低电平
	if(cnt < angle)
	{
     sg90_con = 1;
	}
	else
	{
     sg90_con = 0;
	}
	//判断cnt是否加到40,定时是否20毫秒PWM波形周期
	if(cnt == 40)
	{
	   cnt = 0;     //定时到20豪秒,cnt从0开始加
		 sg90_con = 1;//定时到20豪秒,重新给舵机控制线一个高电平
	}
}
  1. sg90.h对应代码为


void initTime0(); //初始化定时器T0


void initSG90_0(); //SG90舵机初始化函数。


void openCoverLight();  //开盖灯的状态


void closeCoverLight(); //关盖垃圾桶的状态


void openCoverDustbin(); //垃圾桶开盖函数


void closeCoverDustbin();//垃圾桶关盖函数

5.4在主C文件和其他文件中调用相应的.h文件。

  1. 主C文件中调用的.h文件
#include "reg52.h"
#include "hc04.h"
#include "delay.h"
#include "sg90.h"
  1. hc04.c文件中调用的.h文件
#include "reg52.h"
#include "delay.h"
  1. sg90.c文件中调用的.h文件
#include "reg52.h"
#include "delay.h"
  1. 主C文件代码
#include "reg52.h"
#include "hc04.h"
#include "delay.h"
#include "sg90.h"

/*
		时间:    2023年10月4日14:00:24
		程序功能:垃圾桶03实现距离感应开盖
		注意:一定要在魔术手中Output内勾选输出Hex文件,不然代码无效,执行其他代码。
*/


void main()
{
	
	double dis;
	
	Delay300ms();
	
	initTime0();
	initTime1();
	initSG90_0();
	
	while(1)
	{
		dis = getDistance();  //超声波测距
		if(dis < 10)
		{
			openCoverLight();  //开盖,D5亮
			openCoverDustbin();
		}
		else
		{
			closeCoverLight();  //关盖,D5灭
			closeCoverDustbin();
		}
	}
}

6.摇头测距小车02_实现疯狂摇头

6.1摇头测距小车02_实现疯狂摇头核心思路

  • 修改关盖函数closeCoverDustbin();sg90Right()。修改开盖函数openCoverDustbin();sg90Middle();
  • 增加sg90Left();函数
  • 主C文件修改初识位置为中间;while(1)死循环中给予适度延时调用sg90函数。

6.2修改关盖函数closeCoverDustbin();为sg90Right()。修改开盖函数openCoverDustbin();为sg90Middle();

  1. 修改关盖函数closeCoverDustbin();sg90Right();
修改前
void closeCoverDustbin()//垃圾桶关盖函数
{
	angle    = 1;       //舵机关盖
	cnt      = 0;
	Delay150ms();
}
修改后(去掉延时,不然在最终呈现时会影响结果)
void sg90Right()//垃圾桶关盖函数
{
	angle    = 1;       //舵机关盖
	cnt      = 0;
}
  1. 修改开盖函数openCoverDustbin();sg90Middle();
修改前
void openCoverDustbin() //垃圾桶开盖函数
{
	angle    = 3;       //舵机开盖
	cnt      = 0;
	Delay2000ms();
}
修改后(去掉延时,不然在最终呈现时会影响结果)
void sg90Middle() //垃圾桶开盖函数
{
	angle    = 3;       //舵机开盖
	cnt      = 0;
}

6.3增加sg90Left();函数

  1. 角度变量设置成5,sg90舵机转动180度。
  • 代码体现
void sg90Left()//
{
	angle    = 5;       //旋转180度   
	cnt      = 0;
}
  1. 在sg90.h文件中添加sg90左、右、中函数声明
void sg90Middle(); //垃圾桶开盖函数


void sg90Right();//垃圾桶关盖函数

void sg90Left();
  1. sg90.h文件代码。


void initTime0(); //初始化定时器T0


void initSG90_0(); //SG90舵机初始化函数。


void openCoverLight();  //开盖灯的状态


void closeCoverLight(); //关盖垃圾桶的状态


void sg90Middle(); //垃圾桶开盖函数


void sg90Right();//垃圾桶关盖函数

void sg90Left();

6.4主C文件修改初识位置为中间;while(1)死循环中给予适度延时调用右、中、左、中、sg90函数。

  1. 初始化位置为中间后延时1秒。
sg90Middle();
Delay1000ms();
  1. while(1)死循环中给予600ms延时调用右、中、左、中、sg90函数最为适合。
while(1)
{
    sg90Right();
    Delay600ms();
    sg90Middle();
    Delay600ms();
    sg90Left();
    Delay600ms();
    sg90Middle();
    Delay600ms();
}
  1. 主C文件代码
#include "reg52.h"
#include "hc04.h"
#include "delay.h"
#include "sg90.h"

/*
		时间:    2023年10月4日14:00:24
		程序功能:垃圾桶03实现距离感应开盖
		注意:一定要在魔术手中Output内勾选输出Hex文件,不然代码无效,执行其他代码。
*/


void main()
{
	
	Delay300ms();
	initTime0();
	initTime1();
	sg90Middle();
	Delay1000ms();
	while(1)
	{
		sg90Right();
		Delay600ms();
		sg90Middle();
		Delay600ms();
		sg90Left();
		Delay600ms();
		sg90Middle();
		Delay600ms();
	}
}
  1. delay.c和delay.h文件代码
#include "intrins.h"

void Delay10us()		//@11.0592MHz 软件延时10us
{
	unsigned char i;

	i = 2;
	while (--i);
}

void Delay2000ms()		//@11.0592MHz 软件延时2秒
{
	unsigned char i, j, k;

	i = 15;
	j = 2;
	k = 235;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}

void Delay150ms()		//@11.0592MHz
{
	unsigned char i, j, k;

	i = 2;
	j = 13;
	k = 237;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}

void Delay300ms()		//@11.0592MHz  软件延时300毫秒
{
	unsigned char i, j, k;

	i = 3;
	j = 26;
	k = 223;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}

void Delay600ms()		//@11.0592MHz
{
	unsigned char i, j, k;

	_nop_();
	i = 5;
	j = 52;
	k = 195;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}

void Delay1000ms()		//@11.0592MHz
{
	unsigned char i, j, k;

	_nop_();
	i = 8;
	j = 1;
	k = 243;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}


void Delay10us();

void Delay2000ms();

void Delay150ms();

void Delay300ms();

void Delay600ms();

void Delay1000ms();

7.摇头测距小车03_测距摇头

7.1摇头测距小车03_测距摇头核心思路

  在主C文件中设计算法,前方距离小于35厘米就左右两边都测一下距离。距离大于35厘米就前进。

7.2算法设计思路

  1. 在主C文件的主函数中一上电就让测距模块在中间位置,在while(1)死循环中先测正前面的距离,距离大于35厘米就直走,距离小于35厘米就左边测,然后右边测,最后回中。具体请看程序代码。
sg90Middle();
Delay1000ms();
while(1)
{
    disMiddle = getDistance();      //先测中间
    if(disMiddle > 35)  						//如果中间距离大于35厘米就前进
    {
        //前进
    }
    else                						//否则就摇头
    {
        sg90Left();       						//转左边
        disLeft = getDistance();      //测左边
        Delay600ms();                 //等待600毫秒

        sg90Middle();                 //转中间
        Delay600ms();                 //等待600毫秒

        sg90Right();                  //转右边
        disRight = getDistance();     //测右边
        Delay600ms();                 //等待600毫秒
    }
    sg90Middle();                   //回到中间
    Delay600ms();                   //等待600毫秒
}

  这样的代码验证后,sg90Middle();//回到中间 Delay600ms();//等待600毫秒;这两句会出现舵机在中间抽搐。原因是当距离大于35厘米时会一直调用转向中间函数,但此时处于中间位置,所以会出现抽搐。
  解决办法为定义标志位来控制

  1. 建立转向位置位置变量算法思路:定义转向位置变量宏,当初始化为中间的时候记录中间位置,在while(1)死循环内进行位置判断,如果位置不是中间位置,就回到中间,在中间位置就不做任何操作。
#define MIDDLE 0    //定义中间位置宏
#define RIGHT  1    //定义右边位置宏
#define LEFT   2    //定义左边位置宏

sg90Middle();
dir = MIDDLE;                     //记录中间位置
Delay1000ms();
disMiddle = getDistance();      //先测中间
		
if(dir != MIDDLE)               //方向不在中间会中
{
    sg90Middle();                 //回中
    Delay600ms();
    dir = MIDDLE;                 //软件初始化
}
if(disMiddle > 35)  						//如果中间距离大于35厘米就前进
{
    //前进
}
else                						//否则就摇头
{
    sg90Left();       						//转左边
    disLeft = getDistance();      //测左边
    Delay600ms();                 //等待600毫秒

    sg90Middle();                 //转中间
    Delay600ms();                 //等待600毫秒

    sg90Right();                  //转右边
    disRight = getDistance();     //测右边
    dir      = RIGHT;             //记录末位置
    Delay600ms();                 //等待600毫秒
}

7.3完整主C文件代码

#include "reg52.h"
#include "hc04.h"
#include "delay.h"
#include "sg90.h"

#define MIDDLE 0    //定义中间位置宏
#define RIGHT  1    //定义右边位置宏
#define LEFT   2    //定义左边位置宏

/*
		时间:    2023年10月4日14:00:24
		程序功能:垃圾桶03实现距离感应开盖
		注意:一定要在魔术手中Output内勾选输出Hex文件,不然代码无效,执行其他代码。
*/


void main()
{
	double disMiddle;                 //中间距离变量
	double disLeft;                   //左边距离变量
	double disRight;                  //右边距离变量
	
	char dir;                         //转头标志位变量
	
	Delay300ms();
	initTime0();
	initTime1();
	sg90Middle();
	dir = MIDDLE;                     //记录中间位置
	Delay1000ms();
	//Delay600ms();
	while(1)
	{
		disMiddle = getDistance();      //先测中间
		
		if(dir != MIDDLE)               //方向不在中间会中
		{
			sg90Middle();                 //回中
			Delay600ms();
			dir = MIDDLE;                 //软件初始化
		}
		if(disMiddle > 35)  						//如果中间距离大于35厘米就前进
		{
			//前进
		}
		else                						//否则就摇头
		{
			sg90Left();       						//转左边
			disLeft = getDistance();      //测左边
			Delay600ms();                 //等待600毫秒
			
			sg90Middle();                 //转中间
			Delay600ms();                 //等待600毫秒
			
			sg90Right();                  //转右边
			disRight = getDistance();     //测右边
			dir      = RIGHT;             //记录末位置
			Delay600ms();                 //等待600毫秒
		}
		/*
		验证后,这两句会出现舵机在中间抽搐。
		原因是当距离大于35厘米时会一直调用转向中间函数,但此时处于中间位置,所以会出现抽搐。
		解决办法为定义标志位来控制
		sg90Middle();                   //回到中间
		Delay600ms();                   //等待600毫秒
		*/
	}
}

8.摇头测距小车04_摇头测距和行驶bug调试

8.1摇头测距小车04_摇头测距和行驶核心思路

  • 在7.3代码中添加判断转向代码
  • 在转向代码中操控LED灯已验证是否进入判断执行方便调试

8.2在7.3代码中添加判断转向代码

  1. 转向思路:当左边的距离小于右边的距离时,右转一段距离,使用延时函数,延时300毫秒适合我的地图。当右边的距离小于左边的距离时,左转一段距离,也延时300毫秒。
  2. 转向代码
if(disLeft < disRight)        //左边小于右边,向右转
{
    goRight();
    Delay300ms();                 
    stop();
}

if(disRight < disLeft )        //左边大于右边,向左转
{
    goLeft();
    Delay300ms();                 
    stop();
}
  1. 地图照片

“无限交互,全新驾驶体验!智能语音小车,与您共同开创未来出行。”#51单片机最终项目《智能语音小车》【中】,学习嵌入式笔记,嵌入式硬件,单片机,51单片机,c语言,学习

8.3在转向代码中操控LED灯已验证是否进入判断执行方便调试

  1. 声明LED灯地址
右转指示灯
sbit D1 = P3^7;
左转指示灯
sbit D2 = P3^6;
  1. 主C文件主函数一开始就初识化指示灯
初始化熄灭
D1 = 1;
D2 = 1;
  1. 左右转功能中使用LED灯
if(disLeft < disRight)        //左边小于右边,向右转
{
    D1 = 0;
    goRight();
    Delay300ms();                 
    //Delay200ms();
    stop();
    D1 = 1;

}

if(disRight < disLeft )        //左边大于右边,向左转
{
    D2 = 0;
    goLeft();
    Delay300ms();                 
    //Delay200ms();
    stop();
    D2 = 1;
}

8.4 Bug调试

  1. Bug1:小车直冲撞墙,不左右转也不后退。

  解决办法:添加后退代码,距离小于10厘米就后退一定距离,指导距离大于10厘米。

if(disMiddle > 30)  						//如果中间距离大于30厘米就前进
{
    //前进
    goFront();
}
else if(disMiddle < 10)
{
    goBack();
}
else  
  1. Bug2:小车待在原地转头

  解决办法:我开始以为是超声波测距没有测到数据,于是对美测到距离的情况做判断,可是实验后并没有解决待在原地不动转头。也没有进入代码程序,我想是不是左右距离一样导致无法判断,可是相应代码后还未解决。于是我试了很久很久,浪费了很多时间。终于我看到电机转动开始不怎么转了,想到可能是电池没电了。于是我用充电宝供电,一下子就又可以使用了。而且算法没一点矛盾。

  所以在调试小车时一定要记得检测电源是否电量充足。

结束语

  很高兴您能看到这里,点个赞再走呗。谢谢您啦!!!文章来源地址https://www.toymoban.com/news/detail-834466.html

到了这里,关于“无限交互,全新驾驶体验!智能语音小车,与您共同开创未来出行。”#51单片机最终项目《智能语音小车》【中】的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 美格智能推出全新一代5G R16车规级模组,助力智能驾驶时代加速到来

    3月14日,在 Embedded World 2023德国纽伦堡国际嵌入式系统展 会上,全球领先的无线通信模组及解决方案提供商美格智能重磅推出 全新一代5G车规级C-V2X MA925系列模组 。此系列模组基于高通技术公司近期推出的 第二代骁龙 ® 汽车5G调制解调器及射频平台进行设计研发和生产 。该

    2024年02月11日
    浏览(50)
  • 基于LD3320的51智能遥控语音小车

    小车实物图  本实验基于51单片机和LD3320语音识别模块 小车能够实现遥控器直接控制,语音控制以及自动避障 涉及到的知识有:I/O口的配置(点亮led),定时器(循迹),串口通信(两个板子的连接),SPI同步通信(遥控器),中断(定时器中断和串口中断),PWM(循迹)

    2024年02月06日
    浏览(39)
  • 人工智能智能语音交互:让语音交互更智能

    作者:禅与计算机程序设计艺术 随着移动互联网、物联网、无人机、机器人技术等新型技术的出现,以及更多对话应用的出现,智能语音交互在当今社会越来越受到重视。最近几年,深度学习技术逐渐普及,为基于语音的智能系统的开发提供了巨大的助力,并取得了不错的成

    2024年02月10日
    浏览(59)
  • 运用全新空调插座秒变智能新体验

    最近台风肆虐,城市内涝等灾害频频发生;气候离不开环境,环境也离不开气候,在这两者之间,人类却成了第三者。 随手关灯,节约用电,是一种再普通不过的行为,然而10亿人在同一时间做同样的一件普通的事,人们心中激荡起强烈的情感共鸣,进而产生对人类命运和地

    2024年02月10日
    浏览(35)
  • 人工智能交互革命:探索ChatGPT的无限可能 第4章 ChatGPT-智能客服

    智能客服是一种利用人工智能技术,为客户提供在线服务和支持的解决方案。它能够通过自然语言处理、机器学习等技术,识别和理解客户的问题,并提供针对性的解决方案。智能客服可以通过多种渠道提供服务,包括网站、社交媒体、短信、电话等。 智能客服的发展可以追

    2023年04月25日
    浏览(60)
  • 基于51单片机的多功能智能语音循迹避障小车

    目录 一.功能介绍及硬件准备 二.电机控制及调速 三.小车循迹方案 四.跟随功能实现 五.测速功能实现 六.OLED显示车速 七.摇头避障功能实现 八.SU-03T语音模块介绍 九.语音切换小车模式+OLED显示模式 这是一款基于51单片机开发的智能小车,通过这篇文章我会记录下来开发这款小

    2024年02月03日
    浏览(46)
  • 智能家居(2)智能体验与智能交互

    随着信息和网络技术的发展,可以网络连接的电子电器产品越来越丰富,智能家居、智慧园区、智能汽车等智能控制系统和产品应用越来越广泛。 智能交互终端是智能控制系统的人机交互接口,既是实现智能功能的重要载体,也是用户感受智能化体验的关键节点。现有智能家

    2023年04月08日
    浏览(98)
  • 智能语音交互流程

    用该文来讲解语音全流程涉及到的技术,整体语音涉及的交互流程如下图: 语音唤醒指的是通过预设的即可将智能硬件从休眠状态唤醒,来执行相应操作。 传统模式 唤醒方式:先唤醒设备,等硬件设备反馈后(提示音或亮灯),用户认为设备被唤醒了,再发出语音控

    2024年02月11日
    浏览(43)
  • 智能语音交互中的人机交互场景分析改进

    引言 1.1. 背景介绍 智能语音交互技术作为人工智能领域的重要分支之一,近年来取得了长足的发展。语音交互已经成为了人们日常生活和工作中不可或缺的一部分,尤其是在疫情期间,语音助手成为了人们获取信息、交流互动的重要工具。为了更好地提升智能语音交互的用户

    2024年02月09日
    浏览(38)
  • 基于语音交互的智能翻译系统

    作者:禅与计算机程序设计艺术 引言 1.1. 背景介绍 随着全球化的发展,跨文化交流日益频繁,语言障碍和文化差异成为了影响人们交流的一个重要因素。为了更好地解决这一问题,人工智能翻译技术逐渐得到了普及和发展。 1.2. 文章目的 本文旨在介绍一种基于语音交互的智

    2024年02月14日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包