B44 – 基于stm32蓝牙智能语音识别分类播报垃圾桶

文章目录

任务

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

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

效果

B44 - 基于stm32蓝牙智能语音识别分类播报垃圾桶
B44 - 基于stm32蓝牙智能语音识别分类播报垃圾桶

B44 - 基于stm32蓝牙智能语音识别分类播报垃圾桶

; 原理图

B44 - 基于stm32蓝牙智能语音识别分类播报垃圾桶
B44 - 基于stm32蓝牙智能语音识别分类播报垃圾桶

指令编码

B44 - 基于stm32蓝牙智能语音识别分类播报垃圾桶
B44 - 基于stm32蓝牙智能语音识别分类播报垃圾桶

; 语音识别模块

简介

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功率

B44 - 基于stm32蓝牙智能语音识别分类播报垃圾桶

; 代码设计

B44 - 基于stm32蓝牙智能语音识别分类播报垃圾桶

驱动

#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];
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)
    {
        ASR01_Data.isGetData = FALSE;
        if(ASR01_Find("$1@"))
        {
            ASR01_Data.isParseData = TRUE;
            ASR01_Data.isUsefull = TRUE;

            SG90_Control(1,ANGLE_90);
            SG90_Structure.is_num01_open = TRUE;
            printf("$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调制,并根据不同的占空比来控制舵机的转动角度和方向。

B44 - 基于stm32蓝牙智能语音识别分类播报垃圾桶

本设计选用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

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


#include "SG90.h"
#include "led.h"
#include "bsp_timer3.h"

void SG90_GPIO_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;

    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
u8 Duoji_WaitTime01=0;
u8 Duoji_WaitTime02=0;
u8 Duoji_WaitTime03=0;
u8 Duoji_WaitTime04=0;
#define Duoji_WaitTime_Max 36
STRUCT_SG90 SG90_Structure;
void SG90_ControlAngleX(void)
{
    Counter_01++;
    if(Counter_01>=PWM_Cycle)
    {
        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;

        }

        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;

        }

        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;

        }

        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;

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

主程序源代码


#include "main.h"
#include "SG90.h"
#include "bsp_timer4.h"
#include "usart1.h"
#include "Lu_ASR01.h"
#include "usart2.h"
#include "bsp_timer3.h"

extern const unsigned char BMP1[];

STRUCT_NVICPriority NVICPriority_Structure;
void sysInit(void)
{

    NVICPriority_Structure.Tim4 = 1;
    NVICPriority_Structure.Usart1 = 2;
    NVICPriority_Structure.Usart2 = 3;
    NVICPriority_Structure.Tim3 = 0;

    TIM4_Init();
    SG90_Init();
    USART1_Init();
    USART2_Init();

    SG90_Control(1,ANGLE_0);
    SG90_Control(2,ANGLE_0);
    SG90_Control(3,ANGLE_0);
    SG90_Control(4,ANGLE_0);

    LED_Init();

    OLED_Init();
    LCD_Display();
    Delay_ms(5000);
    LCD_Menu = LCD_SHOWMESSAGE;LCD_refresh = TRUE;

    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)
            {
                time3_struct.is_5000MS_01Arrive = FALSE;
                SG90_Structure.is_num01_finish = FALSE;
                if(SG90_Structure.num01_angleX != ANGLE_0)
                {
                    SG90_Control(1,ANGLE_0);
                    SG90_Structure.is_num01_open = FALSE;
                    printf("$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@");
                    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@");
                    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@");
                    LCD_refresh=TRUE;
                }
            }
        }
        LCD_Display();
    }
}

Original: https://blog.csdn.net/qq_20467929/article/details/126137039
Author: 小小工程员
Title: B44 – 基于stm32蓝牙智能语音识别分类播报垃圾桶

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/527187/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球