B44 - Based on stm32 bluetooth intelligent voice recognition classification and broadcast trash can

Task

Topic: Based on stm32 Bluetooth intelligent voice recognition, classification and broadcast of trash bins.
The functions are as follows:

  1. Voice recognition automatically sorts garbage according to the instructions issued by the user
  2. According to the type of garbage, the type of garbage is broadcast in real time
  3. Drive the corresponding servo to rotate according to the type of garbage (the simulated trash can is opened, and it will automatically reset in ten seconds, and the simulated trash can will be closed)
  4. The OLED display shows the status of the four trash cans in real time
  5. The Bluetooth app can control the switch of the trash can and display four trash can states at the same time

Effect

insert image description here
insert image description here

insert image description here

schematic diagram

insert image description here
insert image description here

instruction encoding

insert image description here
insert image description here

speech recognition module

Introduction

LU-ASR01 is a low-cost, low-power, small-volume, high-performance offline speech recognition system. This system integrates voice recognition, voice reply, IO control (multi-signal output), serial port output, temperature and humidity broadcasting and other functions. The speech recognition rate within 10 meters can reach 98%, far exceeding other modules such as LD3320.
LU-ASR01 basic parameters:
Module model: LU-ASRO1 size: 36mmx36mm
I0 port: There are 8 IOs, which are "IO1~lO8". Among them, I01, I02, I03, I04, IO5, and IO6 can output PWM signals, and can also be used as ordinary IOs. IO7 and IO8 are ordinary IOs, which can output high and low levels, pulse signals, and servo signals. There is a serial port output TX pin, which can output character or hexadecimal data. One DHT sensor pin can be connected to DHT11 temperature and humidity sensor or DS18B20 temperature sensor [6], which can realize voice control and broadcast the current temperature and humidity Standby power consumption: 10mA Power supply
range
: 3.6-5.8V, generally use 5V power supply, the power supply current is greater than 500mA
Operating temperature: -20°C~80°C
Speaker parameters: 8 ohms, 3W power

insert image description here

code design

insert image description here

drive

#ifndef __Lu_ASR01_H
#define __Lu_ASR01_H

#include "stm32f10x.h"
#include "Def_config.h"

#define ASR01_Buffer_Length 50
#define ASR01_Length 5

typedef struct
{
    
    
	char ASR01_Rec_Buffer[ASR01_Buffer_Length];
	ENUM_JUDGE isGetData;		//是否获取到数据
	ENUM_JUDGE isParseData;	//是否解析完成
	char ASR01[ASR01_Length];		//字符串形式存储
	ENUM_JUDGE isUsefull;		//信息是否有效
} _ASR01Data;

extern _ASR01Data ASR01_Data;

void ASR01_RecHandle(u8 Res);
void ASR01_Clear_Data(void);
void parseASR01Buffer(void);

#endif 


#include "Lu_ASR01.h"
#include <string.h>
#include <stdio.h>
#include "SG90.h"


_ASR01Data ASR01_Data;
char  ASR01_RX_BUF[ASR01_Buffer_Length]; //接收缓冲,最大ASR01_Buffer_Length个字节.末字节为换行符 
u8 point2 = 0;
void ASR01_RecHandle(u8 Res)
{
    
    
	if(Res == '$')
	{
    
    
		point2 = 0;	
	}
	ASR01_RX_BUF[point2++] = Res;
	if(Res == '@' || point2 >2)									   
	{
    
    
		memset(ASR01_Data.ASR01_Rec_Buffer, 0, ASR01_Buffer_Length);      //清空
		memcpy(ASR01_Data.ASR01_Rec_Buffer, ASR01_RX_BUF, point2); 	//保存数据
		ASR01_Data.isGetData = TRUE; 
		point2 = 0;
		memset(ASR01_RX_BUF, 0, ASR01_Buffer_Length);      //清空
	}		
	if(point2 >= ASR01_Buffer_Length)
	{
    
    
		point2 = ASR01_Buffer_Length;
	}	
}
u8 ASR01_Find(char *a)                   // 串口命令识别函数
{
    
     
    if(strstr(ASR01_Data.ASR01_Rec_Buffer,a)!=NULL)
	    return 1;
	else
		return 0;
}
void ASR01_Clear_Data(void)
{
    
    
	ASR01_Data.isGetData = FALSE;
	ASR01_Data.isParseData = FALSE;
	ASR01_Data.isUsefull = FALSE;
	memset(ASR01_Data.ASR01, 0, ASR01_Length);      //清空
	memset(ASR01_Data.ASR01_Rec_Buffer, 0, ASR01_Buffer_Length);      //清空
}
void parseASR01Buffer(void)
{
    
    
	if (ASR01_Data.isGetData)  //获得语音模块的数据 --- $1@   : $4@
	{
    
    
		ASR01_Data.isGetData = FALSE;
		if(ASR01_Find("$1@"))
		{
    
    
			ASR01_Data.isParseData = TRUE;
			ASR01_Data.isUsefull = TRUE;
			
			SG90_Control(1,ANGLE_90);  //控制舵机1 旋转90°
			SG90_Structure.is_num01_open = TRUE;
			printf("$O1@"); //OPEN1  --缩写O1  ---  输出--蓝牙模块--手机同步更改舵机状态
		}
		else if(ASR01_Find("$2@"))
		{
    
    
			ASR01_Data.isParseData = TRUE;
			ASR01_Data.isUsefull = TRUE;
			
			SG90_Control(2,ANGLE_90);			
			SG90_Structure.is_num02_open = TRUE;
			printf("$O2@");
		}
		else if(ASR01_Find("$3@"))
		{
    
    
			ASR01_Data.isParseData = TRUE;
			ASR01_Data.isUsefull = TRUE;
			
			SG90_Control(3,ANGLE_90);
			SG90_Structure.is_num03_open = TRUE;
			printf("$O3@");
		}
		else if(ASR01_Find("$4@"))
		{
    
      	
			ASR01_Data.isParseData = TRUE;
			ASR01_Data.isUsefull = TRUE;
			
			SG90_Control(4,ANGLE_90);
			SG90_Structure.is_num04_open = TRUE;
			printf("$O4@");
		}
		else
		{
    
    
			ASR01_Clear_Data(); //清空接收到的数据---数据帧无效
		}
	}
}





Servo module

Introduction

This design uses 4 steering gears to control the opening and closing of the trash can, all of which are SG90 steering gears. The steering gear is a kind of position (angle) servo drive, which is suitable for the closed-loop control execution module that needs to change and maintain the angle [13]. The steering gear is mainly composed of a motor, a potentiometer, a control circuit, a reduction gear set, a casing, and a steering wheel.

The cycle of the control signal of the steering gear is a 20ms pulse width modulation (PWM) signal, and the PWM signal has a linear change between 0.5 and 2.5ms and between 0 and 180°. The input signal of the steering gear is a PWM signal, which is modulated by PWM, and controls the rotation angle and direction of the steering gear according to different duty ratios.
insert image description here

In this design, the four pins PB8-PB11 of the STM32 single-chip microcomputer are used to input PWM signals for the steering gear to control the rotation angle of the steering gear so as to control the opening and closing of the trash can lid. Its working principle is: the four pins PB8-PB11 of the STM32 single-chip microcomputer are respectively connected to the input terminals of the four servos, and the PWM signal is generated by the timer to control the operation of the steering gear. The steering gear drive circuit has a built-in reference voltage, and the signal requirement is 20ms Period, 0.5ms width, by comparing the input signal with the reference voltage, the deviation result can be obtained, thus controlling the rotation angle of the external device. For example: when the voltage difference is positive, the motor rotates forward, when the voltage difference is negative, the motor rotates in the opposite direction, when the voltage difference is zero, the motor is in a static state, so as to achieve the purpose of driving the trash can lid switch.

drive

#ifndef __SG90_H
#define __SG90_H

#include "stm32f10x.h"
#include "Def_config.h"

#define SG90_RCC_APB2Periph_GPIOX  RCC_APB2Periph_GPIOB
#define SG90Num01_GPIOX_PinX  GPIO_Pin_8
#define SG90Num01_GPIOX       GPIOB

#define SG90Num02_GPIOX_PinX  GPIO_Pin_9
#define SG90Num02_GPIOX       GPIOB

#define SG90Num03_GPIOX_PinX  GPIO_Pin_10
#define SG90Num03_GPIOX       GPIOB

#define SG90Num04_GPIOX_PinX  GPIO_Pin_11
#define SG90Num04_GPIOX       GPIOB

//Turn_angle: 1---0度  2---45度 3---90 4--- 135度  5---180度     
typedef enum {
    
    
	ANGLE_0 = 1,
	ANGLE_45 = 2,
	ANGLE_90 = 3,
	ANGLE_135 = 4,
	ANGLE_180 = 5
}ENUM_ANGLE;

typedef struct {
    
    
	ENUM_JUDGE is_num01_start;  //启动
	ENUM_JUDGE is_num02_start;
	ENUM_JUDGE is_num03_start;
	ENUM_JUDGE is_num04_start;
	ENUM_ANGLE num01_angleX;  //转动角度
	ENUM_ANGLE num02_angleX;
	ENUM_ANGLE num03_angleX;
	ENUM_ANGLE num04_angleX;
	ENUM_JUDGE is_num01_finish;  //到达指定角度
	ENUM_JUDGE is_num02_finish;
	ENUM_JUDGE is_num03_finish;
	ENUM_JUDGE is_num04_finish;
	
	ENUM_JUDGE is_num01_open;
	ENUM_JUDGE is_num02_open;
	ENUM_JUDGE is_num03_open;
	ENUM_JUDGE is_num04_open;
}STRUCT_SG90;
extern STRUCT_SG90 SG90_Structure;

void SG90_Init(void);
void SG90_ControlAngleX(void);
void SG90_Control(u8 numX,ENUM_ANGLE angleX);

#endif


/******************************
SG90 舵机驱动程序
PB8 - PB11  四个舵机
******************************/
#include "SG90.h"
#include "led.h"
#include "bsp_timer3.h"  

void SG90_GPIO_Init(void)
{
    
    
	GPIO_InitTypeDef GPIO_InitStructure;
	/* GPIOx clock enable */
	RCC_APB2PeriphClockCmd(SG90_RCC_APB2Periph_GPIOX, ENABLE);
	GPIO_InitStructure.GPIO_Pin = SG90Num01_GPIOX_PinX | SG90Num02_GPIOX_PinX | SG90Num03_GPIOX_PinX | SG90Num04_GPIOX_PinX;  
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

	GPIO_Init(SG90Num01_GPIOX, &GPIO_InitStructure);
}
void SG90_Init(void)
{
    
    
	SG90_GPIO_Init();
	
	SG90_Structure.is_num01_start = FALSE;
	SG90_Structure.is_num02_start = FALSE;
	SG90_Structure.is_num03_start = FALSE;
	SG90_Structure.is_num04_start = FALSE;
	SG90_Structure.num01_angleX = ANGLE_0;
	SG90_Structure.num02_angleX = ANGLE_0;
	SG90_Structure.num03_angleX = ANGLE_0;
	SG90_Structure.num04_angleX = ANGLE_0;
	
	SG90_Structure.is_num01_open = FALSE;
	SG90_Structure.is_num02_open = FALSE;
	SG90_Structure.is_num03_open = FALSE;
	SG90_Structure.is_num04_open = FALSE;
	
	SG90_Structure.is_num01_finish = FALSE;
	SG90_Structure.is_num02_finish = FALSE;
	SG90_Structure.is_num03_finish = FALSE;
	SG90_Structure.is_num04_finish = FALSE;
	
	SG90_Control(1,ANGLE_0);
	SG90_Control(2,ANGLE_0);
	SG90_Control(3,ANGLE_0);
	SG90_Control(4,ANGLE_0);
}
u8 Counter_01 = 0;
#define PWM_Cycle 40            //40*500us  = 20ms	
u8 Duoji_WaitTime01=0;	
u8 Duoji_WaitTime02=0;	
u8 Duoji_WaitTime03=0;	
u8 Duoji_WaitTime04=0;	
#define Duoji_WaitTime_Max 36  //设置转动等待时间  36个信号周期---500us/1周期
STRUCT_SG90 SG90_Structure;
void SG90_ControlAngleX(void)  //uint16_t SG90NumX_GPIOX_PinX,ENUM_ANGLE angle
{
    
    
	Counter_01++;
	if(Counter_01>=PWM_Cycle)                   //一个周期20ms    //LED_Control(REVERSE);
	{
    
    
		Counter_01=0;	
		if(SG90_Structure.is_num01_start == TRUE)  
		{
    
    
			Duoji_WaitTime01++;
			if(Duoji_WaitTime01>Duoji_WaitTime_Max)
			{
    
    
				Duoji_WaitTime01=0;
				SG90_Structure.is_num01_finish = TRUE;
				
				SG90_Structure.is_num01_start = FALSE;
			}	
		}
		else
		{
    
    
			Duoji_WaitTime01=0;
//			SG90_Structure.is_num01_finish = FALSE;
		}
		
		if(SG90_Structure.is_num02_start == TRUE)  
		{
    
    
			Duoji_WaitTime02++;
			if(Duoji_WaitTime02>Duoji_WaitTime_Max)
			{
    
    
				Duoji_WaitTime02=0;
				SG90_Structure.is_num02_finish = TRUE;
				
				SG90_Structure.is_num02_start = FALSE;
			}	
		}
		else
		{
    
    
			Duoji_WaitTime02=0;
//			SG90_Structure.is_num02_finish = FALSE;
		}

		if(SG90_Structure.is_num03_start == TRUE)  
		{
    
    
			Duoji_WaitTime03++;
			if(Duoji_WaitTime03>Duoji_WaitTime_Max)
			{
    
    
				Duoji_WaitTime03=0;
				SG90_Structure.is_num03_finish = TRUE;
				
				SG90_Structure.is_num03_start = FALSE;
			}	
		}
		else
		{
    
    
			Duoji_WaitTime03=0;
//			SG90_Structure.is_num03_finish = FALSE;
		}

		if(SG90_Structure.is_num04_start == TRUE)  
		{
    
    
			Duoji_WaitTime04++;
			if(Duoji_WaitTime04>Duoji_WaitTime_Max)
			{
    
    
				Duoji_WaitTime04=0;
				SG90_Structure.is_num04_finish = TRUE;
				
				SG90_Structure.is_num04_start = FALSE;
			}	
		}
		else
		{
    
    
			Duoji_WaitTime04=0;
//			SG90_Structure.is_num04_finish = FALSE;
		}		
	}		
	if(SG90_Structure.is_num01_start == TRUE)
	{
    
    
		if(Counter_01 <= SG90_Structure.num01_angleX)
		{
    
    
			GPIO_SetBits(SG90Num01_GPIOX,SG90Num01_GPIOX_PinX);
		}
		else
		{
    
    
			GPIO_ResetBits(SG90Num01_GPIOX,SG90Num01_GPIOX_PinX);
		}
	}
	if(SG90_Structure.is_num02_start == TRUE)
	{
    
    
		if(Counter_01 <= SG90_Structure.num02_angleX)
		{
    
    
			GPIO_SetBits(SG90Num02_GPIOX,SG90Num02_GPIOX_PinX);
		}
		else
		{
    
    
			GPIO_ResetBits(SG90Num02_GPIOX,SG90Num02_GPIOX_PinX);
		}
	}
	if(SG90_Structure.is_num03_start == TRUE)
	{
    
    
		if(Counter_01 <= SG90_Structure.num03_angleX)
		{
    
    
			GPIO_SetBits(SG90Num03_GPIOX,SG90Num03_GPIOX_PinX);
		}
		else
		{
    
    
			GPIO_ResetBits(SG90Num03_GPIOX,SG90Num03_GPIOX_PinX);
		}
	}
	if(SG90_Structure.is_num04_start == TRUE)
	{
    
    
		if(Counter_01 <= SG90_Structure.num04_angleX)
		{
    
    
			GPIO_SetBits(SG90Num04_GPIOX,SG90Num04_GPIOX_PinX);
		}
		else
		{
    
    
			GPIO_ResetBits(SG90Num04_GPIOX,SG90Num04_GPIOX_PinX);
		}
	}
}
void SG90_Control(u8 numX,ENUM_ANGLE angleX)
{
    
    
	switch(numX)
	{
    
    
		case 1:
			SG90_Structure.is_num01_start = TRUE;
			SG90_Structure.is_num01_finish = FALSE;
			SG90_Structure.num01_angleX = angleX;
			while(SG90_Structure.is_num01_finish == FALSE);	
			time3_struct.Counter_01 = 0;
			time3_struct.is_5000MS_01Arrive = FALSE;
		break;
		case 2:
			SG90_Structure.is_num02_start = TRUE;
			SG90_Structure.is_num02_finish = FALSE;
			SG90_Structure.num02_angleX = angleX;
			while(SG90_Structure.is_num02_finish == FALSE);	
			time3_struct.Counter_02 = 0;
			time3_struct.is_5000MS_02Arrive = FALSE;
		break;
		case 3:
			SG90_Structure.is_num03_start = TRUE;
			SG90_Structure.is_num03_finish = FALSE;
			SG90_Structure.num03_angleX = angleX;
			while(SG90_Structure.is_num03_finish == FALSE);	
			time3_struct.Counter_03 = 0;
			time3_struct.is_5000MS_03Arrive = FALSE;
		break;
		case 4:
			SG90_Structure.is_num04_start = TRUE;
			SG90_Structure.is_num04_finish = FALSE;
			SG90_Structure.num04_angleX = angleX;
			while(SG90_Structure.is_num04_finish == FALSE);	
			time3_struct.Counter_04 = 0;
			time3_struct.is_5000MS_04Arrive = FALSE;
		break;
		default:break;
	}
}


main program source code

/*******************************************************************************

\* 文件名称:基于stm32蓝牙智能语音识别分类播报垃圾桶

\* 实验目的:1.

\* 2.

\* 程序说明:完整程序Q:277 227 2579;@: itworkstation@ hotmail.com

\* 日期版本:本项目分享关键细节,熟悉使用单片机的可做参考代码。完整讲解+源代码工程可联系获取,可定制。

*******************************************************************************/
/*******************************************************************************  
* 适配工程:最小系统板STM32C8T6镀金板
* 舵机占空比与运行角度的关系
0.5ms--------------0度;

1.0ms------------45度;

1.5ms------------90度;

2.0ms-----------135度;

2.5ms-----------180度;
*******************************************************************************/

/* Includes ------------------------------------------------------------------*/
#include "main.h"  
#include "SG90.h"
#include "bsp_timer4.h" 
#include "usart1.h"
#include "Lu_ASR01.h"
#include "usart2.h" 
#include "bsp_timer3.h" 
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
extern const unsigned char BMP1[];

/**
  * @说明     主函数
  * @参数     None 
  * @返回值   None
  */
STRUCT_NVICPriority NVICPriority_Structure;
void sysInit(void)
{
    
    
	/*---------------------初始化中断顺序,0:最优先---------------------*/
	NVICPriority_Structure.Tim4 = 1;  
	NVICPriority_Structure.Usart1 = 2;
	NVICPriority_Structure.Usart2 = 3;
	NVICPriority_Structure.Tim3 = 0;
	
	/*----------------------外设初始化,配置参数-------------------------------------*/
	TIM4_Init();  
	SG90_Init();
	USART1_Init();  
	USART2_Init();
	
	/*-----------------------舵机控制:归0------------------------------------*/
	SG90_Control(1,ANGLE_0);
	SG90_Control(2,ANGLE_0);
	SG90_Control(3,ANGLE_0);
	SG90_Control(4,ANGLE_0);
	
	LED_Init();
	
	/*------------------------屏幕初始,IO等-----------------------------------*/
	OLED_Init();
	LCD_Display();  //显示---欢迎界面
	Delay_ms(5000); //延时5S
	LCD_Menu = LCD_SHOWMESSAGE;LCD_refresh = TRUE;	//变换界面
	
	//			LED_Control(ON);
//			Delay_ms(5000);
//			LED_Control(OFF);
//			Delay_ms(5000);
	TIM3_Init();
}
int main(void)
{
    
    	
	sysInit();	
    while(1){
    
    				
		parseASR01Buffer(); 
		if (ASR01_Data.isUsefull)
		{
    
    
			ASR01_Data.isUsefull =  FALSE;
			LCD_refresh=TRUE; 				//屏幕同步刷新状态
		}
		if(SG90_Structure.is_num01_finish)  //舵机转动结束
		{
    
    
			if(time3_struct.is_5000MS_01Arrive) //5s标志位
			{
    
    
				time3_struct.is_5000MS_01Arrive = FALSE;
				SG90_Structure.is_num01_finish = FALSE;
				if(SG90_Structure.num01_angleX != ANGLE_0)  //若舵机角度不等于0°,说明在90°状态--
				{
    
    
					SG90_Control(1,ANGLE_0);  //舵机归0
					SG90_Structure.is_num01_open = FALSE;
					printf("$C1@");  //CLOSE1  -- 缩写C1  同步状态给手机
					LCD_refresh=TRUE; 	
				}
			}
		}
		if(SG90_Structure.is_num02_finish)
		{
    
    
			if(time3_struct.is_5000MS_02Arrive)
			{
    
    
				time3_struct.is_5000MS_02Arrive = FALSE;
				SG90_Structure.is_num02_finish = FALSE;
				if(SG90_Structure.num02_angleX != ANGLE_0)
				{
    
    
					SG90_Control(2,ANGLE_0);
					SG90_Structure.is_num02_open = FALSE;
					printf("$C2@");  //CLOSE2  -- 缩写C1
					LCD_refresh=TRUE; 	
				}
			}
		}
		if(SG90_Structure.is_num03_finish)
		{
    
    
			if(time3_struct.is_5000MS_03Arrive)
			{
    
    
				time3_struct.is_5000MS_03Arrive = FALSE;
				SG90_Structure.is_num03_finish = FALSE;
				if(SG90_Structure.num03_angleX != ANGLE_0)
				{
    
    
					SG90_Control(3,ANGLE_0);
					SG90_Structure.is_num03_open = FALSE;
					printf("$C3@");  //CLOSE3  -- 缩写C1
					LCD_refresh=TRUE; 	
				}
			}
		}
		if(SG90_Structure.is_num04_finish)
		{
    
    
			if(time3_struct.is_5000MS_04Arrive)
			{
    
    
				time3_struct.is_5000MS_04Arrive = FALSE;
				SG90_Structure.is_num04_finish = FALSE;
				if(SG90_Structure.num04_angleX != ANGLE_0)
				{
    
    
					SG90_Control(4,ANGLE_0);
					SG90_Structure.is_num04_open = FALSE;
					printf("$C4@");  //CLOSE4  -- 缩写C1
					LCD_refresh=TRUE; 	
				}
			}
		}
		LCD_Display();
    }     
}





Guess you like

Origin blog.csdn.net/qq_20467929/article/details/126137039