• STC89C51基础及项目第15天:小车测速、添加语言识别控制


    1. 小车测速的原理(281.126)

    测速模块

    在这里插入图片描述

    • 用途:
      • 广泛用于电机转速检测,脉冲计数,位置限位等。
    • 逻辑:
      • 有遮挡,输出高电平;无遮挡,输出低电平
    • 接线
      • VCC 接电源正极 3.3 - 5V
      • GND 接电源负极
      • DO TTL开关信号输出
      • AO 此模块不起作用

    测试原理和单位换算

    • 轮子走一圈经过一个周长,C = 2 x 3.14 x 半径 = 3.14 x 直径(6.5cm)
    • 对应的码盘也转了一圈。码盘有20个格子,每经过一个格子,会遮挡(高电平)和不遮挡(低电平)
    • 那么一个脉冲就是走了 3.14 x 6.5 cm /20 = 1.0205cm
    • 定时器可以设计成一秒,统计一秒内的脉冲数,一个脉冲就是 1cm
    • 假设一秒有 80 脉冲,那么就是 80cm/s

    2. 小车测速代码实现(282.127)

    • 代码(20./11. 测速数据通过串口发送到上位机01)
    #include "motor.h"
    #include "delay.h"
    #include "uart.h"
    #include "reg52.h"
    #include "timer.h"
    
    
    sbit speedIO = P3^2;		   //外部中断0
    unsigned int speedCnt = 0; //统计格子,脉冲次数
    extern unsigned int speed; //速度
    extern char signal;			   //主程序1s后可以发速度数据的信号
    
    void Ex0Init(){
    	EX0 = 1;//允许中断
    	//EA = 1;在串口初始化函数中已经打开了总中断
    	IT0 = 1;//外部中断的下降沿触发
    }
    
    void main(){
    	Timer0Init();
    	UartInit();//串口相关初始化
    	Ex0Init(); //外部中断初始化
    
    	while(1){
    		if(signal){//定时器1s到点,把signal置一,主程序发送速度
    			SendString("speed:");
    			SendByte(speed);//速度发出去//用sendByte不合理
    			signal = 0;//清0
    		}
    	}
    }
    
    void speedHelper() interrupt 0{//下降沿触发,即轮子转的时候产生高电平再到低电平//外部中断处理函数
    	speedCnt++;//码盘转动了一个格子
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • SendByte(speed) 并不合理,应该这么做:
      在这里插入图片描述

    3. 小车测速代码验证和BUG修改(283.128)

    • 代码(20./11. 测速数据通过串口发送到上位机02)
    #include "motor.h"
    #include "delay.h"
    #include "uart.h"
    #include "reg52.h"
    #include "timer.h"
    #include "stdio.h"
    
    sbit speedIO = P3^2;		   //外部中断0
    unsigned int speedCnt = 0; //统计格子,脉冲次数
    extern unsigned int speed; //速度
    extern char signal;			   //主程序发速度数据的信号
    char speedMes[24];  			 //主程序发速度数据的字符串缓冲区
    
    void Ex0Init(){
    	EX0 = 1;//允许中断
    	//EA = 1;在串口初始化函数中已经打开了总中断
    	IT0 = 1;//外部中断的下降沿触发
    }
    
    void main(){
    	Timer0Init();
    	UartInit();//串口相关初始化
    	Ex0Init(); //外部中断初始化
    
    	while(1){
    		if(signal){//定时器1s到点,把signal置一,主程序发送速度
    			sprintf(speedMes,"speed:%d cm/s",speed);//字符串拼装,speed的值格式化为字符串,写入speedMes字符串缓冲区
    			SendString(speedMes);//速度发出去
    			signal = 0;//清0
    		}
    	}
    }
    
    void speedHelper() interrupt 0{//下降沿触发,即轮子转的时候产生高电平再到低电平//外部中断处理函数
    	speedCnt++;//码盘转动了一个格子
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    4. OLED二次开发为了显速度(284.129)

    • 代码(20./12. OLED代码二次开发)
    #include "reg52.h"
    #include "intrins.h"
    #include "OLED.h"
    
    void main(){
    	Oled_Init();
    	Oled_Clear();
    	Oled_Show_Str(2,2,"speed:35cm/s");
    	
    	while(1);//不让程序结束
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    5. 蓝乐控制且OLED和蓝牙显示速度(285.130)

    • 代码(20./13. 蓝牙测速并本地显示的小车)
    #include "motor.h"
    #include "delay.h"
    #include "uart.h"
    #include "reg52.h"
    #include "timer.h"
    #include "stdio.h"
    #include "OLED.h"
    
    
    sbit speedIO = P3^2;		   //外部中断0
    unsigned int speedCnt = 0; //统计格子,脉冲次数
    extern unsigned int speed; //速度
    extern char signal;			   //主程序发速度数据的信号
    char speedMes[24];  			 //主程序发速度数据的字符串缓冲区
    
    void Ex0Init(){
    	EX0 = 1;//允许中断
    	//EA = 1;在串口初始化函数中已经打开了总中断
    	IT0 = 1;//外部中断的下降沿触发
    }
    
    void main(){
    	Timer0Init();
    	UartInit();//串口相关初始化
    	Ex0Init(); //外部中断初始化
    	Oled_Init();
      Oled_Clear();
    	while(1){
    		if(signal){//定时器1s到点,把signal置一,主程序发送速度
    			sprintf(speedMes,"speed:%d cm/s",speed);//字符串拼装,speed的值格式化为字符串,写入speedMes字符串缓冲区
    			SendString(speedMes);//速度发出去
    			signal = 0;//清0
    			Oled_Show_Str(2,2,speedMes);
    		}
    	}
    }
    
    void speedHelper() interrupt 0{//下降沿触发,即轮子转的时候产生高电平再到低电平//外部中断处理函数
    	speedCnt++;//码盘转动了一个格子
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    6. wifi控制小车并发送速度(286.131)

    • 代码(20./14. wifi测速并本地显示的小车)
    #include "motor.h"
    #include "delay.h"
    #include "uart.h"
    #include "reg52.h"
    #include "timer.h"
    #include "stdio.h"
    #include "OLED.h"
    #include "esp8266.h"
    
    sbit speedIO = P3^2;		   //外部中断0
    unsigned int speedCnt = 0; //统计格子,脉冲次数
    extern unsigned int speed; //速度
    extern char signal;			   //主程序发速度数据的信号
    char speedMes[24];  			 //主程序发速度数据的字符串缓冲区
    //4 发送数据
    code char sendData [] = "AT+CIPSEND=0,6\r\n";
    
    void Ex0Init(){
    	EX0 = 1;//允许中断
    	//EA = 1;在串口初始化函数中已经打开了总中断
    	IT0 = 1;//外部中断的下降沿触发
    }
    
    void main(){
    	Timer0Init();
    	UartInit();//串口相关初始化
    	
    	Delay1000ms();//给espwifi模块上电时间
    	initWifi_AP();//初始化wifi工作在ap模式
    	waitConnect();//等待客户端的连接
    	
    	Ex0Init();    //外部中断初始化
    	Oled_Init();  //oled初始化
      Oled_Clear(); //OLED清屏
    	while(1){
    		if(signal){//定时器1s到点,把signal置一,主程序发送速度		
    			SendString(sendData);//4 发送数据
    			Delay1000ms();
    			sprintf(speedMes,"speed:%d cm/s",speed);//字符串拼装,speed的值格式化为字符串,写入speedMes字符串缓冲区
    			SendString(speedMes);//速度发出去
    			signal = 0;//清0
    			Oled_Show_Str(2,2,speedMes);
    		}
    	}
    }
    
    void speedHelper() interrupt 0{//下降沿触发,即轮子转的时候产生高电平再到低电平//外部中断处理函数
    	speedCnt++;//码盘转动了一个格子
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49

    7. 4g模块控制小车(287.132)

    • 代码不做修改,直接复制蓝牙测速小车
    • 4g 模块只要做好内网穿透外网透传就可以了
    • 代码(20./15. 4g模块控制小车)

    8. 非特定语音识别方案介绍(~.133)

    • SU-03T(还有 LD3320)
    • 购买地址:https://item.taobao.com/item.htm?spm=a1z09.2.0.0.4c9d2e8d7NyISY&id=660663988887&_u=nbdq6ut5ec8
      在这里插入图片描述
    • 此语音模块不需编程,不需二次开发:通过厂家给的网站配置后即可使用,傻瓜式操作
    • 想要稍微开发点语音相关代码,LD3320 模块需要二次开发,根据厂家给的源码并二次开发添加识别词条

    9. SU-03T语音模块的配置使用(~.134)

    1. 进入官网,注册并登陆

      • http://www.smartpi.cn/#/
    2. 创建产品

      • 其他产品、纯离线方案、SU-03T、名称、中文、下一步
        在这里插入图片描述
    3. Pin脚配置

      • A25-A27 改为默认高电平
        在这里插入图片描述
    4. 唤醒词自定义和唤醒回复配置
      在这里插入图片描述

    5. 命令词自定义
      1)“基础信息”配置
      在这里插入图片描述
      在这里插入图片描述

      2)“控制详情”配置:添加控制
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述

    3)“识别灵敏度”配置:中
    在这里插入图片描述
    6. 发音人配置
    在这里插入图片描述
    7. 其他配置
    在这里插入图片描述
    8. 发布版本
    在这里插入图片描述
    9. 半小时左右后下载sdk固件
    在这里插入图片描述
    在这里插入图片描述

    10. SU-03T固件烧录并语音识别测试(288.135)

    • 提前做 语言模块和 ttl 的接线:
      • B7 引脚 接 串口工具 RXD
      • B6 引脚 接 串口工具 TXD
      • GND 接 串口工具 GND
      • VCC 接 串口工具 5V
    1. 将上节课生成的文件解压
      在这里插入图片描述
    2. 将解压后的文件夹放至非中文路径下、以管理员身份打开 “UniOneUpdateTool.exe” 文件
      在这里插入图片描述
    3. 将 usb-ttl 插入电脑接口
      在这里插入图片描述
    4. 打开软件,选择镜像文件 “uni_app_release_update.bin”
      在这里插入图片描述
    5. 下电至 OFF
      在这里插入图片描述
    6. 点“烧录”
      在这里插入图片描述
    7. 上电至 ON
      在这里插入图片描述
    8. 开始烧录
      在这里插入图片描述
    9. 下载完成,烧录结束
      在这里插入图片描述
    10. 即可进行语音测试

    11. 语音识别切换小车循迹避障跟随且OLED显示状态(289.136)

    • 代码(20./16. 语音识别切换小车寻迹避障跟随并oled显示)
    #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 XJ 3
    #define GS 4
    #define BZ 5
    #define ST 6
    
    sbit A25 = P1^5;
    sbit A26 = P1^6;
    sbit A27 = P1^7;
    
    sbit leftSensorXJ = 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(leftSensorXJ == 0 && rightSensorXJ == 0){//左右都反射回来,都低电平,直走,灯都亮
    		goForward();
    	}
    	
    	if(leftSensorXJ == 1 && rightSensorXJ == 0){//左边没反射回来,左高电平,左转,右灯亮
    		goLeft();
    	}	
    	
    	if(leftSensorXJ == 0 && rightSensorXJ == 1){//右边没反射回来,右高电平,右转,左灯亮
    		goRight();
    	}
    		
    	if(leftSensorXJ == 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;
    		Delay300ms();
    	}
    		disMiddle = getDistance();
    			
    		if(disMiddle > 35){
    				//前进
    			goForward();
    		}else if(disMiddle < 10){
    			goBack();
    		}else{
    			//停止
    			stop();
    			//sg左转 测左边距离
    			sgLeft();
    			Delay300ms();
    			disLeft = getDistance();
    				
    			sgMiddle();
    			Delay300ms();
    				
    			//sg右转 测右边距离
    			sgRight();
    			dir = RIGHT;
    			Delay300ms();
    			disRight = getDistance();
    				
    			if(disLeft < disRight){
    				goRight();
    				Delay150ms();
    				stop();
    			}
    			if(disLeft > disRight){
    				goLeft();
    				Delay150ms();
    				stop();
    			}
    		}
    }
    
    void main(){
    	int mark = 0;
    	
    	Timer0Init();//定时器0初始化(为舵机)
    	Timer1Init();//定时器1初始化(为超声波测距)
    	sgMiddle();  //舵机初始化位置(避障)
    	Delay2000ms();
    	dir = MIDDLE;
    
    	Oled_Init(); //OLED初始化
    	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();
    			}
    		}
    		//满足stop的条件
    		if(A25 == 0 && A26 == 0 && A27 == 0){
    			if(mark != ST){
    				Oled_Clear();
    				Oled_Show_Str(2,2,"-----STOP----");
    				mark = ST;
    				stop();
    			}
    		}
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162

    12. 效果演示(290.137)

  • 相关阅读:
    Spring 源码(11)Spring Bean 的创建过程(2)
    微信小程序标题栏封装
    java毕业设计宠物领养饲养交流管理平台Mybatis+系统+数据库+调试部署
    Linux文件和目录管理
    win11右键菜单显示更多的设置方法
    网络安全(黑客)—0基础学习手册
    爬虫-(4)
    122. 买卖股票的最佳时机 II
    文件批量重命名 Renamer 最新中文 for mac
    免费,C++蓝桥杯等级考试真题--第5级
  • 原文地址:https://blog.csdn.net/Jaci133/article/details/133751871