Funpack2-5 ESP32-S3-box-lite 语音播报系统
基于ESP32-S3-box-lite 的语音播报系统,涉及wifi模块 http模块,TTS模块
标签
嵌入式系统
Funpack活动
语音
ESP32-S3-BOX-LITE
安先生
更新2023-08-02
648

开发板介绍

ESP32-S3-BOX-Lite 是目前对应的 AIoT 应用开发板,搭载支持 AI 加速的 ESP32-S3 Wi-Fi + Bluetooth 5 (LE) SoC。为用户提供了一个基于语音助手、传感器、红外控制器和智能 Wi-Fi 网关等功能开发和控制智能家居设备的平台。开发板出厂支持离线语音交互功能,用户通过乐鑫丰富的 SDK 和解决方案,能够轻松构建在线和离线语音助手、智能语音设备、HMI 人机交互设备、控制面板、多协议网关等多样的应用。
 
参考链接
 

环境配置

1.下载esp-box项目代码
github仓库:

https://github.com/espressif/esp-box

使用git工具和如下命令进行下载:

git clone --recursive https://github.com/espressif/esp-box.git

下载成功后,如下图所示:

Fv8zBwfyJoOutEU-ItIxVKc9Z_GW


2.切换分支
根据版本信息,作者使用的是v4.4和ESP32-S3-BOX-Lite,因此需切换到 Tag 0.3.0。在本地项目中使用以下命令切换:

git checkout v0.3.0

3.补全项目的子模块
此时本地项目还并不完整,还有一些子模块需要单独下载,先使用如下命令查看需要哪些子模块:(这部很重要,没有下载 后面编译会报错)

git submodule

以子模块components/lvgl/lv_demos为例,在仓库中找到它(注意仓库要切换分支0.3.0,否则没有该文件夹):

直接点击lv_demos @ 615d40f,就切换到了另一个仓库,将该仓库下载下来,解压缩,然后覆盖掉本地项目中空的 lv_demos 即可。

 

4.编译并烧录示例程序
打开例程文件夹 esp-box\examples\,选择例程 image_display,剩下的就是正常编译和烧录的步骤,具体内容可见上一篇博客。

实际运行结果:

FsarJSkI84boMUCB-yff2sCWdKF7

参考:

https://github.com/espressif/esp-box/blob/master/README.md
https://github.com/espressif/esp-box/tree/master/examples/image_display

自此 开发板初步验证与环境配置验证OK ,接下来开始我们的任务开发

任务描述

使用ESP32的WiFi和TTS功能,实现一个语音播报系统,如联网获取粉丝数并播报 。

任务分析

整个系统分成4个大模块
  • GUI模块:LVGL框架 负责显示界面与界面更新
  • wifi模块:负责联网与网络数据的通道建立
  • http模块:负责HTTP请求与数据交互
  • TTS模块:负责语音的播放

如下图所示。

首先开机先进入GUI模块 进行GUI的显示,

其次,WIFI模块开始建立wifi的网络通道

然后,  HTTP模块进行数据的交互,获取粉丝数据

最后,获取到数据后,进行数据界面更新与语音数据播放。

FuMEchPR-EmcMGamYakxokeHfeSf

核心代码

  • GUI模块,核心代码说明,首先开机显示控件界面,然后获取到数据后更新控件的数据信息
void main_gui_task(void *pvParams)
{
    /* Create a white label, set its text and align it to the center */
    label = lv_label_create(lv_scr_act());
    lv_obj_set_style_text_font(label, &lv_font_montserrat_18, 0); // Font size 24
    
    char msg[256] = {0};
    snprintf(msg, sizeof(msg),
             "#000000 Software Ver: # "  "#888888 V%u.%u.%u#\n"
             "#000000 ESP-IDF Ver: # "   "#888888 %s#\n"
             "#000000 Wifi status: # "       "#888888 %s#\n"
             "#000000 Bili Followers: # "         "#888888 %s#",
             BOX_DEMO_VERSION_MAJOR, BOX_DEMO_VERSION_MINOR, BOX_DEMO_VERSION_PATCH,
             esp_get_idf_version(),
             wifi_status ? "Connect OK!":"Connecting!",
             "Waiting query");
    lv_label_set_text(label, msg);
    lv_label_set_recolor(label, true);
    lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);
    vTaskDelete(NULL);
}

void main_gui_display_update(int num)
{
    char msg[256] = {0};
    snprintf(msg, sizeof(msg),
             "#000000 Software Ver: # "  "#888888 V%u.%u.%u#\n"
             "#000000 ESP-IDF Ver: # "   "#888888 %s#\n"
             "#000000 Wifi status: # "       "#5da027 %s#\n"
             "#000000 Bili Followers: # "         "#888888 %d#",
             BOX_DEMO_VERSION_MAJOR, BOX_DEMO_VERSION_MINOR, BOX_DEMO_VERSION_PATCH,
             esp_get_idf_version(),
             wifi_status ?  "Connect OK!":"Connecting!",             
             num);
    lv_obj_set_style_bg_color(lv_scr_act(), lv_color_hex(0x1e3c06), LV_PART_MAIN);
    lv_label_set_text_fmt(label, msg);
}
  • HTTP模块 核心代码说明,通过HTTP获取到bilibili的数据 并把数据放在buffer 然后回调TTS进行数据播放 
static void https_get_request(esp_tls_cfg_t cfg, const char *WEB_SERVER_URL, const char *REQUEST)
{
    char buf[MAX_REQUEST_BUF_LEN];
    int ret, len;

    struct esp_tls *tls = esp_tls_conn_http_new(WEB_SERVER_URL, &cfg);

    if (tls != NULL)
    {
        ESP_LOGI(TAG, "Connection established...");
    }
    else
    {
        ESP_LOGE(TAG, "Connection failed...");
        goto exit;
    }

#ifdef CONFIG_EXAMPLE_CLIENT_SESSION_TICKETS
    /* The TLS session is successfully established, now saving the session ctx for reuse */
    if (save_client_session)
    {
        free(tls_client_session);
        tls_client_session = esp_tls_get_client_session(tls);
    }
#endif
    size_t written_bytes = 0;
    do
    {
        ret = esp_tls_conn_write(tls,
                                 REQUEST + written_bytes,
                                 strlen(REQUEST) - written_bytes);
        if (ret >= 0)
        {
            ESP_LOGI(TAG, "%d bytes written", ret);
            written_bytes += ret;
        }
        else if (ret != ESP_TLS_ERR_SSL_WANT_READ && ret != ESP_TLS_ERR_SSL_WANT_WRITE)
        {
            ESP_LOGE(TAG, "esp_tls_conn_write  returned: [0x%02X](%s)", ret, esp_err_to_name(ret));
            goto exit;
        }
    } while (written_bytes < strlen(REQUEST));

    ESP_LOGI(TAG, "Reading HTTP response...");

    do
    {
        len = sizeof(buf) - 1;
        bzero(buf, sizeof(buf));
        ret = esp_tls_conn_read(tls, (char *)buf, len);

        if (ret == ESP_TLS_ERR_SSL_WANT_WRITE || ret == ESP_TLS_ERR_SSL_WANT_READ)
        {
            continue;
        }

        if (ret < 0)
        {
            ESP_LOGE(TAG, "esp_tls_conn_read  returned [-0x%02X](%s)", -ret, esp_err_to_name(ret));
            break;
        }

        if (ret == 0)
        {
            ESP_LOGI(TAG, "connection closed");
            break;
        }

        len = ret;
        ESP_LOGD(TAG, "%d bytes read", len);
        /* Print response directly to stdout as it is read */
        for (int i = 0; i < len; i++)
        {
            putchar(buf[i]);
        }
        putchar('\n'); // JSON output doesn't have a newline at end
        memcpy(https_requst_buffer, buf, MAX_REQUEST_BUF_LEN);
        static bool play_flag = 0;
        if(!play_flag){
          play_flag = 1;
          vTaskDelay(3000 / portTICK_PERIOD_MS);
          main_tts_play(NULL);
        }
        // 

    } while (1);

exit:
    esp_tls_conn_delete(tls);
}
  • TTS播放 ,通过调用TTS模块,进行数据的语音播放
void main_tts_play(void *arg)
{
    char *followers;
    char prompt[64];
    ESP_LOGE(TAG, "main_tts_play\n");
    /* Parse the followers number(string) */
    esp_err_t err = json_parse_followers(&followers);
    if (err != ESP_OK)
    {
        ESP_LOGE(TAG, "tts report failed!\n");
        return;
    }

    /* Update the followers number on the screen */
    main_gui_display_update(atoi(followers));

    /* Convert the string to Chinese prompt */
    err = followers_to_prompt(followers, prompt);
    if (err != ESP_OK)
    {
        ESP_LOGE(TAG, "converted followers string to Chinese prompt failed!\n");
        return;
    }

    /* Play the prompt at speed=1 */
    err = tts_report(prompt, 1);
    if (err != ESP_OK)
    {
        ESP_LOGE(TAG, "TTS report failed!\n");
        return;
    }
}

功能展示

1.开机时,界面展示
FqdepA-31Xl6N85E4N6r3INdadw-
 
2, 获取到数据后,界面展示

Fs8Bs1x7bBBquKI2M7ip8k9nevL-

心得体会

非常感谢本次活动 。
ESP32的生态非常完善,这次在语音领域的初步尝试,收获也挺多。
接下来还会继续尝试离线语音功能,以及AIOT的联动。
非常感谢电子森林 以后还会继续支持。
 
附件下载
esp-box-lite-demo-tts.zip
团队介绍
安迪,一枚嵌入式攻城狮
评论
0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号