开发板介绍
环境配置
1.下载esp-box项目代码
github仓库:
https://github.com/espressif/esp-box
使用git工具和如下命令进行下载:
git clone --recursive https://github.com/espressif/esp-box.git
下载成功后,如下图所示:
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,剩下的就是正常编译和烧录的步骤,具体内容可见上一篇博客。
实际运行结果:
参考:
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功能,实现一个语音播报系统,如联网获取粉丝数并播报 。
任务分析
- GUI模块:LVGL框架 负责显示界面与界面更新
- wifi模块:负责联网与网络数据的通道建立
- http模块:负责HTTP请求与数据交互
- TTS模块:负责语音的播放
如下图所示。
首先开机先进入GUI模块 进行GUI的显示,
其次,WIFI模块开始建立wifi的网络通道
然后, HTTP模块进行数据的交互,获取粉丝数据
最后,获取到数据后,进行数据界面更新与语音数据播放。
核心代码
-
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;
}
}