从零开始 DIY 智能家居 - 基于 ESP32 的智能语音合成播报模块
前言
这里这么多设备,突然发现我做的好像都是传感器之类的居多好像没啥输出端设备,每天采集一堆数据,但是没注意看手机就不知道,我那甲醛传感器丢柜子里面大半月都忘记它的存在了,但是每次掏手机就去打游戏刷视频去了,懒得专门去看(理直气壮!)
我得再搞个法子让我连手机都不用看,就能知道需要的信息,于是我搞了一个语音播报模块。
硬件选择
板子依然用便宜好用的的安信可的 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;
}
总结
好了之后只要写个应用,定一个时间或者阈值获取传感器数据让语言播报模块告诉我就好了,完美!
本文仅个人学习使用,如有错误,欢迎指正, ( ੭ ˙ᗜ˙ )੭谢谢老板!
从零开始 DIY 智能家居 - 基于 ESP32 的智能语音合成播报模块的更多相关文章
- 从零开始 DIY 智能家居 - 基于 ESP32 的智能紫外线传感器模块
目录 前言 硬件选择 二.使用步骤 获取代码 设备控制命令: 设备和协议初始化流程: 配置设备信息 回调函数注册 数据获取与上报流程 总结 前言 做了这么多传感器都是自己玩,这次家里人看不下去了,非得 ...
- 从零开始的DIY智能家居 - 基于 ESP32 的智能水浊度传感器
前言 家里有个鱼缸养了几条鱼来玩玩,但是换水的问题着实头疼,经常一个不注意就忘记换水,鱼儿就没了.o(╥﹏╥)o 在获得 Spirit 1 边缘计算机 后就相当于有了一个人智能设备服务器,可以自己开发 ...
- 从零开始的DIY智能家居 - 基于 ESP32 的智能光照传感器
前言 上周出差有点急,结果家里灯没关,开了整整一周的时间(T▽T),整个人都裂开了,准备做一个能够远程控制灯的东西,让我以后出差能远程把家里灯关了. 第一步就是做这期的主题 - 智能光照传感器,因为我 ...
- 从零开始的DIY智能家居 - 基于 ESP32 的智能浇水器
前言 上次 土壤湿度传感器 完成之后,就立下一个 flag 要搭建一个智慧浇水的智能场景,现在终于有时间填坑了!(o゚▽゚)o 智慧浇水场景的核心设备有三个: 检测土壤状态的:土壤湿度传感器 通过这个 ...
- 从零开始的DIY智能家居 - 基于 ESP32 的土壤湿度传感器
前言 自从上次做了那个 甲醛传感器 和 水浊度传感器 之后开始尝到智能家居的甜头了,这两东西有没有用我不知道,但是没事的时候掏出手机瞄两眼,看着就让人很安心( ̄︶ ̄). 于是懒惰的我开始琢磨把给植物浇 ...
- 基于ESP32的智能家居管理系统的设计与实现
基于ESP32的智能家居管理系统的设计与实现 ESP32的智能家居管理系统访问链接: https://www.cnblogs.com/easyidea/p/13101165.html 一.需求分析 1 ...
- 手把手搭建自己的智能家居 - 基于 IOT Pi 的智能甲醛检测器
智慧家居 - 基于 IOT Pi 的智能甲醛检测器 之前的文章体验 MS-RTOS 的时候入手了一个块 IOT Pi ,放着也是浪费,这次我们就利用 IOT PI 开发一个智能甲醛检测器.φ(> ...
- 基于能量收集的智能家居-2013国家级大学生创业实践项目申报_商业计划书_V0.2
SmartHome项目商业计划 基于能量收集的 免电池无线智能家居系统 IA-SmartHome团队 2012.12 l 基于无线的智能家居解决方案,节省施工成本: l 基于能 ...
- 谁才是智能家居的未来?视声M+O融合方案给出答案
有些智能家居,你不能说它不智能. 但在现实生活中,常常帅不过一秒. 就比如,当你经历了一天的疲惫后回到家,发现玄关的智能开关突然没反应,家里的灯怎么都打不开.这种时候你得明白,你的智能开关面板很有可能 ...
随机推荐
- Redis核心原理与实践--列表实现原理之quicklist结构
在上一篇文章<Redis列表实现原理之ziplist结构>,我们分析了ziplist结构如何使用一块完整的内存存储列表数据. 同时也提出了一个问题:如果链表很长,ziplist中每次插入或 ...
- 【C++基础教程】第三课
上次的课后练习答案 练习一 第一题a=8 第二题8 第三题(int)(a+0.2) 提示:把浮点数转换为整数,用强制类型转换的方式.(int)(...)表示把...的内容强制转换为int类型,同理,( ...
- 【OI】WERTYU UVa 10082
题目: A common typing error is to place the hands on the keyboard one row to the right of the correct ...
- Hyper-V + WSL2与 VirtualBox 共存
Hyper-V + WSL2与 VirtualBox 共存 这样的教程网上有很多,我先简单复述一下.真正麻烦的是我遇到的问题--开启 Hyper-V 后我的电脑会多出几个删不掉的虚拟显示器来,会在文章 ...
- 简单学习PHP中的层次性能分析器
在 PHP 中,我们需要进行调试的时候,一般都会使用 memory_get_usage() 看下内存的使用情况.但如果想看当前的脚本 CPU 的占用情况就没有什么现成的函数了.不过,PHP 也为我们提 ...
- C++ 找零钱方法数
* 动态规划法 #include "stdafx.h" #include <iostream> #include <vector> using std::v ...
- IOS 安装网页
一般使用企业签名的iOS安装包 都需要一个下载地址,像蒲公英什么的 都有下载限制,所以求人不如求己. 内容也是复制别人的 :https://lzw.me/a/itms-services-ios-ins ...
- Orchard Core 配置项说明
Orchard Core使用IShellConfiguration扩展了ASP.NET Core IConfiguration,以允许在应用程序范围的配置之上进行特定于租户的配置.虽然本文档使用Orc ...
- Linkerd stable-2.11.0 稳定版发布:授权策略、gRPC 重试、性能改进等!
公众号:黑客下午茶 授权策略 Linkerd 的新服务器授权策略(server authorization policy)功能使您可以细粒度控制允许哪些服务相互通信.这些策略直接建立在 Linkerd ...
- 洛谷P6075题解
题面 首先这 \(n\) 个数是互相独立的,所以我们不需要统一的去考虑,只需要考虑其中一个数即可. 我们以 \(k=5\) 的情况举例. 我设 \(f_i\) 为最后一行只填前 \(i\) 个点的情况 ...