基于ardunio和esp32的语音控制玩具“阎王点卯机”

一.项目介绍

本项目是一款语音控制玩具,核心功能为通过用户的语音控制实现圆盘转动与音乐播放功能,具体功能演示如下:这就是完全的课设,完全的抽象,完全的,我!!_哔哩哔哩_bilibili

本项目主要由三大模块组成,分别是语音识别模块、电机模块、mp3模块。下面将分别介绍三大模块并附上代码

二.语音识别模块

我们的语音识别模块使用的芯片是ASR-PRO,搭配软件天问block使用。该软件支持图形化编程,操作简便,易于上手。当然也可以直接进行编程,以下为代码

#include "asr.h"
extern "C"{ void * __dso_handle = 0 ;}
#include "setup.h"

uint32_t snid;
void ASR_CODE();

//{speak:小蝶-清新女声,vol:4,speed:10,platform:haohaodada}
//{playid:10001,voice:欢迎使用语音助手,用启动唤醒我。}
//{playid:10002,voice:再见}

/*描述该功能...
*/
void ASR_CODE(){
  set_state_enter_wakeup(30000);
  switch (snid) {
   case 1:
    digitalWrite(4,1);
    digitalWrite(3,0);
    digitalWrite(2,0);
    digitalWrite(5,0);
    break;
   case 2:
    digitalWrite(3,1);
    digitalWrite(4,0);
    digitalWrite(2,0);
    digitalWrite(5,0);
    break;
   case 3:
    digitalWrite(2,1);
    digitalWrite(3,0);
    digitalWrite(4,0);
    digitalWrite(5,0);
    break;
  }
  switch (snid) {
   case 4:
    digitalWrite(4,1);
    digitalWrite(3,0);
    digitalWrite(2,0);
    digitalWrite(5,0);
    break;
   case 5:
    digitalWrite(3,1);
    digitalWrite(4,0);
    digitalWrite(2,0);
    digitalWrite(5,0);
    break;
   case 6:
    digitalWrite(2,1);
    digitalWrite(3,0);
    digitalWrite(4,0);
    digitalWrite(5,0);
    break;
  }
  switch (snid) {
   case 7:
    digitalWrite(4,1);
    digitalWrite(3,0);
    digitalWrite(2,0);
    digitalWrite(5,0);
    break;
   case 8:
    digitalWrite(3,1);
    digitalWrite(4,0);
    digitalWrite(2,0);
    digitalWrite(5,0);
    break;
   case 9:
    digitalWrite(2,1);
    digitalWrite(3,0);
    digitalWrite(4,0);
    digitalWrite(5,0);
    break;
  }
  switch (snid) {
   case 10:
    digitalWrite(4,1);
    digitalWrite(3,0);
    digitalWrite(2,0);
    digitalWrite(5,0);
    break;
   case 11:
    digitalWrite(3,1);
    digitalWrite(4,0);
    digitalWrite(2,0);
    digitalWrite(5,0);
    break;
   case 12:
    digitalWrite(2,1);
    digitalWrite(3,0);
    digitalWrite(4,0);
    digitalWrite(5,0);
    break;
  }
  switch (snid) {
   case 13:
    digitalWrite(5,1);
    delay(26);
    digitalWrite(5,0);
    break;
  }

}

void hardware_init(){
  vol_set(5);
  vTaskDelete(NULL);
}

void setup()
{
  //{ID:0,keyword:"唤醒词",ASR:"启动",ASRTO:"已启动"}
  //{ID:1,keyword:"命令词",ASR:"科比",ASRTO:"在呢"}
  //{ID:4,keyword:"命令词",ASR:"牢大",ASRTO:"哈哈"}
  //{ID:2,keyword:"命令词",ASR:"丁真",ASRTO:"我在"}
  //{ID:5,keyword:"命令词",ASR:"你是哪个生的",ASRTO:"一"}
  //{ID:3,keyword:"命令词",ASR:"坤坤",ASRTO:"来了"}
  //{ID:6,keyword:"命令词",ASR:"蔡徐坤",ASRTO:"哇哇"}
  //{ID:13,keyword:"命令词",ASR:"下一首",ASRTO:"收到"}
  setPinFun(4,FIRST_FUNCTION);
  pinMode(4,output);
  setPinFun(3,FIRST_FUNCTION);
  pinMode(3,output);
  setPinFun(2,FIRST_FUNCTION);
  pinMode(2,output);
  setPinFun(5,FIRST_FUNCTION);
  pinMode(5,output);
  digitalWrite(4,0);
  digitalWrite(3,0);
  digitalWrite(2,0);
  digitalWrite(5,0);
}

需要注意的一点是,该芯片对语音指令自带语音回复功能,按照代码中所写,当用户说出“牢大”时,该芯片会回复“哈哈”,但这个回复显然不是我们想要的。在功能演示中,当用户说出“牢大”时,语音回复是科比的经典语音“man!”。要实现这一点并不困难,只需要对语音回复的音频文件进行替换即可,详细教程如下:

注意,用于替换的音频文件需要自己录制

三.电机模块

我们使用的电机是28BYJ4步进电机,其优点是不需要功放,直接用esp32芯片上的5V引脚就可以驱动。当然,更重要的原因是本产品中电机的负载较小,28BYJ4步进电机完全能够驱动,如果再后续改进中负载增加了,28BYJ4步进电机可能就不好用了,就必须替换为功率更大的接功放的电机了。本产品中电机实现的功能是接收到对应的语音信号后,逆时针或顺时针旋转120度,将对应的人物带到用户面前,因此在编程时需要添加一个位置变量,以便判断当前是哪个人物在前,并据此作出反应。以下为电机的代码

#include <Stepper.h>
// 设置步进电机旋转一圈是多少步
const int stepsPerRevolution = 100;   
int a=1;
  //这里特别注意 ,后面4个参数分别是驱动板上的 IN1 , IN3 , IN2 , IN4 
Stepper myStepper = Stepper(stepsPerRevolution, 27, 26, 25, 33);
void setup() {
  pinMode(32, INPUT_PULLDOWN);
  pinMode(34, INPUT_PULLDOWN);  // 设置34引脚为输入模式
  pinMode(35, INPUT_PULLDOWN);  // 设置35引脚为输入模式
  //设置转速
  myStepper.setSpeed(120); 
  Serial.begin(115200);
  }
void loop() {
  if(a==1)
  {
   if (digitalRead(34) == HIGH)
    {
     myStepper.step(683);
     a=2;
     delay(50);
    }
    if (digitalRead(35) == HIGH)
    {
     myStepper.step(-683);
     a=3;
     delay(50);
    }
  }
   if(a==2)
    {
    if (digitalRead(35) == HIGH)
    {
     myStepper.step(683);
     a=3;
     delay(50);
    }
   if (digitalRead(32) == HIGH)
    {
     myStepper.step(-683);
     a=1;
     delay(50);
    }
   }
  if(a==3)
  {
   if (digitalRead(32) == HIGH)
    {
     myStepper.step(683);
     a=1;
     delay(50);
    }
   if (digitalRead(34) == HIGH)
    {
     myStepper.step(-683);
     a=2;
     delay(50);
    }
   }
  }

四.mp3模块

mp3模块使用的是DF mini player与一个0.5w的喇叭,注意如果没有喇叭的话单靠一个DF mini player是没法发出声音的,选择0.5w的喇叭也是因为它功率小,不需要接功放,而且对本产品来说这个小喇叭的音量也是完全够用了。

mp3模块主要实现的功能是放歌与切歌(其实还可以加上暂停,但是我们由于比较懒所以没加),其功能有点类似于一个智能音响。在本产品中我们总共准备了9首歌,其中丁真4首,坤坤3首,牢大2首。实际切歌时并不是在9首歌之间来回切,而是分成三人的三个小曲库,每个人只在自己的曲库里切,这样避免了丁真在前却播放着牢大的歌这种情况的出现。

mp3模块由另一个esp32芯片控制(不是控制电机的那个芯片)按说一个esp32芯片完全足以同时控制电机和mp3了,但由于我们的代码编写有些问题,放在一个芯片上功能没法实现,不过这个问题通过调整代码应该可以解决。

以下为mp3的代码

#include "Arduino.h"
#include "SoftwareSerial.h"
#include "DFRobotDFPlayerMini.h"
int dingzhen[]={1,4,5,6};
int d=0;
int kun[]={3,7,8};
int k=0;
int laoda[]={2,9};
int l=0;

SoftwareSerial mySerial(16, 17); // RX, TX
DFRobotDFPlayerMini myPlayer;

void setup() {
  Serial.begin(9600);
  mySerial.begin(9600);
  pinMode(2, INPUT);
  pinMode(15, INPUT_PULLDOWN);
  pinMode(13, INPUT_PULLDOWN);
  pinMode(12, INPUT_PULLDOWN);
  if (!myPlayer.begin(mySerial)) {
    Serial.println(F("Unable to begin:"));
    Serial.println(F("1.Please recheck the connection!"));
    Serial.println(F("2.Please insert the SD card!"));
    while(true);
  }
  Serial.println(F("DFPlayer Mini online."));
}

void loop() {
  myPlayer.volume(20); // 设置音量为 30
  Serial.println("Attempting to play music...");
  if(digitalRead(15)==HIGH)
  {
   myPlayer.play(dingzhen[d]); // 播放音乐文件编号为 1
   for (int i = 1; i <= 100; i--) 
    {
       delay(10);
       if(digitalRead(13)==HIGH)
       i=200;
       if(digitalRead(12)==HIGH)
       i=200;
       if (digitalRead(2)==HIGH)
       {
        delay(15);
        if (digitalRead(2)==HIGH)
        {
          if(d<3)
          d=d+1;
          else
          d=0;
          i=200;
        }
       }
       

    }
  }
  if(digitalRead(13)==HIGH)
  {
   myPlayer.play(kun[k]); // 播放音乐文件编号为 1
   for (int i = 1; i <= 100; i--) 
    {
       delay(10);
       if(digitalRead(15)==HIGH)
       i=200;
       if(digitalRead(12)==HIGH)
       i=200;
       if (digitalRead(2)==HIGH)
       {
        delay(15);
        if (digitalRead(2)==HIGH)
        {
          i=200;
          if(k<2)
          k=k+1;
          else
          k=0;
        }
       }
       

    }
  }
  if(digitalRead(12)==HIGH)
  {
   myPlayer.play(laoda[l]); // 播放音乐文件编号为 1
   for (int i = 1; i <= 100; i--) 
    {
       delay(10);
       if(digitalRead(13)==HIGH)
       i=200;
       if(digitalRead(15)==HIGH)
       i=200;
       if (digitalRead(2)==HIGH)
       {
        delay(15);
        if (digitalRead(2)==HIGH)
        {
          i=200;
          if(l<1)
          l=l+1;
          else
          l=0;
        }
       }
       

    }
  }
}

注意,要让mp3播放音乐,首先要用SD卡读卡器(跟U盘差不多,插入电脑USB口即可操作)将音频文件储存在SD卡中,将SD卡中的歌曲编好序号(如1号歌曲命名为0001)之后,再将SD卡插入mp3即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值