从零开始 DIY 智能家居 - 基于 ESP32 的智能语音合成播报模块

22 篇文章 8 订阅
21 篇文章 0 订阅


前言

这里这么多设备,突然发现我做的好像都是传感器之类的居多好像没啥输出端设备,每天采集一堆数据,但是没注意看手机就不知道,我那甲醛传感器丢柜子里面大半月都忘记它的存在了,但是每次掏手机就去打游戏刷视频去了,懒得专门去看(理直气壮!)
在这里插入图片描述

我得再搞个法子让我连手机都不用看,就能知道需要的信息,于是我搞了一个语音播报模块。

硬件选择

板子依然用便宜好用的的安信可的 ESP32S (我是不是真得去找安信可要赞助啊?至少把我买板子的钱报销一下啊!)
语音播报模块我买的是:亚博智能语音合成播报模块 DF家的用太多啦,换一家免得你们说我是托 o(* ̄3 ̄)o
这个模块使用 I2C 控制和通信(连接开发板:SDA->P21,SCL->P22)

服务器用的翼辉的 翼辉的 Spirit 1 边缘计算机(其实并不是真正的服务器,只是在这里的作用类似于服务器)。

代码解析

获取代码

为了方便讲解逻辑,我会打乱代码的顺序可能还会进行裁剪,要是想直接拿代码跑的朋友可以直接去 灵感桌面的秘密宝库 获取代码,或者直接 clone:

https://gitee.com/inspiration-desktop/DEV-lib-arduino.git

下载或者 clone代码后这次用到的是这个四个文件夹:

在这里插入图片描述

cjson:我移植的 cjson 库,就是标准的 cjson 库,放到 arduino 安装目录下的 libraries 文件夹里,百度一下 cjson 的函数使用就行了。

libsddc:是我移植自官方的SDDC库和自己写的 SDK,也是放入 libraries 文件夹里就行。里面是 SDDC 协议的处理函数,我们不用管。
XFS: 是亚博官方提供的语音播报模块的库,我单独打包出来了,也是放入也是放入 libraries 文件夹里就行。

demo 文件夹里面就是我们各种传感器的 demo 代码了:
在这里插入图片描述

红圈的 speech_sddc_sdk_demo 文件夹里面就是我们代码,点进去就能看见 speech_sddc_sdk_demo.ino 文件,双击文件会自动启动 arduino-IDE 打开代码。在工具 -> 端口 选择对应的 COM 口然后点击上传就可以把代码烧录到板子里:
在这里插入图片描述
具体 arduino 使用教程可以看我之前的文章 arduino开发指导手把手带你 arduino 开发:基于ESP32S 的第一个应用-红外测温枪(带引脚图)

设备控制命令:

通过 Spirit 1 的应用程序或者嗅探器 向传感器设备发送的命令:
语音播报命令:

{
  "method": "set",
  "speech": "string"      // string为需要播报的文本。编码方式必须为ANSI或者GB2312
}

语速设置命令:

{
  "method": "set",        //设置语速1~10
  "set_speed": 1-10
}

语调设置命令:

{
  "method": "set",
  "set_intonation": 1-10  //设置语调1~10
}

音量设置命令:

{
  "method": "set",
  "set_volume": 1-10      //设置音量1~10
}

设备和协议初始化流程:

基于官方 demo 写的不需要做什么修改,主要是设备初始化,管脚配置,和协议初始化部分。

/* 
 * 初始化语音播报模块
 */
static void XFS_Init()
{
    uint8_t n = 5;
    Serial.println("初始化语音播报模块");
    xfs.Begin(0x30);//设备i2c地址,地址为0x50
    delay(n);
    Serial.println("设置发音人");
    xfs.SetReader(XFS5152CE::Reader_XiaoYan);               //设置发音人
    delay(n);
    Serial.println("文本的编码格式");
    xfs.SetEncodingFormat(XFS5152CE::GB2312);               //文本的编码格式
    delay(n);
    Serial.println("语种判断");
    xfs.SetLanguage(xfs.Language_Auto);                   //语种判断
    delay(n);
    Serial.println("合成风格设置");
    xfs.SetStyle(XFS5152CE::Style_Continue);              //合成风格设置
    delay(n);
    Serial.println("设置单词的发音方式");
    xfs.SetArticulation(XFS5152CE::Articulation_Letter);  //设置单词的发音方式
    delay(n);
    Serial.println("设置语速");
    xfs.SetSpeed(5);                                      //设置语速1~10
    delay(n);
    Serial.println("设置语调");
    xfs.SetIntonation(5);                                 //设置语调1~10
    delay(n);
    Serial.println("设置音量");
    xfs.SetVolume(5);                                     //设置音量1~10
    delay(n);
}

/*
 * 初始化传感器
 */
void sensor_init()
{
    // 初始化语音播报模块
    XFS_Init();
}

void setup() {
    byte mac[6];
    Serial.begin(115200);
    Serial.setDebugOutput(true);
    Serial.println();

    // 初始化传感器
    sensor_init();

    // 清除一下按键状态机的状态
    button.reset();
  
    // 创建按键扫描线程,长按 IO0 按键,松开后ESP32 将会进入 SmartConfig 模式
    sddc_printf("长按按键进入 Smartconfig...\n");
    button.attachLongPressStop(esp_io0_key_task);
    xTaskCreate(esp_tick_task, "button_tick", ESP_TASK_STACK_SIZE, NULL, ESP_TASK_PRIO, NULL);

    // 启动 WiFi 并且连接网络
    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED) 
    {
        delay(500);
        Serial.print(".");
    }
    
    // 获取并打印 IP 地址
    Serial.println("");
    Serial.println("WiFi connected");
    Serial.print("'ip :");
    Serial.print(WiFi.localIP());
    Serial.println("' to connect"); 

    // sddc协议初始化
    sddc_lib_main(&sys_cfg);

    // 获取并打印网卡 mac 地址
    WiFi.macAddress(mac);
    sddc_printf("MAC addr: %02x:%02x:%02x:%02x:%02x:%02x\n",
              mac[5], mac[4], mac[3], mac[2], mac[1], mac[0]);
    // 使用网卡 mac 地址设置设备唯一标识 UID
    sddc_set_uid(G_sddc, mac);
}

void loop() {
    // 运行 SDDC 协议循环
    while (1) 
    {
        sddc_printf("SDDC running...\n");
        sddc_run(G_sddc);
        sddc_printf("SDDC quit!\n");
    }

    // 销毁 SDDC 协议
    sddc_destroy(G_sddc);
}

配置设备信息

这部分代码可以配置 WiFi 名字和 WiFi 密码,要使用的引脚,并且配置设备在 Spirit 1 上显示的信息:


#define SDDC_CFG_PORT             680U             // SDDC 协议使用的端口号
#define PIN_INPUT                 0                // 选择 IO0 进行控制
#define ESP_TASK_STACK_SIZE       4096
#define ESP_TASK_PRIO             25

/*超时设置,示例为30S*/
static uint32_t LastSpeakTime = 0;
#define SpeakTimeOut 10000

static const char* ssid = "EOS-Tenda";             // WiFi 名
static const char* password = "1234567890";        // WiFi 密码
static double illu_val;
OneButton button(PIN_INPUT, true);
XFS5152CE xfs;

/*
 *  当前设备的信息定义
 */
DEV_INFO    dev_info = {
            .name     = "语音合成模块",
            .type     = "device.speech",
            .excl     = SDDC_FALSE,
            .desc     = "ESP-32S + 亚博语音合成播报模块",
            .model    = "IDSPEECHU01B",
            .vendor   = "inspiration-desktop",
};

/*
 *   系统注册对象汇聚
 */
SDDC_CONFIG_INFO sys_cfg = {
        .token             = "1234567890",            // 设备密码
        .devinfo           = &dev_info,               
        .io_dev_reg        = io_dev,
        .io_dev_reg_num    = ARRAY_SIZE(io_dev),
        .num_dev_reg       = num_dev,
        .num_dev_reg_num   = ARRAY_SIZE(num_dev),
        .state_get_reg     = dev_state_get_reg,
        .state_get_reg_num = ARRAY_SIZE(dev_state_get_reg),
        .dis_dev_reg       = dis_dev,
        .dis_dev_num       = ARRAY_SIZE(dis_dev),
};

回调函数注册

这是收到命令后回调函数注册的位置,在这里注册的函数才能被 SDK 正确的调用,执行正确的动作。

具体 SDK 的解析可以参考 同人逼死官方系列!基于sddc 协议的SDK框架 sddc_sdk_lib 解析同人逼死官方系列!从 DDC 嗅探器到 sddc_sdk_lib 的数据解析

/* 
 *  数字量设备对象函数与处理方法注册
 */
NUM_DEV_REGINFO num_dev[] = {
//        {"set_num_demo", demo},                          // 字符串为输入命令,demo为命令处理函数
          {"设置语速",SetSpeed},
    	  {"设置语调",SetIntonation},
          {"设置音量",SetVolume},
};

/*
 *  显示设备对象函数与处理方法注册
 */
DIS_DEV_REGINFO dis_dev[] = {
//        {"set_dis_demo", demo},                          // 字符串为输入命令,demo为命令处理函数
};

/*
 * IO设备对象设置函数与处理方法注册
 */
IO_DEV_REGINFO io_dev[] = {
//        {"set_io_demo", demo},                           // 字符串为输入命令,demo为命令处理函数
    	  {"语音播报",speech},
};

/*
 *  系统对象状态获取注册
 */
DEV_STATE_GET  dev_state_get_reg[] = {
//        {"demo",   DEV_NUM_TYPE,  num_get_demo},         // demo为输入命令,字符串为命令处理函数
//        {"demo",   DEV_IO_TYPE,  io_get_demo},
//        {"demo", DEV_DISPLAY_TYPE, dis_get_demo},
};

语音播报与设置流程

这里是我们自己编写的处理流程 ,可以根据你的需求自己更改,收到 set 或者 get 后根据前面的注册的函数,进入对应的处理函数。
语言播报模块会将语音播报命令中的字符串转换成中文,合成语音播报出来,还可以通过 set 命令来设置模块的功能,这里只举了用了三个常用功能,但是实际上还有更多的功能可以设置:

/*
 * 语音播报函数
 */
sddc_bool_t speech(const char* value)
{
    printf("开始播报\n");
    xfs.StartSynthesis(value);            // 选择播报的语句
    while(xfs.GetChipStatus() != xfs.ChipStatus_Idle) //检查判断是否完成
    {
        delay(30);
    }
    return SDDC_TRUE;
}

/*
 * 设置语速函数
 */
sddc_bool_t SetSpeed(const uint64_t value)
{
    printf("设置语速\n");
    xfs.SetSpeed(value);
    return SDDC_TRUE;
}
/*
 * 设置语调函数
 */
sddc_bool_t SetIntonation(const uint64_t value)
{
    printf("设置语调\n");

    xfs.SetIntonation(value);
    return SDDC_TRUE;

}

/*
 * 设置音量函数
 */
sddc_bool_t SetVolume(const uint64_t value)
{
    xfs.SetVolume(value); 
    return SDDC_TRUE;
} 

总结

好了之后只要写个应用,定一个时间或者阈值获取传感器数据让语言播报模块告诉我就好了,完美!

本文仅个人学习使用,如有错误,欢迎指正, ( ੭ ˙ᗜ˙ )੭谢谢老板!

  • 2
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值