项目四 智能小车

项目四 智能小车

实现串口通信控制小车

通过手机的蓝牙助手软件,给蓝牙发送信息,蓝牙接收到信息再通过串口传给单片机。

//串口中断函数
void uart_func() interrupt 4
{
	char tmp;
	//定义一个局部静态变量
	static char i = 0;
	if(RI)
	{
		//清空标志位
		RI = 0;
		tmp = SBUF;
		if(tmp == 'b' || tmp == 'g' || tmp == 'r' || tmp == 'l')
		{
			i = 0;
		}
		*(buffer+i) = tmp;
		i++;
		if((*buffer) == 'b' && (*(buffer+1)) == 'a')
		{
			make = 1;
			myMemset(buffer);
		}
		if((*buffer) == 'g' && (*(buffer+1)) == 'o')
		{
			make = 2;
			myMemset(buffer);
		}
		if((*buffer) == 'r' && (*(buffer+1)) == 'i')
		{
			make = 3;
			myMemset(buffer);
		}
		if((*buffer) == 'l' && (*(buffer+1)) == 'e')
		{
			make = 4;
			myMemset(buffer);
		}
		
		if(i == 12)
		{
			i = 0;
		}
	}
	if(TI);
}

51单片机串口接收到数据后进行检索,当收到想要的字符串后,会将标志位make进行修改,在main函数中会对make变量进行操作。

main函数

switch(make)
		{
			//make = 1 表示后退
			case 1:
				CarBack();
				Delay30ms();
				make = 0;
				break;
			//make = 2 表示前进
			case 2:
				CarGo();
				Delay30ms();
				make = 0;
				break;
			//make = 3 表示右转
			case 3:
				CarRight();
				Delay30ms();
				make = 0;
				break;
			//make = 4 表示右转
			case 4:
				CarLeft();
				Delay30ms();
				make = 0;
				break;
			//否则小车不动
			default :
				CarStop();
				break;
		}

串口有数据进来,首先会进入串口中断函数,对make的值进行修改,出来中断函数后,会进入main函数,根据make的值,对电机进行操作。

1.小车PWM调速

通过PWM进行调速就是对输出功率的一个改变,假设一个周期是20ms,有15ms的时间是前进,5ms的时间时间停止,那么输出的功率就是全功率的3/4。从而导致速度下降,因为只有5ms的停止时间,由于惯性的原因,必不会看到小车停止,只是速度降低。

void time0_func() interrupt 1
{
	//cnt记录进来的次数
	cnt++;
	//重新装初值 5ms进来一次
	TL0 = 0x00;
	TH0 = 0xEE;
	if(cnt < speed)
	{
		//小车前进
		CarGo();
	}
	else
	{
		//小车后退
		CarStop();
	}
	//进来4次为20ms 一个周期,进行下一个周期
	if(cnt == 4)
	{
		cnt = 0;
		CarGo();
	}
}

与控制舵机的当时类似

2.PWM对小车左右电机单独调速

与一下对小车两个轮子调速的方法类似,需要用到两个定时器同时工作(定时0和定时器1),定时器0负责控制左轮的速度,定时器1负责控制右轮的速度,两个轮子速度一快一慢从未实现小车的转弯。

循迹小车的实现

循迹模块的使用

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

总结就是,没有反射回来发出的红外线,输出就是高电平,灯灭。

循迹小车原理

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

总结就是,检测到黑线就输出高电平,灯灭。

image-20230116145439277

在左右循迹模块都输出低电平的时候,小车直走,当左侧的循迹模块输出为高点平时(碰到黑线),向左转弯,右侧的循迹模块输出为高电平时(碰到黑线),小车向右转弯。

代码

sbit leftSensor  = P1^4;
sbit rightSensor = P1^5;

while(1)
	{
		if(leftSensor == 1 && rightSensor == 1)
		{
			speedLeft = 0;
			speedRight = 0;
		}
		if(leftSensor == 1 && rightSensor == 0)
		{
			speedLeft= 2;
			speedRight = 4;
		}
		if(leftSensor == 0 && rightSensor == 1)
		{
			speedLeft = 4;
			speedRight = 2;
		}
		if(leftSensor == 0 && rightSensor == 0)
		{
			speedLeft = 4;
			speedRight = 4;
		}
	}

这里采用的是使用PWM波控制小车的转弯,实现让小车转弯更平滑。分别使用了定时器0和定时器1单独的控制小车的两个轮子。

跟随小车的实现

与循迹模块的原理是一样的,如果发送红外线返回来了,输出的是低电平,如果没有回来输出的是高电平。

当左边输出的高电平,右边输出的是低电平,说明右边有人,小车右转

当右边输出的高电平,左边输出的是低电平,说明左边有人,小车左转

小车测速

测速模块的原理

有遮挡、输出高电平。无遮挡、输出低电平。
轮子走一圈的周长是:3.14*6.5 cm
一圈内一共有20个小格子平均分布,也就是说轮子走一圈会产生20个脉冲
一个脉冲对应的是 3.14*6.5/20  = 1.0205cm 一个脉冲相当于走了大约1cm
那么只需要统计 1s 内单片机接收了多少个脉冲(下降沿) ,就可以计算1s内走的总路程是多少。

oled显示小车的速度

1.用取模软件得到要显示的字符
2.创建字符数组
3.可以用一个指针数组保存字符数组名,数组名就是数组首元素的地址
4.用指针数组访问字符数组中的各个元素,减少main函数的代码量
/*--  文字:  s  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=8x16   --*/
code char s1[8] = {0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00};
code char s2[8] = {0x00,0x33,0x24,0x24,0x24,0x24,0x19,0x00};

/*--  文字:  p  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=8x16   --*/
code char p1[8] = {0x80,0x80,0x00,0x80,0x80,0x00,0x00,0x00};
code char p2[8] = {0x80,0xFF,0x91,0x20,0x20,0x11,0x0E,0x00};

/*--  文字:  e  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=8x16   --*/
code char e1[8] = {0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00};
code char e2[8] = {0x00,0x1F,0x24,0x24,0x24,0x24,0x17,0x00};

/*--  文字:  e  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=8x16   --*/
code char e11[8] = {0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00};
code char e22[8] = {0x00,0x1F,0x24,0x24,0x24,0x24,0x17,0x00};

/*--  文字:  d  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=8x16   --*/
code char d1[8] = {0x00,0x00,0x80,0x80,0x80,0x90,0xF0,0x00};
code char d2[8] = {0x00,0x1F,0x20,0x20,0x20,0x10,0x3F,0x20};

/*--  文字:  :  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=8x16   --*/
code char sym1[8] = {0x00,0x00,0x00,0xC0,0xC0,0x00,0x00,0x00};
code char sym2[8] = {0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00};

char* pointArr1[6] = {s1,p1,e1,e11,d1,sym1};
char* pointArr2[6] = {s2,p2,e2,e22,d2,sym2};

*pointArr 就是 数组s1 的首元素的地址
**pointArr 是数组s1 的首元素

语音识别的实现

配置SU—03T语音模块网址 http://www.smartpi.cn/#/

在上面网址上配置好语音模块后,下载SDK,烧入语音模块即可。

接线方式:

  • B6 :接串口工具的TX
  • B7:接串口工具的RX

要注意下载SDK的路径不可以为中文

posted @ 2023-09-01 14:00  徐博正  阅读(34)  评论(0)    收藏  举报