Add recoder every 60s.

This commit is contained in:
Colin 2025-12-21 18:49:03 +08:00
parent 5c5dcb40fa
commit 646b29790e
8 changed files with 229 additions and 88 deletions

17
.vscode/c_cpp_properties.json vendored Normal file
View File

@ -0,0 +1,17 @@
{
"configurations": [
{
"name": "Mac",
"includePath": [
"${workspaceFolder}/**"
],
"defines": [],
"compilerPath": "/usr/bin/clang",
"intelliSenseMode": "macos-clang-arm64",
"compileCommands": [
"${workspaceFolder}/build/compile_commands.json"
]
}
],
"version": 4
}

21
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,21 @@
{
"files.associations": {
"BUILD": "bazel",
"*.inc": "cpp",
"__config": "c",
"__hash_table": "c",
"__locale": "c",
"atomic": "c",
"deque": "c",
"istream": "c",
"iterator": "c",
"memory": "c",
"sstream": "c",
"string": "c",
"string_view": "c",
"vector": "c",
"unordered_map": "c",
"esp_netif_sntp.h": "c",
"sdmmc_cmd.h": "c"
}
}

View File

@ -5,5 +5,5 @@
cmake_minimum_required(VERSION 3.16)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(speech_recognition)
project(listener)

View File

@ -1,4 +1,2 @@
idf_component_register(SRCS "app_sr.c" "esp32_s3_szp.c" "main.c" "app_ui.c"
INCLUDE_DIRS ".")
spiffs_create_partition_image(storage ../spiffs FLASH_IN_PROJECT)
INCLUDE_DIRS ".")

View File

@ -175,8 +175,8 @@ void app_sr_init(void) {
ESP_LOGI(TAG, "wakenet:%s", afe_config.wakenet_model_name); // 打印唤醒名称
task_flag = 1;
xTaskCreatePinnedToCore(&detect_Task, "detect", 8 * 1024, (void*)afe_data, 5,
NULL, 1);
xTaskCreatePinnedToCore(&feed_Task, "feed", 8 * 1024, (void*)afe_data, 5,
NULL, 0);
// xTaskCreatePinnedToCore(&detect_Task, "detect", 8 * 1024, (void*)afe_data, 5,
// NULL, 1);
// xTaskCreatePinnedToCore(&feed_Task, "feed", 8 * 1024, (void*)afe_data, 5,
// NULL, 0);
}

View File

@ -122,9 +122,8 @@ void mp3_player_init(void) {
player_config.priority = 6;
player_config.coreID = 1;
// ESP_ERROR_CHECK(audio_player_new(player_config));
// ESP_ERROR_CHECK(audio_player_callback_register(_audio_player_callback,
// NULL));
ESP_ERROR_CHECK(audio_player_new(player_config));
ESP_ERROR_CHECK(audio_player_callback_register(_audio_player_callback, NULL));
// 显示界面
music_ui();

View File

@ -1,5 +1,7 @@
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <time.h>
#include "app_sr.h"
#include "app_ui.h"
@ -10,49 +12,53 @@
#include "es7210.h"
#include "esp32_s3_szp.h"
#include "esp_check.h"
#include "esp_netif_sntp.h"
#include "esp_sntp.h"
#include "esp_vfs_fat.h"
#include "esp_wifi.h"
#include "format_wav.h"
#include "nvs_flash.h"
#include "sdkconfig.h"
#include "sdmmc_cmd.h"
/* I2C port and GPIOs */
#define EXAMPLE_I2C_NUM (0)
#define EXAMPLE_I2C_SDA_IO (1)
#define EXAMPLE_I2C_SCL_IO (2)
#define I2C_NUM (0)
#define I2C_SDA_IO (1)
#define I2C_SCL_IO (2)
/* I2S port and GPIOs */
#define EXAMPLE_I2S_NUM (0)
#define EXAMPLE_I2S_MCK_IO (38)
#define EXAMPLE_I2S_BCK_IO (14)
#define EXAMPLE_I2S_WS_IO (13)
#define EXAMPLE_I2S_DI_IO (12)
#define I2S_NUM (0)
#define I2S_MCK_IO (38)
#define I2S_BCK_IO (14)
#define I2S_WS_IO (13)
#define I2S_DI_IO (12)
/* SD card GPIOs */
#define EXAMPLE_SD_CMD_IO (48)
#define EXAMPLE_SD_CLK_IO (47)
#define EXAMPLE_SD_DAT0_IO (21)
#define SD_CMD_IO (48)
#define SD_CLK_IO (47)
#define SD_DAT0_IO (21)
/* I2S configurations */
#define EXAMPLE_I2S_TDM_FORMAT (ES7210_I2S_FMT_I2S)
#define EXAMPLE_I2S_CHAN_NUM (2)
#define EXAMPLE_I2S_SAMPLE_RATE (48000)
#define EXAMPLE_I2S_MCLK_MULTIPLE (I2S_MCLK_MULTIPLE_256)
#define EXAMPLE_I2S_SAMPLE_BITS (I2S_DATA_BIT_WIDTH_16BIT)
#define EXAMPLE_I2S_TDM_SLOT_MASK (I2S_TDM_SLOT0 | I2S_TDM_SLOT1)
#define I2S_TDM_FORMAT (ES7210_I2S_FMT_I2S)
#define I2S_CHAN_NUM (2)
#define I2S_SAMPLE_RATE (48000)
#define I2S_MCLK_MULTIPLE (I2S_MCLK_MULTIPLE_256)
#define I2S_SAMPLE_BITS (I2S_DATA_BIT_WIDTH_16BIT)
#define I2S_TDM_SLOT_MASK (I2S_TDM_SLOT0 | I2S_TDM_SLOT1)
/* ES7210 configurations */
#define EXAMPLE_ES7210_I2C_ADDR (0x41)
#define EXAMPLE_ES7210_I2C_CLK (100000)
#define EXAMPLE_ES7210_MIC_GAIN (ES7210_MIC_GAIN_30DB)
#define EXAMPLE_ES7210_MIC_BIAS (ES7210_MIC_BIAS_2V87)
#define EXAMPLE_ES7210_ADC_VOLUME (0)
#define ES7210_I2C_ADDR (0x41)
#define ES7210_I2C_CLK (100000)
#define ES7210_MIC_GAIN (ES7210_MIC_GAIN_30DB)
#define ES7210_MIC_BIAS (ES7210_MIC_BIAS_2V87)
#define ES7210_ADC_VOLUME (0)
/* SD card & recording configurations */
#define EXAMPLE_RECORD_TIME_SEC (10)
#define EXAMPLE_SD_MOUNT_POINT "/sdcard"
#define EXAMPLE_RECORD_FILE_PATH "/RECORD.WAV"
#define RECORD_TIME_SEC (60)
#define SD_MOUNT_POINT "/sdcard"
static const char* TAG = "example";
static const char* TAG = "main";
static char* record_file_name = NULL;
static i2s_chan_handle_t es7210_i2s_init(void) {
i2s_chan_handle_t i2s_rx_chan = NULL; // 定义接收通道句柄
@ -66,16 +72,15 @@ static i2s_chan_handle_t es7210_i2s_init(void) {
// 定义接收通道为I2S TDM模式 并配置
i2s_tdm_config_t i2s_tdm_rx_conf = {
.slot_cfg = I2S_TDM_PHILIPS_SLOT_DEFAULT_CONFIG(
EXAMPLE_I2S_SAMPLE_BITS, I2S_SLOT_MODE_STEREO,
EXAMPLE_I2S_TDM_SLOT_MASK),
I2S_SAMPLE_BITS, I2S_SLOT_MODE_STEREO, I2S_TDM_SLOT_MASK),
.clk_cfg = {.clk_src = I2S_CLK_SRC_DEFAULT,
.sample_rate_hz = EXAMPLE_I2S_SAMPLE_RATE,
.mclk_multiple = EXAMPLE_I2S_MCLK_MULTIPLE},
.gpio_cfg = {.mclk = EXAMPLE_I2S_MCK_IO,
.bclk = EXAMPLE_I2S_BCK_IO,
.ws = EXAMPLE_I2S_WS_IO,
.sample_rate_hz = I2S_SAMPLE_RATE,
.mclk_multiple = I2S_MCLK_MULTIPLE},
.gpio_cfg = {.mclk = I2S_MCK_IO,
.bclk = I2S_BCK_IO,
.ws = I2S_WS_IO,
.dout = -1, // ES7210 only has ADC capability
.din = EXAMPLE_I2S_DI_IO},
.din = I2S_DI_IO},
};
ESP_ERROR_CHECK(i2s_channel_init_tdm_mode(
@ -100,17 +105,17 @@ sdmmc_card_t* mount_sdcard(void) {
sdmmc_slot_config_t slot_config =
SDMMC_SLOT_CONFIG_DEFAULT(); // SDMMC插槽配置
slot_config.width = 1; // 设置为1线SD模式
slot_config.clk = EXAMPLE_SD_CLK_IO;
slot_config.cmd = EXAMPLE_SD_CMD_IO;
slot_config.d0 = EXAMPLE_SD_DAT0_IO;
slot_config.clk = SD_CLK_IO;
slot_config.cmd = SD_CMD_IO;
slot_config.d0 = SD_DAT0_IO;
slot_config.flags |= SDMMC_SLOT_FLAG_INTERNAL_PULLUP; // 打开内部上拉电阻
ESP_LOGI(TAG, "Mounting filesystem");
esp_err_t ret;
while (1) {
ret = esp_vfs_fat_sdmmc_mount(EXAMPLE_SD_MOUNT_POINT, &sdmmc_host,
&slot_config, &mount_config, &sdmmc_card);
ret = esp_vfs_fat_sdmmc_mount(SD_MOUNT_POINT, &sdmmc_host, &slot_config,
&mount_config, &sdmmc_card);
if (ret == ESP_OK) {
break;
} else if (ret == ESP_FAIL) {
@ -134,23 +139,110 @@ sdmmc_card_t* mount_sdcard(void) {
static void es7210_codec_init(void) {
// 创建es7210器件句柄
es7210_dev_handle_t es7210_handle = NULL;
es7210_i2c_config_t es7210_i2c_conf = {.i2c_port = EXAMPLE_I2C_NUM,
.i2c_addr = EXAMPLE_ES7210_I2C_ADDR};
es7210_i2c_config_t es7210_i2c_conf = {.i2c_port = I2C_NUM,
.i2c_addr = ES7210_I2C_ADDR};
ESP_ERROR_CHECK(es7210_new_codec(&es7210_i2c_conf, &es7210_handle));
// 初始化es7210芯片
ESP_LOGI(TAG, "Configure ES7210 codec parameters");
es7210_codec_config_t codec_conf = {
.i2s_format = EXAMPLE_I2S_TDM_FORMAT,
.mclk_ratio = EXAMPLE_I2S_MCLK_MULTIPLE,
.sample_rate_hz = EXAMPLE_I2S_SAMPLE_RATE,
.bit_width = (es7210_i2s_bits_t)EXAMPLE_I2S_SAMPLE_BITS,
.mic_bias = EXAMPLE_ES7210_MIC_BIAS,
.mic_gain = EXAMPLE_ES7210_MIC_GAIN,
.i2s_format = I2S_TDM_FORMAT,
.mclk_ratio = I2S_MCLK_MULTIPLE,
.sample_rate_hz = I2S_SAMPLE_RATE,
.bit_width = (es7210_i2s_bits_t)I2S_SAMPLE_BITS,
.mic_bias = ES7210_MIC_BIAS,
.mic_gain = ES7210_MIC_GAIN,
.flags.tdm_enable = true};
ESP_ERROR_CHECK(es7210_config_codec(es7210_handle, &codec_conf));
ESP_ERROR_CHECK(
es7210_config_volume(es7210_handle, EXAMPLE_ES7210_ADC_VOLUME));
ESP_ERROR_CHECK(es7210_config_volume(es7210_handle, ES7210_ADC_VOLUME));
}
// wifi事件组
static EventGroupHandle_t s_wifi_event_group = NULL;
// wifi事件
#define WIFI_CONNECTED_BIT BIT0
#define WIFI_FAIL_BIT BIT1
#define WIFI_START_BIT BIT2
#define WIFI_GET_SNTP_BIT BIT3
// wifi最大重连次数
#define EXAMPLE_ESP_MAXIMUM_RETRY 3
typedef struct {
char wifi_ssid[32]; // 获取wifi名称
char wifi_password[64]; // 获取wifi密码
char back_flag; // 是否退出
} wifi_account_t;
static void wifi_connect() {
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
assert(esp_netif_create_default_wifi_sta());
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
// ESP_ERROR_CHECK(esp_event_handler_instance_register(
// WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL, &instance_any_id));
// ESP_ERROR_CHECK(esp_event_handler_instance_register(
// IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL,
// &instance_got_ip));
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
wifi_account_t wifi_account;
strcpy(wifi_account.wifi_ssid, "Liang");
strcpy(wifi_account.wifi_password, "wifi1234");
ESP_LOGI(TAG, "connected to ap SSID:%s password:%s", wifi_account.wifi_ssid,
wifi_account.wifi_password);
wifi_account.back_flag = 0; // 正常连接
wifi_config_t wifi_config = {
.sta =
{
.threshold.authmode = WIFI_AUTH_WPA2_PSK,
.sae_pwe_h2e = WPA3_SAE_PWE_BOTH,
.sae_h2e_identifier = "",
},
};
strcpy((char*)wifi_config.sta.ssid, wifi_account.wifi_ssid);
strcpy((char*)wifi_config.sta.password, wifi_account.wifi_password);
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));
ESP_ERROR_CHECK(esp_wifi_start());
esp_wifi_connect();
}
time_t now;
struct tm timeinfo;
static void get_time_task() {
esp_sntp_config_t config = ESP_NETIF_SNTP_DEFAULT_CONFIG("cn.pool.ntp.org");
esp_netif_sntp_init(&config);
// wait for time to be set
int retry = 0;
// const int retry_count = 6;
while (esp_netif_sntp_sync_wait(2000 / portTICK_PERIOD_MS) ==
ESP_ERR_TIMEOUT) {
ESP_LOGI(TAG, "Waiting for system time to be set... (%d)", retry++);
}
esp_netif_sntp_deinit();
// 设置时区
setenv("TZ", "CST-8", 1);
tzset();
// 获取系统时间
time(&now);
localtime_r(&now, &timeinfo);
ESP_LOGI(TAG, "%d年%02d月%02d日", timeinfo.tm_year + 1900,
timeinfo.tm_mon + 1, timeinfo.tm_mday);
ESP_LOGI(TAG, "%02d:%02d:%02d", timeinfo.tm_hour, timeinfo.tm_min,
timeinfo.tm_sec);
}
static char* get_file_name_from_time(void) {
get_time_task();
strftime(record_file_name, 48, "/sdcard/Record_%Y%m%d%H%M%S.wav", &timeinfo);
return record_file_name;
}
static esp_err_t record_wav(i2s_chan_handle_t i2s_rx_chan) {
@ -158,19 +250,18 @@ static esp_err_t record_wav(i2s_chan_handle_t i2s_rx_chan) {
"invalid i2s channel handle pointer");
esp_err_t ret = ESP_OK;
uint32_t byte_rate = EXAMPLE_I2S_SAMPLE_RATE * EXAMPLE_I2S_CHAN_NUM *
EXAMPLE_I2S_SAMPLE_BITS / 8;
uint32_t wav_size = byte_rate * EXAMPLE_RECORD_TIME_SEC;
uint32_t byte_rate = I2S_SAMPLE_RATE * I2S_CHAN_NUM * I2S_SAMPLE_BITS / 8;
uint32_t wav_size = byte_rate * RECORD_TIME_SEC;
const wav_header_t wav_header =
WAV_HEADER_PCM_DEFAULT(wav_size, EXAMPLE_I2S_SAMPLE_BITS,
EXAMPLE_I2S_SAMPLE_RATE, EXAMPLE_I2S_CHAN_NUM);
const wav_header_t wav_header = WAV_HEADER_PCM_DEFAULT(
wav_size, I2S_SAMPLE_BITS, I2S_SAMPLE_RATE, I2S_CHAN_NUM);
ESP_LOGI(TAG, "Opening file %s", EXAMPLE_RECORD_FILE_PATH);
FILE* f = fopen(EXAMPLE_SD_MOUNT_POINT EXAMPLE_RECORD_FILE_PATH, "w");
get_file_name_from_time();
ESP_LOGI(TAG, "Opening file %s", record_file_name);
FILE* f = fopen(record_file_name, "w");
ESP_LOGI(TAG, "fopen error: %s", strerror(errno));
ESP_RETURN_ON_FALSE(f, ESP_FAIL, TAG, "error while opening wav file");
/* Write wav header */
ESP_GOTO_ON_FALSE(fwrite(&wav_header, sizeof(wav_header_t), 1, f), ESP_FAIL,
err, TAG, "error while writing wav header");
@ -182,7 +273,7 @@ static esp_err_t record_wav(i2s_chan_handle_t i2s_rx_chan) {
while (wav_written < wav_size) {
if (wav_written % byte_rate < sizeof(i2s_readraw_buff)) {
ESP_LOGI(TAG, "Recording: %" PRIu32 "/%ds", wav_written / byte_rate + 1,
EXAMPLE_RECORD_TIME_SEC);
RECORD_TIME_SEC);
}
size_t bytes_read = 0;
/* Read RAW samples from ES7210 */
@ -205,33 +296,43 @@ err:
}
void app_main(void) {
bsp_i2c_init(); // I2C初始化
pca9557_init(); // IO扩展芯片初始化
bsp_lvgl_start(); // 初始化液晶屏lvgl接口
// Initialize NVS.
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES ||
ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
}
ESP_ERROR_CHECK(ret);
bsp_i2c_init(); // I2C初始化
// pca9557_init(); // IO扩展芯片初始化
// bsp_lvgl_start(); // 初始化液晶屏lvgl接口
bsp_spiffs_mount(); // SPIFFS文件系统初始化
bsp_codec_init(); // 音频初始化
mp3_player_init(); // MP3播放器初始化
// bsp_codec_init(); // 音频初始化
// mp3_player_init(); // MP3播放器初始化
app_sr_init(); // 语音识别初始化
/* 初始化I2S接口 */
i2s_chan_handle_t i2s_rx_chan = es7210_i2s_init();
/* 初始化es7210芯片 */
es7210_codec_init();
/* 挂载SD卡 */
wifi_connect();
record_file_name = malloc(64);
sdmmc_card_t* sdmmc_card = mount_sdcard();
/* 录音 */
esp_err_t err = record_wav(i2s_rx_chan);
/* 弹出SD卡 */
esp_vfs_fat_sdcard_unmount(EXAMPLE_SD_MOUNT_POINT, sdmmc_card);
if (err == ESP_OK) {
ESP_LOGI(TAG,
"Audio was successfully recorded into " EXAMPLE_RECORD_FILE_PATH
". You can now remove the SD card safely");
} else {
ESP_LOGE(TAG, "Record failed, " EXAMPLE_RECORD_FILE_PATH
" on SD card may not be playable.");
while (1) {
esp_err_t err = record_wav(i2s_rx_chan);
if (err == ESP_OK) {
ESP_LOGI(TAG, "Audio was successfully recorded into %s.",
record_file_name);
} else {
ESP_LOGE(TAG, "Record failed, %s .", record_file_name);
}
}
esp_vfs_fat_sdcard_unmount(SD_MOUNT_POINT, sdmmc_card);
}

View File

@ -3,6 +3,11 @@
#
CONFIG_IDF_TARGET="esp32s3"
CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y
CONFIG_FATFS_LFN_HEAP=y
CONFIG_FATFS_CODEPAGE_936=y
CONFIG_FATFS_API_ENCODING_UTF_8=y
CONFIG_FATFS_VFS_FSTAT_BLKSIZE=4096
CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_SPIRAM=y
CONFIG_SPIRAM_MODE_OCT=y