文章目录

任务效果原理图指令编码语音识别模块简介代码设计驱动

舵机模块简介驱动

主程序源代码

任务

题目:基于stm32蓝牙智能语音识别分类播报垃圾桶 实现功能如下:

语音识别根据使用者发出的指令自动对垃圾进行分类根据垃圾的种类实时播报垃圾的类型根据垃圾种类驱动对应的舵机进行转动(模拟垃圾桶打开,并在十秒钟自动复位,模拟垃圾桶关闭)OLED显示屏实时显示四种垃圾桶的状态蓝牙app可以控制垃圾桶开关,同时显示四种垃圾桶状态

效果

原理图

指令编码

语音识别模块

简介

LU-ASR01是一款低成本、低功耗、体积小、高性能的离线语音识别系统。本系统集成了语音识别、语音回复、IO控制(多信号输出)、串口输出、温湿度广播等功能。在10米范围内的语音识别率可达98%,远远超过了LD3320等其他模组。 LU-ASR01基本参数: 模块型号:LU-ASRO1尺寸:36mmx36mm I0口:有8路IO,分别是“IO1~lO8”。其中I01、I02、I03、I04、IO5、IO6可以输出PWM信号,也可以作为普通IO使用。IO7、IO8为普通IO,可以输出高低电平、脉冲信号、舵机信号。有一路串口输出TX管脚,可输出字符或16进制类型数据。一路DHT传感器管脚,可以接DHT11温湿度传感器或DS18B20温度传感器[6],可实现语音控制播报当时温湿度 待机功耗:10mA 供电范围:3.6-5.8V,一般使用5V供电,供电电流大于500mA 工作温度:-20℃~80°C 喇叭参数:8欧姆,3W功率

代码设计

驱动

#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

#include

#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(); //清空接收到的数据---数据帧无效

}

}

}

舵机模块

简介

本设计使用了4台舵机用来控制垃圾桶的开合,都是SG90型舵机。舵机是一种位置(角度)伺服驱动器,适用于那些需要角度不断变化并可以保持的闭环控制执行模块[13]。舵机主要由电机、电位器、控制电路、减速齿轮组、外壳、以及舵盘组成。

所述舵机的控制信号周期是一个20ms的脉宽调制(PWM)信号,在该PWM信号中,在0.5至2.5ms之间,在0至180°之间具有线性变化。舵机的输入信号为PWM信号,由PWM调制,并根据不同的占空比来控制舵机的转动角度和方向。

本设计选用STM32单片机的PB8-PB11四个引脚为舵机输入PWM信号来控制舵机旋转的角度从而实现控制垃圾桶盖的开关。其工作原理是:STM32单片机的PB8-PB11四个引脚分别连接4个舵机的输入端,通过定时器产生PWM信号控制舵机工作,舵机驱动电路内置基准电压,对信号的要求是20ms周期、0.5ms宽度,通过对比输入的信号与基准电压,可以得到偏差结果,从而控制了外部设备的转动角度。比如:电压差为正时,电机正向旋转,电压差为负时,电机反向旋转,电压差为零时,电机处于静止状态,从而达到带动垃圾桶盖开关的目的。

驱动

#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;

}

}

主程序源代码

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

\* 文件名称:基于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();

}

}

精彩链接

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: