【训练营_进阶班】esp32语音助手 - 嘉立创EDA开源硬件平台

编辑器版本 ×
标准版 Standard

1、简单易用,可快速上手

2、流畅支持300个器件或1000个焊盘以下的设计规模

3、支持简单的电路仿真

4、面向学生、老师、创客

专业版 professional

1、全新的交互和界面

2、流畅支持超过3w器件或10w焊盘的设计规模,支持面板和外壳设计

3、更严谨的设计约束,更规范的流程

4、面向企业、更专业的用户

标准版 【训练营_进阶班】esp32语音助手

简介:1.采用esp32作为主控芯片 2.离线语音识别(支持语音唤醒) 3.手机APP控制 两个继电器和板载小灯(阿里云的云智能APP)

开源协议: GPL 3.0

(未经作者授权,禁止转载)

创建时间: 2020-08-07 00:53:50
更新时间: 2023-12-31 19:16:46
描述
# 芯片的选择 为什么选择esp32,因为我觉得它性能强悍,双核架构,240MHZ主频,有强大的算力,支持我进行离线语音识别。 本项目没有使用额外的语音识别模块,就一个麦克风采集声音,esp32用来解析和分析音频数据。 # 板子的踩的坑 我是第一次画在工厂打出来样品的板子,真的感谢立创EDA,给提供这么好的平台,知道了强电不能敷铜等等等。真的是我技术不到家的原因,我原本焊上去5个灯,结果就亮了两个,我把剩下的三个拆了,可能我拆坏了,把这三个灯调换下位置,还是不会亮,最后我果断把后三个灯拆了,后续会把这三个灯珠补齐。 # 硬件的设计 ## 1.主要的IC 1.ESP32-WROOM                    一款乐鑫研发的32位芯片,内置WIFI,蓝牙,240HZ的主频等等 2.MSM261S4030H0R                一个I2S接口的麦克风,用来进行语音输入 3.CP2102N-A01-GQFN28R            一个USB下载芯片 4.WS2812E                                5个LED灯珠(主要是考虑esp32内置了RMT发射器,发送的波形 刚好满足 WS2812的时序) 5.AMS1117-3.3_C347222            5V转3.3V 6.HK4100F-DC5V-SHG               继电器 ........ 还有就不一一列举了 ## 2.硬件的整体框架 整个板子的主控是ESP32。 GPIO18             产生RMT波形,发送到WS2812,从而点亮LED灯。 GPIO32 33 25  是esp32的I2S接口,接到麦克风对应的引脚 GPIO4 16          接入继电器,用来驱动强电 GPIO0  EN脚    外接了两个键盘 剩下的都是一些下载电路,和电源部分 # 软件的设计 ## 1.开发环境 Ubuntu18.0.4 Vscode esp-idf 3.2 ## 2.环境的搭建 由于开发环境是在Linux平台下编译的,所以我选择了Ubuntu,可以从乐鑫的官方文档中, 看到安装步骤,一步一步搭建, 具体的网址-->:[https://docs.espressif.com/projects/esp-idf/zh_CN/v3.3.2/get-started/linux-setup.html](https://docs.espressif.com/projects/esp-idf/zh_CN/v3.3.2/get-started/linux-setup.html) \*\*第一步 :\*\*就是获取工具链,eps32的架构是xtensa架构的,所以需要下载交叉编译的编译器,连接器等等\,获取完工具链把它添加到环境变量。 \*\*第二步:\*\*就是获取esp\-idf了,由于国内的网络环境,从github获取代码比较慢,可以去采取合理的方法下载,注意克隆仓库的时候要加 \-\-recursive 这个参数,如: ``` git clone -b v3.3.2 --recursive https://github.com/espressif/esp-idf.git ``` 这个参数是克隆全部的,不然会造成克隆过来的仓库不完整。 下来把esp-idf的路径,添加到环境变量。 运行 ``` python -m pip install --user -r $IDF_PATH/requirements.txt ``` 安装python库,因为idf有些驱动是用python写的脚本。 **第三步:** 获取阿里云的SDK,不过我没用去阿里云获取,我在乐鑫的仓库中发现了,他们完成了底层的硬件接口和阿里云飞燕平台对接的库,运行: ``` git clone https://github.com/espressif/esp-ali-smartliving.git ``` 编译 ali-smartliving-device-sdk-c 库 在 esp-ali-smartliving 目录下执行: ``` cd ali-smartliving-device-sdk-c make reconfig (选择SDK平台,选择esp32) make menuconfig (选择相关功能配置,默认不需要修改,该步骤可以省略) make (生成相关头文件和库文件) ``` 乐鑫还给了示例工程,我是在工程是进行修改。 **第四步:** 安装Vscode ,Vscode免费,有强大的插件功能,Vscode也发行了Linux版本,用来开发esp32我感觉是最好的选择。

**这几步下来,所有一切东西全部免费开源,不用担心版权原因。** #### 总的来说在Linux下环境搭建比较麻烦,不像Keil之类的IDE,通过自己一步一步设置编译工具链,一步步下来,那种感觉是在Keil之类的IDE是感受不到的。 ## 3.软件的整体架构 1\. 阿里云对生活物联网平台提供了SDK,本软件整体架构就是基于阿里云的SDK和乐鑫的esp\-idf。 2.esp32是基于 freeRTOS操作系统,这就方便了我们以任务的形式 进行并发执行。 下图是我画的大概流程,两个任务,期中主任务分布着某些小任务
![image.png](//image.lceda.cn/pullimage/tBbnRFHuLPaeAtV61zdj5TaGNM5XJ5K1d8vbd2xW.png) 语音识别的固件来源与乐鑫音频开发框架esp-adf,可以进行离线语音识别,支持语音唤醒, 乐鑫的语音识别,乐鑫提拱了,编译好的库,这些库都是乐鑫自己训练好的库,CNN卷积神经网络,大量训练而来的,这里感谢乐鑫提供的库。 说:嗨乐鑫,进入唤醒模式,LED灯会以呼吸灯的形式闪烁,表示进入语音监听模式,说出命令,从而控制开发板,如果5s之内没反应,恢复以前的状态,重新进入语音监控模式。
![image.png](//image.lceda.cn/pullimage/JUclccJz0zOuV1nPdAUaBt7TDtjnHB7vql4W0lIT.png) 图画的比较丑 阿里云监控数据,就不画图了,大致就是解析Json数据,执行相对应的命令。阿里云的SDK里面有专门的API提供调用。 ### 外设的驱动设计: 外设有WS2812  麦克风 和继电器 WS2812 这个驱动我搞了好久,把有关RMT部分都放在ws2812.c文件下了,都把它封装成结构体的形式,提供调用, ``` struct led_strip_s { esp_err_t (*get_hsv)(led_strip_t *strip, uint32_t *h, uint32_t *s, uint32_t *v); esp_err_t (*get_rgb)(led_strip_t *strip, uint32_t *red, uint32_t *green, uint32_t *blue); esp_err_t (*set_hsv)(led_strip_t *strip, uint32_t h, uint32_t s, uint32_t v); esp_err_t (*set_rgb)(led_strip_t *strip, uint32_t red, uint32_t green, uint32_t blue);   esp_err_t (*set_pixel)(led_strip_t *strip, uint32_t index, uint32_t red, uint32_t green, uint32_t blue);  esp_err_t (*refresh)(led_strip_t *strip, uint32_t timeout_ms);   esp_err_t (*clear)(led_strip_t *strip, uint32_t timeout_ms); esp_err_t (*del)(led_strip_t *strip); }; // 通过调用这个函数得到一个结构体 led_strip_t *led_strip_new_rmt_ws2812(const led_strip_config_t *config); 下面举个简单的例子 /******example*******/ led_strip_t *g_leds = led_strip_new_rmt_ws2812(&strip_config); // 得到led的结构体 g_leds->g_leds->set_hsv(g_leds, h, s, v); // 调用这个函数设置 灯的hsv属性 ``` 通过这样设计灯的驱动,操作更简单,便于以后增加和删除功能,代码的灵活性大大提高 麦克风,esp-idf框架下有I2S的库,直接调用,音频部分还要进行,一部分滤波,具体的代码,我是参考esp-adf里面的 ``` static void i2s_init(void) { i2s_config_t i2s_config = { .mode = I2S_MODE_MASTER | I2S_MODE_RX, // the mode must be set according to DSP configuration .sample_rate = 16000, // must be the same as DSP configuration .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, // must be the same as DSP configuration .bits_per_sample = 32, // must be the same as DSP configuration .communication_format = I2S_COMM_FORMAT_I2S, .dma_buf_count = 3, .dma_buf_len = 300, .intr_alloc_flags = ESP_INTR_FLAG_LEVEL2, }; i2s_pin_config_t pin_config = { .bck_io_num = BOARD_DMIC_I2S_SCK, // IIS_SCLK .ws_io_num = BOARD_DMIC_I2S_WS, // IIS_LCLK .data_out_num = -1, // IIS_DSIN .data_in_num = BOARD_DMIC_I2S_SDO // IIS_DOUT }; i2s_driver_install(1, &i2s_config, 0, NULL); i2s_set_pin(1, &pin_config); i2s_zero_dma_buffer(1); } ``` 继电器 只用到了 GPIO的输出功能,同样esp-idf里面有驱动 :包含 #include "driver/gpio.h"
``` gpio_config_t io_conf; io_conf.intr_type = GPIO_PIN_INTR_DISABLE; //set as output mode io_conf.mode = GPIO_MODE_OUTPUT; //bit mask of the pins that you want to set,e.g io_conf.pin_bit_mask = GPIO_OUTPUT_PIN_SEL; //disable pull-down mode io_conf.pull_down_en = 0; //disable pull-up mode io_conf.pull_up_en = 0; //configure GPIO with the given settings gpio_config(&io_conf); 通过调用 gpio_set_level(GPIO_OUTPUT_IO_16, leavel); 就可以进行很简单的GPIO控制 ``` # ESP32分区表的划分 esp32把FLASH的空间进行了划分,具体有关分区表的介绍,参考:[https://docs.espressif.com/projects/esp-idf/zh_CN/v3.3.2/api-guides/partition-tables.html](https://docs.espressif.com/projects/esp-idf/zh_CN/v3.3.2/api-guides/partition-tables.html) 文档中有详细的介绍。我们把四元组的信息,烧录在flash的指定位置。 我用的这个模组,是4M的flash,因为要进行语音识别,所以nvs要分的大一点,下一个存的是wifi信息,我还预留了两个OTA升级的空间,不过这个空间太小了,用不上,最后一个是存储阿里云生活物联网平台的四元组信息。 下面代码,就是我的分区表,第一个分区很大,因为要进行语音识别要很大的空间,最后一个分区,存入的是四元组的信息。 ``` factory, app, factory, , 3840K nvs, data, nvs, , 0x4000, otadata, data, ota, , 0x2000, phy_init, data, phy, , 0x1000, ota_0, app, ota_0, , 0x1000, ota_1, app, ota_1, , 0x1000, fctry, data, nvs, , 0x4000 ``` ### 烧录四元组到flash ``` mass_mfg 目录中有一参考配置:single_mfg_config.csv,请拷贝成自己的配置文件,如 my_single_mfg_config.csv。 ``` cp single\_mfg\_config\.csv my\_single\_mfg\_config\.csv ``` 使用自己的 ProductKey、ProductSecret、DeviceName、DeviceSecret 对 my_single_mfg_config.csv 进行修改: ``` ``` key,type,encoding,value aliyun-key,namespace,, DeviceName,data,string,config DeviceSecret,data,string,dsj3RuY74pgCBJ3zczKz1LaLK7RGApqh ProductKey,data,string,a10BnLLzGv4 ProductSecret,data,string,pVfLpS1u3A9JM0go ``` ``` 将 config,dsj3RuY74pgCBJ3zczKz1LaLK7RGApqh,a10BnLLzGv4,pVfLpS1u3A9JM0go 修改为你对应的值。 修改完成后,使用如下命令生成对应的 NVS 分区: ``` ``` $IDF_PATH/components/nvs_flash/nvs_partition_generator/nvs_partition_gen.py --input my_single_mfg_config.csv --output my_single_mfg.bin --size 0x4000 ``` ``` 下载 针对 esp32: ``` ``` $IDF_PATH/components/esptool_py/esptool/esptool.py write_flash 0x003f1000 my_single_mfg.bin 注:0x003f1000 这个地址,是存放四元组的起始地址,一定要算对,要跟分区表一致,否则会造成配网失败 ``` # 手机配网 **在阿里云生活物联网平台创建产品,具体就是那一套过程,在这块i要注意一点,采用这个东西配网,要选择一键配网** ![image.png](//image.lceda.cn/pullimage/Ai2UKfb43LZJiLbbT1yDRIgoZHHtGd9OIK9fs6iI.png) 然后采用二维码扫描的方式配网,这个二维码的入口在这个地方。扫描这个二维码,一键配网 ![image.png](//image.lceda.cn/pullimage/jwdwdgBrNtCEqsd2Zi4EimtXojSwGiB9XBH9oqhr.png) 配网完成,在手机上可以看见这样,就可以用手机控制了 ![image.png](//image.lceda.cn/pullimage/7FgU6RaKTYlSpjf8nURO9RwD8GBkywYTIjVBN02I.png)


# 实用性 ### 我觉得,后期可以买个灯罩 把板子罩起来,放在桌子上,继电器可以外接,控制个风扇啥的。

### 这个并不完全依赖网络,当网络断开的时候,可以离线控制,方便了使用者使用,后续我会加入OTA升级,实现远程升级 8.26     我发现跑个离线神经网络占了flash的四分之三大小,就剩1M的空间,根本不够存放OTA升级的固件,所以要想OTA升级和离线识别共用,就需要增大flash的容量大小,或许有什么方法能裁剪,我再看看。
设计图
原理图
1 /
PCB
1 /
未生成预览图,请在编辑器重新保存一次
工程视频/附件
序号 文件名称 下载次数
1

代码解释编译下载.mp4

410
2

ALI_Demo.zip

58
3

作品演示.mp4

473
工程成员
侵权投诉
相关工程
换一批
加载中...
添加到专辑 ×

加载中...

温馨提示 ×

是否需要添加此工程到专辑?

温馨提示
动态内容涉嫌违规
内容:
  • 153 6159 2675

服务时间

周一至周五 9:00~18:00
  • 技术支持

support
  • 开源平台公众号

MP