赞
踩
该智能小车具有循迹、跟随、避障三种模式,可以通过语音识别实现三种模式的切换,并且在oled显示屏显示当前模式。在循迹模式下,小车可以通过循迹模块跟随赛道中的黑线位置实时改变方向,并沿赛道前行;在跟随模式下,小车可以通过跟随模块实时跟随前方物体而移动;在避障模式下,小车利用超声波模块检测前方距离,并根据距离判断障碍物位置,并及时躲避前方障碍。
1.小车底盘套件
2.51开发板
3.电池盒(4节)
4.面包板
5.L9110s电机驱动模块
6.循迹模块(2个)
7.红外跟随模块(2个)
8.SU-03语音模块
9.OLED显示屏
10.超声波
11.sg-90舵机
12.杜邦线若干
•循迹模块介绍
当发射出的红外线没有被反射回来或被反射回来但强度不够大时,红外接收管一直处于关断状态,此时模块的输出端为高电平,指示二极管一直处于熄灭状态被检测物体出现在检测范围内时,红外线被反射回来且强度足够大,红外接收管饱和,此时模块的输出端为低电平,指示二极管被点亮。
总结就是一句话,有感应到黑线,D0输出高电平 ,灭灯。
•跟随模块介绍
左边跟随模块能返回红外,输出低电平,右边不能返回,输出高电平,物体在左边,需要左转;
右边跟随模块能返回红外,输出低电平,左边不能返回,输出高电平,物体在右边,需要右转。
•语音模块介绍
语音模块配置网址如下:
配置好以后先连接USB转TTL进行固件烧录 测试(SU-03T 的RX是B6 TX是B7 ),测试无误后即可接入开发板使用。
main.c
- #include "reg52.h"
- #include "hc04.h"
- #include "delay.h"
- #include "sg90.h"
- #include "motor.h"
- #include "Oled.h"
-
- #define MIDDLE 0
- #define LEFT 1
- #define RIGHT 2
-
- #define BZ 1
- #define XJ 2
- #define GS 3
- #define ST 4
-
- sbit A25 = P1^5;
- sbit A26 = P1^6;
- sbit A27 = P1^7;
-
- sbit leftSensoXJ = P2^7;
- sbit rightSensorXJ = P2^6;
-
- sbit leftSensorGS = P2^5;
- sbit rightSensorGS = P2^4;
-
- char dir;
- double disMiddle;
- double disLeft;
- double disRight;
-
- void xunjiMode()
- {
- if(leftSensoXJ == 0 && rightSensorXJ == 0){
- goForward();//前进
- }
- if(leftSensoXJ == 1 && rightSensorXJ == 0){
- goLeft();//左转
- }
- if(leftSensoXJ == 0 && rightSensorXJ == 1){
- goRight();//右转
- }
- if(leftSensoXJ == 1 && rightSensorXJ == 1){
- stop();//停止
- }
- }
-
- void gensuiMode()
- {
- if(leftSensorGS == 0 && rightSensorGS == 0){
- goForward();//前进
- }
- if(leftSensorGS == 1 && rightSensorGS == 0){
- goRight();//右转
- }
- if(leftSensorGS == 0 && rightSensorGS == 1){
- goLeft();//左转
- }
- if(leftSensorGS == 1 && rightSensorGS == 1){
- stop();//停止
- }
- }
-
- void bizhangMode()
- {
- if(dir != MIDDLE){
- sgMiddle();//中间
- dir = MIDDLE;
- Delay450ms();
- }
- disMiddle = get_distance();
- if(disMiddle > 35){
- //前进
- goForward();
- }else if(disMiddle < 10){
- goBack();
- }else{
- //停止
- stop();
- //测左边距离
- sgLeft();//左边
- Delay450ms();
- disLeft = get_distance();
-
- sgMiddle();//中间
- Delay450ms();
- //测右边距离
- sgRight();//右边
- dir = RIGHT;
- Delay450ms();
- disRight = get_distance();
-
- if(disLeft < disRight){
- goRight();
- Delay150ms();
- stop();
- }
- if(disLeft > disRight){
- goLeft();
- Delay150ms();
- stop();
- }
- }
- }
-
- void main()
- {
- int mark = 0;
-
- Time0Init();//舵机用
- Time1Init();//超声波用
-
- sgMiddle();//中间
- Delay450ms();
- Delay450ms();
- dir = MIDDLE;
-
- OLED_Init();
- OLED_Clear();
- Oled_Show_Str(2,2,"----Ready----");
-
- while(1){
- //循迹模式
- if(A25 == 0 && A26 == 1 && A27 == 1){
- if(mark != XJ){
- OLED_Clear();
- Oled_Show_Str(2,2,"----XunJi----");
- }
- mark = XJ;
- xunjiMode();
- }
- //跟随模式
- if(A25 == 1 && A26 == 0 && A27 == 1){
- if(mark != GS){
- OLED_Clear();
- Oled_Show_Str(2,2,"----GenSui----");
- }
- mark = GS;
- gensuiMode();
- }
- //避障模式
- if(A25 == 1 && A26 == 1 && A27 == 0){
- if(mark != BZ){
- OLED_Clear();
- Oled_Show_Str(2,2,"----BiZhang----");
- }
- mark = BZ;
- bizhangMode();
- }
- //停下
- if(A25 == 0 && A26 == 0 && A27 == 0){
- if(mark != ST){
- OLED_Clear();
- Oled_Show_Str(2,2,"----Stop----");
- }
- mark = ST;
- stop();
- }
-
- }
- }
hc04.c
- #include "reg52.h"
- #include "delay.h"
-
- sbit Trig = P2^3;
- sbit Echo = P2^2;
-
- void Time1Init()
- {
- TMOD &= 0x0F;
- TMOD |= 0x10;
- TH1 = 0;
- TL1 = 0;
- //设置定时器1工作模式1,初始值设定0开始数数,不着急启动定时器
- }
-
- void startHC()
- {
- Trig = 0;
- Trig = 1;
- Delay10us();
- Trig = 0;
- }
-
- double get_distance()
- {
- double time;
- //定时器数据清零,以便下一次测距
- TH1 = 0;
- TL1 = 0;
- //1. 给Trig一个至少10us高电平
- startHC();
- //2. 由低电平跳转到高电平,表示开始发送波
- while(Echo == 0);
- //波出去的那一下,开启定时器
- TR1 = 1;
- //3. 由高电平跳转到低电平,表示波回来了
- while(Echo == 1);
- //波回来的那一下,停止定时器
- TR1 = 0;
- //4. 计算出中间经过多少时间
- time = (TH1 * 256 + TL1)*1.085;//二进制1左移1位,变成10(2),相当于乘以2,左移8位,相当于乘以2的8次方=256
- //5. 距离=速度(340m/s)*时间/2
- return(time * 0.017);
- }
sg90.c
- #include "reg52.h"
- #include "delay.h"
-
- sbit D5 = P3^7;
- sbit D6 = P3^6;
- sbit sg90_con = P1^1;
-
- int jd;
- int cnt = 0;
-
- void Time0Init()
- {
- //1. 配置定时器0工作模式16位计时
- TMOD &= 0xF0;
- TMOD |= 0X01;
- //2. 给初值,定一个0.5ms出来
- TL0 = 0x33;
- TH0 = 0xFE;
- //3.打开定时器0中断
- ET0 = 1;
- //4.打开总中断EA
- EA = 1;
- //5. 开始计时
- TR0 = 1;
- TF0 = 0;
- }
-
- void sgMiddle()
- {
- //舵机开盖
- jd = 3;//90度,1.5ms高电平
- cnt = 0;
- }
-
- void sgLeft()
- {
- //舵机开盖
- jd = 5;//135度,2.5ms高电平
- cnt = 0;
- }
-
- void sgRight()
- {
- //舵机关盖
- jd = 1;//0度,0.5ms高电平
- cnt = 0;
- }
-
- void Time0Handler() interrupt 1
- {
- cnt++;//统计爆表次数
- TL0 = 0x33;//重新给初值
- TH0 = 0xFE;//重新给初值
-
- /*控制PWM波*/
- if(cnt < jd){
- sg90_con = 1;
- }else{
- sg90_con = 0;
- }
- /*统计爆表次数*/
- if(cnt == 40){//爆表了40次,经过了20ms
- cnt = 0;
- sg90_con = 1;
- }
- }
motor.c
- #include "reg52.h"
-
- sbit RightCon1A = P3^7;
- sbit RightCon1B = P3^3;
- sbit LeftCon1A = P3^4;
- sbit LeftCon1B = P3^5;
-
- void goForward()
- {
- LeftCon1A = 0;
- LeftCon1B = 1;
-
- RightCon1A = 0;
- RightCon1B = 1;
- }
-
- void goBack()
- {
- LeftCon1A = 1;
- LeftCon1B = 0;
-
- RightCon1A = 1;
- RightCon1B = 0;
- }
-
- void goLeft()
- {
- LeftCon1A = 0;
- LeftCon1B = 0;
-
- RightCon1A = 0;
- RightCon1B = 1;
- }
-
- void goRight()
- {
- LeftCon1A = 0;
- LeftCon1B = 1;
-
- RightCon1A = 0;
- RightCon1B = 0;
- }
-
- void stop()
- {
- LeftCon1A = 0;
- LeftCon1B = 0;
-
- RightCon1A = 0;
- RightCon1B = 0;
- }
Oled.c
- #include "reg52.h"
- #include "intrins.h"
- #include "Oledfont.h"
-
- sbit scl = P0^1;
- sbit sda = P0^3;
-
- void IIC_Start()
- {
- scl = 0;//防止雪花
- sda = 1;
- scl = 1;
- _nop_();
- sda = 0;
- }
-
- void IIC_Stop()
- {
- scl = 0;
- sda = 0;
- scl = 1;
- _nop_();
- sda = 1;
- _nop_();
- }
-
- char IIC_ACK()
- {
- char flag;
-
- sda = 1;//就在时钟脉冲9期间释放数据线
- _nop_();
- scl = 1;
- _nop_();
- flag = sda;
- _nop_();
- scl = 0;
- _nop_();
-
- return flag;
- }
-
- void IIC_Send_Byte(char dataSend)
- {
- int i;
-
- for(i=0;i<8;i++){
- scl = 0;//scl拉低,让sda做好数据准备
- sda = dataSend & 0x80;//1000 0000获得dataSend的最高位
- _nop_();//发送数据建立时间
- scl = 1;//scl拉高开始发送
- _nop_();
- scl = 0;//发送完毕,拉低
- _nop_();
- dataSend = dataSend << 1;
- }
- }
-
- void OLED_Write_Cmd(char dataCmd)
- {
- //1.START
- IIC_Start();
- //2.写入从机地址 b0111 1000 0x78
- IIC_Send_Byte(0x78);
- //3.ACK
- IIC_ACK();
- //4.cotrol byte:(0)(0)000000 写入命令 (0)(1)000000 写入数据
- IIC_Send_Byte(0x00);
- //5.ACK
- IIC_ACK();
- //6.写入指令/数据
- IIC_Send_Byte(dataCmd);
- //7.ACK
- IIC_ACK();
- //8.STOP
- IIC_Stop();
- }
-
- void OLED_Write_Data(char dataData)
- {
- //1.START
- IIC_Start();
- //2.写入从机地址 b0111 1000 0x78
- IIC_Send_Byte(0x78);
- //3.ACK
- IIC_ACK();
- //4.cotrol byte:(0)(0)000000 写入命令 (0)(1)000000 写入数据
- IIC_Send_Byte(0x40);
- //5.ACK
- IIC_ACK();
- //6.写入指令/数据
- IIC_Send_Byte(dataData);
- //7.ACK
- IIC_ACK();
- //8.STOP
- IIC_Stop();
- }
-
- void OLED_Init(void)
- {
- OLED_Write_Cmd(0xAE);//--display off
- OLED_Write_Cmd(0x00);//---set low column address
- OLED_Write_Cmd(0x10);//---set high column address
- OLED_Write_Cmd(0x40);//--set start line address
- OLED_Write_Cmd(0xB0);//--set page address
- OLED_Write_Cmd(0x81); // contract control
- OLED_Write_Cmd(0xFF);//--128
- OLED_Write_Cmd(0xA1);//set segment remap
- OLED_Write_Cmd(0xA6);//--normal / reverse
- OLED_Write_Cmd(0xA8);//--set multiplex ratio(1 to 64)
- OLED_Write_Cmd(0x3F);//--1/32 duty
- OLED_Write_Cmd(0xC8);//Com scan direction
- OLED_Write_Cmd(0xD3);//-set display offset
- OLED_Write_Cmd(0x00);//
- OLED_Write_Cmd(0xD5);//set osc division
- OLED_Write_Cmd(0x80);//
- OLED_Write_Cmd(0xD8);//set area color mode off
- OLED_Write_Cmd(0x05);//
- OLED_Write_Cmd(0xD9);//Set Pre-Charge Period
- OLED_Write_Cmd(0xF1);//
- OLED_Write_Cmd(0xDA);//set com pin configuartion
- OLED_Write_Cmd(0x12);//
- OLED_Write_Cmd(0xDB);//set Vcomh
- OLED_Write_Cmd(0x30);//
- OLED_Write_Cmd(0x8D);//set charge pump enable
- OLED_Write_Cmd(0x14);//
- OLED_Write_Cmd(0xAF);//--turn on oled panel
- }
-
- void OLED_Clear()
- {
- int i,j;
-
- for(i=0;i<8;i++){
- OLED_Write_Cmd(0xB0 + i);//page0--page7
- //每个page从0列
- OLED_Write_Data(0x00);
- OLED_Write_Data(0x10);
- //0到127列,依次写入0,每写入数据,列地址自动偏移
- for(j=0;j<128;j++){
- OLED_Write_Data(0);
- }
- }
- }
-
- void Oled_Show_Char(char row,char col,char oledChar){ //row*2-2
- unsigned int i;
- OLED_Write_Cmd(0xb0+(row*2-2)); //page 0
- OLED_Write_Cmd(0x00+(col&0x0f)); //low
- OLED_Write_Cmd(0x10+(col>>4)); //high
- for(i=((oledChar-32)*16);i<((oledChar-32)*16+8);i++){
- OLED_Write_Data(F8X16[i]); //写数据oledTable1
- }
-
- OLED_Write_Cmd(0xb0+(row*2-1)); //page 1
- OLED_Write_Cmd(0x00+(col&0x0f)); //low
- OLED_Write_Cmd(0x10+(col>>4)); //high
- for(i=((oledChar-32)*16+8);i<((oledChar-32)*16+8+8);i++){
- OLED_Write_Data(F8X16[i]); //写数据oledTable1
- }
- }
- /******************************************************************************/
- // 函数名称:Oled_Show_Char
- // 输入参数:oledChar
- // 输出参数:无
- // 函数功能:OLED显示单个字符
- /******************************************************************************/
- void Oled_Show_Str(char row,char col,char *str)
- {
- while(*str!=0){
- Oled_Show_Char(row,col,*str);
- str++;
- col += 8;
- }
- }
语音控制智能小车
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。