esp32-s3-eye

pull/216/head
yehangyang 2022-03-02 19:38:29 +08:00
parent 28f4f14ab6
commit 0684cc5db3
22 changed files with 1724 additions and 0 deletions

View File

@ -0,0 +1,8 @@
# The following lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)
set(EXTRA_COMPONENT_DIRS ../../components)
add_compile_options(-fdiagnostics-color=always)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(esp32-s3-eye)

View File

@ -0,0 +1,65 @@
# ESP-S3-EYE 示例说明
## 交互系统
### 语音
语音交互逻辑遵循“先说唤醒词,再说命令词”。
### 按键
####
## 工作模式
该示例共包含四个工作模式:“待机模式”、“实时显示”、“人脸识别”和“移动侦测”。下面对这四个模式做简要介绍。
### 待机模式
待机模式下LCD 屏幕上仅显示 Espressif Logo。该模式也是开发板上电以后的默认模式。
### 实时显示
实时显示模式下LCD 屏幕上会实时显示摄像头采集的图片。
### 人脸识别
人脸识别模式下LCD 屏幕上会实时显示摄像头采集的图片。并且实时检测画面中的人脸,并显示检测框和关键点。通过按键和语音交互可以实现人脸识别相关的操作,详见下表:
| 操作 | 说明 | 按键触发 | 语音触发 |
| :------: | :------------------------------------------: | :------: | :------------------------------------: |
| 识别人脸 | 识别当前画面中的人脸,并显示识别结果 | “PLAY” | “Hi乐鑫”唤醒后说出命令词“识别一下” |
| 添加人脸 | 添加当前画面中的人脸,并显示添加的 ID 号 | “UP” | “Hi乐鑫”唤醒后说出命令词“添加人脸” |
| 删除人脸 | 删除人脸库中的最后一个 ID 并显示剩余 ID 数 | “DOWN” | “Hi乐鑫”唤醒后说出命令词“删除人脸” |
### 移动侦测
移动侦测模式下LCD 屏幕上会实时显示摄像头采集的图片。并且实时检测画面中是否出现物体移动,如果物体移动,画面左上角会显示蓝点。
#### 进入默认固件
上电后等待3秒不对开发板做任何操作当LCD屏幕显示Espressif LOGO表示已进入默认固件。
#### 默认固件模式
默认固件存在四种运行模式,固件会默认先进入人脸识别模式:
1. 待机模式该模式下开发板只有LCD工作显示公司LOGO。
2. 实时显示模式该模式下LCD会实时显示摄像头拍摄到的画面。
3. 人脸识别模式该模式下LCD会实时显示摄像头拍摄到的画面如果画面中存在人脸LCD显示的画面上会框出人脸并画出人脸的五个特征点。该模式下提供三种功能录入人脸、识别人脸、删除人脸。
- 录入人脸: 按下MENU键。或者使用“Hi乐鑫”唤醒词唤醒唤醒后摄像头旁的LED会被点亮随后说出“添加人脸”。
- 识别人脸: 按下UP键。或者使用“Hi乐鑫”唤醒词唤醒唤醒后摄像头旁的LED会被点亮随后说出“识别一下”。
- 删除人脸: 按下PLAY键。或者使用“Hi乐鑫”唤醒词唤醒唤醒后摄像头旁的LED会被点亮随后说出“删除人脸”。
4. 移动侦测模式: 该模式下LCD会实时显示摄像头拍摄到的画面。若画面中存在物体移动LCD中左上角会显示蓝色色块。
#### 模式切换
在任何时候都可以使用“Hi乐鑫”唤醒词唤醒开发板四种模式分别对应四个命令词。说出相应的命令词识别成功后随即切换到对应的模式。工作模式与命令词的对应关系如下
1. 待机模式:“停止工作”
2. 实时显示模式:“仅显示”
3. 人脸识别模式:“人脸识别”
4. 移动侦测模式:“移动侦测”
#### 语音系统
- 语音唤醒默认固件工作时任何时刻都可以使用“Hi乐鑫”唤醒词唤醒开发板。开发板被唤醒后摄像头旁的LED会常亮。
- 命令词识别唤醒后会等待用户说出命令词。若识别成功摄像头旁的LED会从常亮变为闪烁一秒, LED会随后熄灭。

View File

@ -0,0 +1,11 @@
set(src_dirs .
src)
set(include_dirs include
.)
set(requires console
esp_adc_cal
)
idf_component_register(SRC_DIRS ${src_dirs} INCLUDE_DIRS ${include_dirs})

View File

@ -0,0 +1,13 @@
menu "ESP32-S3-EYE Firmware"
choice ESP_SR_LANGUAGE
bool "esp-sr language"
default CN_MODEL
help
Select ESP-SR Language.
config CN_MODEL
bool "Chinese"
config EN_MODEL
bool "English"
endchoice
endmenu

View File

@ -0,0 +1,50 @@
#include "sdkconfig.h"
#include "driver/gpio.h"
#if CONFIG_FREERTOS_VTASKLIST_INCLUDE_COREID
#include "who_trace.h"
#endif
#include "app_buttom.hpp"
#include "app_camera.hpp"
#include "app_lcd.hpp"
#include "app_led.hpp"
#include "app_motion.hpp"
#include "app_speech.hpp"
#include "app_face.hpp"
extern "C" void app_main()
{
#if CONFIG_FREERTOS_VTASKLIST_INCLUDE_COREID
register_trace();
#endif
QueueHandle_t xQueueFrame_0 = xQueueCreate(2, sizeof(camera_fb_t *));
QueueHandle_t xQueueFrame_1 = xQueueCreate(2, sizeof(camera_fb_t *));
QueueHandle_t xQueueFrame_2 = xQueueCreate(2, sizeof(camera_fb_t *));
AppButtom *key = new AppButtom();
AppSpeech *speech = new AppSpeech();
AppCamera *camera = new AppCamera(PIXFORMAT_RGB565, FRAMESIZE_240X240, 2, xQueueFrame_0);
AppFace *face = new AppFace(key, speech, xQueueFrame_0, xQueueFrame_1);
AppMotion *motion = new AppMotion(key, speech, xQueueFrame_1, xQueueFrame_2);
AppLCD *lcd = new AppLCD(key, speech, xQueueFrame_2);
LED *led = new LED(GPIO_NUM_3, key, speech);
key->attach(face);
key->attach(motion);
key->attach(led);
key->attach(lcd);
speech->attach(face);
speech->attach(motion);
speech->attach(led);
speech->attach(lcd);
lcd->run();
motion->run();
face->run();
camera->run();
speech->run();
key->run();
}

View File

@ -0,0 +1,79 @@
#pragma once
#include <list>
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "esp_camera.h"
typedef enum
{
COMMAND_TIMEOUT = -2,
COMMAND_NOT_DETECTED = -1,
MENU_STOP_WORKING = 0,
MENU_DISPLAY_ONLY = 1,
MENU_FACE_RECOGNITION = 2,
MENU_MOTION_DETECTION = 3,
ACTION_ENROLL = 4,
ACTION_DELETE = 5,
ACTION_RECOGNIZE = 6
} command_word_t;
class Observer
{
public:
virtual void update() = 0;
};
class Subject
{
private:
std::list<Observer *> observers;
public:
void attach(Observer *observer)
{
this->observers.push_back(observer);
}
void detach(Observer *observer)
{
this->observers.remove(observer);
}
void detach_all()
{
this->observers.clear();
}
void notify()
{
for (auto observer : this->observers)
observer->update();
}
};
class Frame
{
public:
QueueHandle_t queue_i;
QueueHandle_t queue_o;
void (*callback)(camera_fb_t *);
Frame(QueueHandle_t queue_i = nullptr,
QueueHandle_t queue_o = nullptr,
void (*callback)(camera_fb_t *) = nullptr) : queue_i(queue_i),
queue_o(queue_o),
callback(callback) {}
void set_io(QueueHandle_t queue_i, QueueHandle_t queue_o)
{
this->queue_i = queue_i;
this->queue_o = queue_o;
}
};

View File

@ -0,0 +1,35 @@
#pragma once
#include <vector>
#include "__base__.hpp"
typedef enum
{
_IDLE = 0,
_MENU,
_PLAY,
_UP,
_DOWN
} _key_name_t;
typedef struct
{
_key_name_t key; /**< button index on the channel */
int min; /**< min voltage in mv corresponding to the button */
int max; /**< max voltage in mv corresponding to the button */
} key_config_t;
class AppButtom : public Subject
{
public:
std::vector<key_config_t> key_configs;
_key_name_t pressed;
uint8_t menu;
AppButtom();
~AppButtom();
void run();
};

View File

@ -0,0 +1,210 @@
#pragma once
#include <list>
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "esp_camera.h"
#include "__base__.hpp"
#if CONFIG_CAMERA_MODULE_WROVER_KIT
#define CAMERA_MODULE_NAME "Wrover Kit"
#define CAMERA_PIN_PWDN -1
#define CAMERA_PIN_RESET -1
#define CAMERA_PIN_XCLK 21
#define CAMERA_PIN_SIOD 26
#define CAMERA_PIN_SIOC 27
#define CAMERA_PIN_D7 35
#define CAMERA_PIN_D6 34
#define CAMERA_PIN_D5 39
#define CAMERA_PIN_D4 36
#define CAMERA_PIN_D3 19
#define CAMERA_PIN_D2 18
#define CAMERA_PIN_D1 5
#define CAMERA_PIN_D0 4
#define CAMERA_PIN_VSYNC 25
#define CAMERA_PIN_HREF 23
#define CAMERA_PIN_PCLK 22
#elif CONFIG_CAMERA_MODULE_ESP_EYE
#define CAMERA_MODULE_NAME "ESP-EYE"
#define CAMERA_PIN_PWDN -1
#define CAMERA_PIN_RESET -1
#define CAMERA_PIN_XCLK 4
#define CAMERA_PIN_SIOD 18
#define CAMERA_PIN_SIOC 23
#define CAMERA_PIN_D7 36
#define CAMERA_PIN_D6 37
#define CAMERA_PIN_D5 38
#define CAMERA_PIN_D4 39
#define CAMERA_PIN_D3 35
#define CAMERA_PIN_D2 14
#define CAMERA_PIN_D1 13
#define CAMERA_PIN_D0 34
#define CAMERA_PIN_VSYNC 5
#define CAMERA_PIN_HREF 27
#define CAMERA_PIN_PCLK 25
#elif CONFIG_CAMERA_MODULE_ESP_S2_KALUGA
#define CAMERA_MODULE_NAME "ESP-S2-KALUGA"
#define CAMERA_PIN_PWDN -1
#define CAMERA_PIN_RESET -1
#define CAMERA_PIN_XCLK 1
#define CAMERA_PIN_SIOD 8
#define CAMERA_PIN_SIOC 7
#define CAMERA_PIN_D7 38
#define CAMERA_PIN_D6 21
#define CAMERA_PIN_D5 40
#define CAMERA_PIN_D4 39
#define CAMERA_PIN_D3 42
#define CAMERA_PIN_D2 41
#define CAMERA_PIN_D1 37
#define CAMERA_PIN_D0 36
#define CAMERA_PIN_VSYNC 2
#define CAMERA_PIN_HREF 3
#define CAMERA_PIN_PCLK 33
#elif CONFIG_CAMERA_MODULE_ESP_S3_EYE
#define CAMERA_MODULE_NAME "ESP-S3-EYE"
#define CAMERA_PIN_PWDN -1
#define CAMERA_PIN_RESET -1
#define CAMERA_PIN_VSYNC 6
#define CAMERA_PIN_HREF 7
#define CAMERA_PIN_PCLK 13
#define CAMERA_PIN_XCLK 15
#define CAMERA_PIN_SIOD 4
#define CAMERA_PIN_SIOC 5
#define CAMERA_PIN_D0 11
#define CAMERA_PIN_D1 9
#define CAMERA_PIN_D2 8
#define CAMERA_PIN_D3 10
#define CAMERA_PIN_D4 12
#define CAMERA_PIN_D5 18
#define CAMERA_PIN_D6 17
#define CAMERA_PIN_D7 16
#elif CONFIG_CAMERA_MODEL_ESP32_CAM_BOARD
#define CAMERA_MODULE_NAME "ESP-DEVCAM"
#define CAMERA_PIN_PWDN 32
#define CAMERA_PIN_RESET 33
#define CAMERA_PIN_XCLK 4
#define CAMERA_PIN_SIOD 18
#define CAMERA_PIN_SIOC 23
#define CAMERA_PIN_D7 36
#define CAMERA_PIN_D6 19
#define CAMERA_PIN_D5 21
#define CAMERA_PIN_D4 39
#define CAMERA_PIN_D3 35
#define CAMERA_PIN_D2 14
#define CAMERA_PIN_D1 13
#define CAMERA_PIN_D0 34
#define CAMERA_PIN_VSYNC 5
#define CAMERA_PIN_HREF 27
#define CAMERA_PIN_PCLK 25
#elif CONFIG_CAMERA_MODULE_M5STACK_PSRAM
#define CAMERA_MODULE_NAME "M5STACK-PSRAM"
#define CAMERA_PIN_PWDN -1
#define CAMERA_PIN_RESET 15
#define CAMERA_PIN_XCLK 27
#define CAMERA_PIN_SIOD 25
#define CAMERA_PIN_SIOC 23
#define CAMERA_PIN_D7 19
#define CAMERA_PIN_D6 36
#define CAMERA_PIN_D5 18
#define CAMERA_PIN_D4 39
#define CAMERA_PIN_D3 5
#define CAMERA_PIN_D2 34
#define CAMERA_PIN_D1 35
#define CAMERA_PIN_D0 32
#define CAMERA_PIN_VSYNC 22
#define CAMERA_PIN_HREF 26
#define CAMERA_PIN_PCLK 21
#elif CONFIG_CAMERA_MODULE_M5STACK_WIDE
#define CAMERA_MODULE_NAME "M5STACK-WIDE"
#define CAMERA_PIN_PWDN -1
#define CAMERA_PIN_RESET 15
#define CAMERA_PIN_XCLK 27
#define CAMERA_PIN_SIOD 22
#define CAMERA_PIN_SIOC 23
#define CAMERA_PIN_D7 19
#define CAMERA_PIN_D6 36
#define CAMERA_PIN_D5 18
#define CAMERA_PIN_D4 39
#define CAMERA_PIN_D3 5
#define CAMERA_PIN_D2 34
#define CAMERA_PIN_D1 35
#define CAMERA_PIN_D0 32
#define CAMERA_PIN_VSYNC 25
#define CAMERA_PIN_HREF 26
#define CAMERA_PIN_PCLK 21
#elif CONFIG_CAMERA_MODULE_AI_THINKER
#define CAMERA_MODULE_NAME "AI-THINKER"
#define CAMERA_PIN_PWDN 32
#define CAMERA_PIN_RESET -1
#define CAMERA_PIN_XCLK 0
#define CAMERA_PIN_SIOD 26
#define CAMERA_PIN_SIOC 27
#define CAMERA_PIN_D7 35
#define CAMERA_PIN_D6 34
#define CAMERA_PIN_D5 39
#define CAMERA_PIN_D4 36
#define CAMERA_PIN_D3 21
#define CAMERA_PIN_D2 19
#define CAMERA_PIN_D1 18
#define CAMERA_PIN_D0 5
#define CAMERA_PIN_VSYNC 25
#define CAMERA_PIN_HREF 23
#define CAMERA_PIN_PCLK 22
#elif CONFIG_CAMERA_MODULE_CUSTOM
#define CAMERA_MODULE_NAME "CUSTOM"
#define CAMERA_PIN_PWDN CONFIG_CAMERA_PIN_PWDN
#define CAMERA_PIN_RESET CONFIG_CAMERA_PIN_RESET
#define CAMERA_PIN_XCLK CONFIG_CAMERA_PIN_XCLK
#define CAMERA_PIN_SIOD CONFIG_CAMERA_PIN_SIOD
#define CAMERA_PIN_SIOC CONFIG_CAMERA_PIN_SIOC
#define CAMERA_PIN_D7 CONFIG_CAMERA_PIN_Y9
#define CAMERA_PIN_D6 CONFIG_CAMERA_PIN_Y8
#define CAMERA_PIN_D5 CONFIG_CAMERA_PIN_Y7
#define CAMERA_PIN_D4 CONFIG_CAMERA_PIN_Y6
#define CAMERA_PIN_D3 CONFIG_CAMERA_PIN_Y5
#define CAMERA_PIN_D2 CONFIG_CAMERA_PIN_Y4
#define CAMERA_PIN_D1 CONFIG_CAMERA_PIN_Y3
#define CAMERA_PIN_D0 CONFIG_CAMERA_PIN_Y2
#define CAMERA_PIN_VSYNC CONFIG_CAMERA_PIN_VSYNC
#define CAMERA_PIN_HREF CONFIG_CAMERA_PIN_HREF
#define CAMERA_PIN_PCLK CONFIG_CAMERA_PIN_PCLK
#endif
#define XCLK_FREQ_HZ 15000000
class AppCamera : public Frame
{
public:
AppCamera(const pixformat_t pixel_fromat,
const framesize_t frame_size,
const uint8_t fb_count,
QueueHandle_t queue_o = nullptr);
void run();
};

View File

@ -0,0 +1,58 @@
#pragma once
#include "human_face_detect_msr01.hpp"
#include "human_face_detect_mnp01.hpp"
#include "face_recognition_tool.hpp"
// #if CONFIG_MFN_V1_Q8
// #include "face_recognition_112_v1_s8.hpp"
// #elif CONFIG_MFN_V1_Q16
#include "face_recognition_112_v1_s16.hpp"
// #endif
#include "__base__.hpp"
#include "app_camera.hpp"
#include "app_buttom.hpp"
#include "app_speech.hpp"
typedef enum
{
IDLE = 0,
ENROLL = 1,
RECOGNIZE = 2,
DELETE = 3,
} recognizer_state_t;
class AppFace : public Observer, public Frame
{
private:
AppButtom *key;
AppSpeech *speech;
public:
HumanFaceDetectMSR01 detector;
HumanFaceDetectMNP01 detector2;
// #if CONFIG_MFN_V1_Q8
// FaceRecognition112V1S8 *recognizer;
// #elif CONFIG_MFN_V1_Q16
FaceRecognition112V1S16 *recognizer;
// #endif
face_info_t recognize_result;
recognizer_state_t state;
recognizer_state_t state_previous;
bool switch_on;
uint8_t frame_count;
AppFace(AppButtom *key,
AppSpeech *speech,
QueueHandle_t queue_i = nullptr,
QueueHandle_t queue_o = nullptr,
void (*callback)(camera_fb_t *) = esp_camera_fb_return);
~AppFace();
void update();
void run();
};

View File

@ -0,0 +1,51 @@
#pragma once
#include <stdint.h>
#include "esp_log.h"
#include "screen_driver.h"
#include "__base__.hpp"
#include "app_camera.hpp"
#include "app_buttom.hpp"
#include "app_speech.hpp"
#define BOARD_LCD_MOSI 47
#define BOARD_LCD_MISO -1
#define BOARD_LCD_SCK 21
#define BOARD_LCD_CS 44
#define BOARD_LCD_DC 43
#define BOARD_LCD_RST -1
#define BOARD_LCD_BL 48
#define BOARD_LCD_PIXEL_CLOCK_HZ (40 * 1000 * 1000)
#define BOARD_LCD_BK_LIGHT_ON_LEVEL 0
#define BOARD_LCD_BK_LIGHT_OFF_LEVEL !BOARD_LCD_BK_LIGHT_ON_LEVEL
#define BOARD_LCD_H_RES 240
#define BOARD_LCD_V_RES 240
#define BOARD_LCD_CMD_BITS 8
#define BOARD_LCD_PARAM_BITS 8
#define LCD_HOST SPI2_HOST
class AppLCD : public Observer, public Frame
{
private:
AppButtom *key;
AppSpeech *speech;
public:
scr_driver_t driver;
bool switch_on;
bool paper_drawn;
AppLCD(AppButtom *key,
AppSpeech *speech,
QueueHandle_t xQueueFrameI = nullptr,
QueueHandle_t xQueueFrameO = nullptr,
void (*callback)(camera_fb_t *) = esp_camera_fb_return);
void draw_wallpaper();
void draw_color(int color);
void update();
void run();
};

View File

@ -0,0 +1,23 @@
#pragma once
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "app_buttom.hpp"
#include "app_speech.hpp"
class LED : public Observer
{
private:
const gpio_num_t pin;
AppButtom *key;
AppSpeech *sr;
public:
LED(const gpio_num_t pin, AppButtom *key, AppSpeech *sr);
~LED();
void update();
};

View File

@ -0,0 +1,26 @@
#pragma once
#include "__base__.hpp"
#include "app_camera.hpp"
#include "app_buttom.hpp"
#include "app_speech.hpp"
class AppMotion : public Observer, public Frame
{
private:
AppButtom *key;
AppSpeech *speech;
public:
bool switch_on;
AppMotion(AppButtom *key,
AppSpeech *speech,
QueueHandle_t queue_i = nullptr,
QueueHandle_t queue_o = nullptr,
void (*callback)(camera_fb_t *) = esp_camera_fb_return);
void update();
void run();
};

View File

@ -0,0 +1,23 @@
#pragma once
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "esp_afe_sr_iface.h"
#include "__base__.hpp"
class AppSpeech : public Subject
{
public:
const esp_afe_sr_iface_t *afe_handle;
esp_afe_sr_data_t *afe_data;
bool detected;
command_word_t command;
AppSpeech();
void run();
};

View File

@ -0,0 +1,79 @@
#include "app_buttom.hpp"
#include <stdio.h>
#include <stdlib.h>
#include "driver/adc_common.h"
#include "esp_log.h"
#include "esp_adc_cal.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
// ADC Channels
#define ADC1_EXAMPLE_CHAN0 ADC1_CHANNEL_0
// ADC Attenuation
#define ADC_EXAMPLE_ATTEN ADC_ATTEN_DB_11
// ADC Calibration
#if CONFIG_IDF_TARGET_ESP32
#define ADC_EXAMPLE_CALI_SCHEME ESP_ADC_CAL_VAL_EFUSE_VREF
#elif CONFIG_IDF_TARGET_ESP32S2
#define ADC_EXAMPLE_CALI_SCHEME ESP_ADC_CAL_VAL_EFUSE_TP
#elif CONFIG_IDF_TARGET_ESP32C3
#define ADC_EXAMPLE_CALI_SCHEME ESP_ADC_CAL_VAL_EFUSE_TP
#elif CONFIG_IDF_TARGET_ESP32S3
#define ADC_EXAMPLE_CALI_SCHEME ESP_ADC_CAL_VAL_EFUSE_TP_FIT
#endif
#define PRESS_INTERVAL 500000
static const char *TAG = "App/Buttom";
AppButtom::AppButtom() : key_configs({{_MENU, 2800, 3000}, {_PLAY, 2250, 2450}, {_UP, 300, 500}, {_DOWN, 850, 1050}}),
pressed(_IDLE)
{
ESP_ERROR_CHECK(adc1_config_width((adc_bits_width_t)ADC_WIDTH_BIT_DEFAULT));
ESP_ERROR_CHECK(adc1_config_channel_atten(ADC1_EXAMPLE_CHAN0, ADC_EXAMPLE_ATTEN));
}
static void task(AppButtom *self)
{
int64_t backup_time = esp_timer_get_time();
int64_t last_time = esp_timer_get_time();
uint8_t menu_count = 0;
while (true)
{
uint32_t voltage = adc1_get_raw(ADC1_EXAMPLE_CHAN0);
backup_time = esp_timer_get_time();
for (auto key_config : self->key_configs)
{
if ((voltage >= key_config.min) && (voltage <= key_config.max))
{
if (((backup_time - last_time) > PRESS_INTERVAL))
{
ESP_LOGD(TAG, "Key[%d] is pressed", self->pressed);
self->pressed = key_config.key;
if (self->pressed == _MENU)
{
self->menu++;
self->menu %= (MENU_MOTION_DETECTION + 1);
}
last_time = backup_time;
self->notify();
self->pressed = _IDLE;
break;
}
}
}
vTaskDelay(pdMS_TO_TICKS(10));
}
}
void AppButtom::run()
{
xTaskCreatePinnedToCore((TaskFunction_t)task, TAG, 3 * 1024, this, 5, NULL, 0);
}

View File

@ -0,0 +1,98 @@
#include "app_camera.hpp"
#include "assert.h"
#include "esp_log.h"
#include "esp_system.h"
const static char TAG[] = "App/Camera";
AppCamera::AppCamera(const pixformat_t pixel_fromat,
const framesize_t frame_size,
const uint8_t fb_count,
QueueHandle_t queue_o) : Frame(nullptr, queue_o, nullptr)
{
ESP_LOGI(TAG, "Camera module is %s", CAMERA_MODULE_NAME);
#if CONFIG_CAMERA_MODEL_ESP_EYE || CONFIG_CAMERA_MODEL_ESP32_CAM_BOARD
/* IO13, IO14 is designed for JTAG by default,
* to use it as generalized input,
* firstly declair it as pullup input */
gpio_config_t conf;
conf.mode = GPIO_MODE_INPUT;
conf.pull_up_en = GPIO_PULLUP_ENABLE;
conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
conf.intr_type = GPIO_INTR_DISABLE;
conf.pin_bit_mask = 1LL << 13;
gpio_config(&conf);
conf.pin_bit_mask = 1LL << 14;
gpio_config(&conf);
#endif
camera_config_t config;
config.ledc_channel = LEDC_CHANNEL_0;
config.ledc_timer = LEDC_TIMER_0;
config.pin_d0 = CAMERA_PIN_D0;
config.pin_d1 = CAMERA_PIN_D1;
config.pin_d2 = CAMERA_PIN_D2;
config.pin_d3 = CAMERA_PIN_D3;
config.pin_d4 = CAMERA_PIN_D4;
config.pin_d5 = CAMERA_PIN_D5;
config.pin_d6 = CAMERA_PIN_D6;
config.pin_d7 = CAMERA_PIN_D7;
config.pin_xclk = CAMERA_PIN_XCLK;
config.pin_pclk = CAMERA_PIN_PCLK;
config.pin_vsync = CAMERA_PIN_VSYNC;
config.pin_href = CAMERA_PIN_HREF;
config.pin_sscb_sda = CAMERA_PIN_SIOD;
config.pin_sscb_scl = CAMERA_PIN_SIOC;
config.pin_pwdn = CAMERA_PIN_PWDN;
config.pin_reset = CAMERA_PIN_RESET;
config.xclk_freq_hz = XCLK_FREQ_HZ;
config.pixel_format = pixel_fromat;
config.frame_size = frame_size;
config.jpeg_quality = 12;
config.fb_count = fb_count;
config.fb_location = CAMERA_FB_IN_PSRAM;
config.grab_mode = CAMERA_GRAB_WHEN_EMPTY;
// camera init
esp_err_t err = esp_camera_init(&config);
if (err != ESP_OK)
{
ESP_LOGE(TAG, "Camera init failed with error 0x%x", err);
return;
}
sensor_t *s = esp_camera_sensor_get();
s->set_vflip(s, 1); // flip it back
// initial sensors are flipped vertically and colors are a bit saturated
if (s->id.PID == OV3660_PID)
{
s->set_brightness(s, 1); // up the blightness just a bit
s->set_saturation(s, -2); // lower the saturation
}
s->set_sharpness(s, 2);
s->set_awb_gain(s, 2);
}
static void task(AppCamera *self)
{
ESP_LOGD(TAG, "Start");
while (true)
{
if (self->queue_o == nullptr)
break;
camera_fb_t *frame = esp_camera_fb_get();
if (frame)
xQueueSend(self->queue_o, &frame, portMAX_DELAY);
}
ESP_LOGD(TAG, "Stop");
vTaskDelete(NULL);
}
void AppCamera::run()
{
xTaskCreatePinnedToCore((TaskFunction_t)task, TAG, 2 * 1024, this, 5, NULL, 1);
}

View File

@ -0,0 +1,231 @@
#include "app_face.hpp"
#include <list>
#include "esp_log.h"
#include "esp_camera.h"
#include "dl_image.hpp"
#include "fb_gfx.h"
#include "who_ai_utils.hpp"
static const char TAG[] = "App/Face";
#define RGB565_MASK_RED 0xF800
#define RGB565_MASK_GREEN 0x07E0
#define RGB565_MASK_BLUE 0x001F
#define FRAME_DELAY_NUM 16
static void rgb_print(camera_fb_t *fb, uint32_t color, const char *str)
{
fb_gfx_print(fb, (fb->width - (strlen(str) * 14)) / 2, 10, color, str);
}
static int rgb_printf(camera_fb_t *fb, uint32_t color, const char *format, ...)
{
char loc_buf[64];
char *temp = loc_buf;
int len;
va_list arg;
va_list copy;
va_start(arg, format);
va_copy(copy, arg);
len = vsnprintf(loc_buf, sizeof(loc_buf), format, arg);
va_end(copy);
if (len >= sizeof(loc_buf))
{
temp = (char *)malloc(len + 1);
if (temp == NULL)
{
return 0;
}
}
vsnprintf(temp, len + 1, format, arg);
va_end(arg);
rgb_print(fb, color, temp);
if (len > 64)
{
free(temp);
}
return len;
}
AppFace::AppFace(AppButtom *key,
AppSpeech *speech,
QueueHandle_t queue_i,
QueueHandle_t queue_o,
void (*callback)(camera_fb_t *)) : Frame(queue_i, queue_o, callback),
key(key),
speech(speech),
detector(0.3F, 0.3F, 10, 0.3F),
detector2(0.4F, 0.3F, 10),
state(IDLE),
switch_on(false)
// recognizer(
// #if CONFIG_MFN_V1_Q8
// new FaceRecognition112V1S8()
// #elif CONFIG_MFN_V1_Q16
// new FaceRecognition112V1S16()
// #endif
// )
{
// this->recognizer = new FaceRecognition112V1S8();
this->recognizer = new FaceRecognition112V1S16();
this->recognizer->set_partition(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, "fr");
int partition_result = this->recognizer->set_ids_from_flash();
}
AppFace::~AppFace()
{
}
void AppFace::update()
{
// Parse key
if (this->key->pressed > _IDLE)
{
if (this->key->pressed == _MENU)
{
this->switch_on = (this->key->menu == MENU_FACE_RECOGNITION) ? true : false;
ESP_LOGD(TAG, "%s", this->switch_on ? "ON" : "OFF");
}
else if (this->key->pressed == _PLAY)
{
this->state = RECOGNIZE;
}
else if (this->key->pressed == _UP)
{
this->state = ENROLL;
}
else if (this->key->pressed == _DOWN)
{
this->state = DELETE;
}
}
// Parse speech recognition
if (this->speech->command > COMMAND_NOT_DETECTED)
{
if (this->speech->command >= MENU_STOP_WORKING && this->speech->command <= MENU_MOTION_DETECTION)
{
this->switch_on = (this->speech->command == MENU_FACE_RECOGNITION) ? true : false;
ESP_LOGD(TAG, "%s", this->switch_on ? "ON" : "OFF");
}
else if (this->speech->command == ACTION_ENROLL)
{
this->state = ENROLL;
}
else if (this->speech->command == ACTION_RECOGNIZE)
{
this->state = RECOGNIZE;
}
else if (this->speech->command == ACTION_DELETE)
{
this->state = DELETE;
}
}
ESP_LOGD(TAG, "Human face recognition state = %d", this->state);
}
static void task(AppFace *self)
{
ESP_LOGD(TAG, "Start");
camera_fb_t *frame = nullptr;
while (true)
{
if (self->queue_i == nullptr)
break;
if (xQueueReceive(self->queue_i, &frame, portMAX_DELAY))
{
if (self->switch_on)
{
std::list<dl::detect::result_t> &detect_candidates = self->detector.infer((uint16_t *)frame->buf, {(int)frame->height, (int)frame->width, 3});
std::list<dl::detect::result_t> &detect_results = self->detector2.infer((uint16_t *)frame->buf, {(int)frame->height, (int)frame->width, 3}, detect_candidates);
if (detect_results.size())
{
// print_detection_result(detect_results);
draw_detection_result((uint16_t *)frame->buf, frame->height, frame->width, detect_results);
}
if (self->state && detect_results.size() == 1)
{
switch (self->state)
{
case ENROLL:
self->recognizer->enroll_id((uint16_t *)frame->buf, {(int)frame->height, (int)frame->width, 3}, detect_results.front().keypoint, "", true);
ESP_LOGW(TAG, "Enroll ID %d", self->recognizer->get_enrolled_ids().back().id);
break;
case RECOGNIZE:
self->recognize_result = self->recognizer->recognize((uint16_t *)frame->buf, {(int)frame->height, (int)frame->width, 3}, detect_results.front().keypoint);
// print_detection_result(detect_results);
ESP_LOGD(TAG, "Similarity: %f", self->recognize_result.similarity);
if (self->recognize_result.id > 0)
ESP_LOGI(TAG, "Match ID: %d", self->recognize_result.id);
else
ESP_LOGE(TAG, "Match ID: %d", self->recognize_result.id);
break;
case DELETE:
vTaskDelay(10);
self->recognizer->delete_id(true);
ESP_LOGE(TAG, "%d IDs left", self->recognizer->get_enrolled_id_num());
break;
default:
break;
}
self->state_previous = self->state;
self->state = IDLE;
self->frame_count = FRAME_DELAY_NUM;
}
// Write result on several frames of image
if (self->frame_count)
{
switch (self->state_previous)
{
case DELETE:
rgb_printf(frame, RGB565_MASK_RED, "%d IDs left", self->recognizer->get_enrolled_id_num());
break;
case RECOGNIZE:
if (self->recognize_result.id > 0)
rgb_printf(frame, RGB565_MASK_GREEN, "ID %d", self->recognize_result.id);
else
rgb_print(frame, RGB565_MASK_RED, "who ?");
break;
case ENROLL:
rgb_printf(frame, RGB565_MASK_BLUE, "Enroll: ID %d", self->recognizer->get_enrolled_ids().back().id);
break;
default:
break;
}
self->frame_count--;
}
}
if (self->queue_o)
xQueueSend(self->queue_o, &frame, portMAX_DELAY);
else
self->callback(frame);
}
}
ESP_LOGD(TAG, "Stop");
vTaskDelete(NULL);
}
void AppFace::run()
{
xTaskCreatePinnedToCore((TaskFunction_t)task, TAG, 5 * 1024, this, 5, NULL, 0);
}

View File

@ -0,0 +1,178 @@
#include "app_lcd.hpp"
#include <string.h>
#include "esp_camera.h"
#include "esp_lcd_panel_io.h"
#include "esp_lcd_panel_vendor.h"
#include "esp_lcd_panel_ops.h"
#include "driver/spi_master.h"
#include "driver/gpio.h"
#include "logo_en_240x240_lcd.h"
static const char TAG[] = "App/LCD";
AppLCD::AppLCD(AppButtom *key,
AppSpeech *speech,
QueueHandle_t queue_i,
QueueHandle_t queue_o,
void (*callback)(camera_fb_t *)) : Frame(queue_i, queue_o, callback),
key(key),
speech(speech),
switch_on(false)
{
do
{
spi_config_t bus_conf = {
.miso_io_num = (gpio_num_t)BOARD_LCD_MISO,
.mosi_io_num = (gpio_num_t)BOARD_LCD_MOSI,
.sclk_io_num = (gpio_num_t)BOARD_LCD_SCK,
.max_transfer_sz = 2 * 240 * 240 + 10,
};
spi_bus_handle_t spi_bus = spi_bus_create(SPI2_HOST, &bus_conf);
scr_interface_spi_config_t spi_lcd_cfg = {
.spi_bus = spi_bus,
.pin_num_cs = BOARD_LCD_CS,
.pin_num_dc = BOARD_LCD_DC,
.clk_freq = 40 * 1000000,
.swap_data = 0,
};
scr_interface_driver_t *iface_drv;
scr_interface_create(SCREEN_IFACE_SPI, &spi_lcd_cfg, &iface_drv);
if (ESP_OK != scr_find_driver(SCREEN_CONTROLLER_ST7789, &this->driver))
{
ESP_LOGE(TAG, "screen find failed");
break;
}
scr_controller_config_t lcd_cfg = {
.interface_drv = iface_drv,
.pin_num_rst = BOARD_LCD_RST,
.pin_num_bckl = BOARD_LCD_BL,
.rst_active_level = 0,
.bckl_active_level = 0,
.width = 240,
.height = 240,
.offset_hor = 0,
.offset_ver = 0,
.rotate = (scr_dir_t)0,
};
if (ESP_OK != this->driver.init(&lcd_cfg))
{
ESP_LOGE(TAG, "screen initialize failed");
break;
}
scr_info_t lcd_info;
this->driver.get_info(&lcd_info);
ESP_LOGI(TAG, "Screen name:%s | width:%d | height:%d", lcd_info.name, lcd_info.width, lcd_info.height);
this->draw_color(0x000000);
vTaskDelay(pdMS_TO_TICKS(500));
this->draw_wallpaper();
vTaskDelay(pdMS_TO_TICKS(1000));
} while (0);
}
void AppLCD::draw_wallpaper()
{
uint16_t *pixels = (uint16_t *)heap_caps_malloc((logo_en_240x240_lcd_width * logo_en_240x240_lcd_height) * sizeof(uint16_t), MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM);
if (NULL == pixels)
{
ESP_LOGE(TAG, "Memory for bitmap is not enough");
return;
}
memcpy(pixels, logo_en_240x240_lcd, (logo_en_240x240_lcd_width * logo_en_240x240_lcd_height) * sizeof(uint16_t));
this->driver.draw_bitmap(0, 0, logo_en_240x240_lcd_width, logo_en_240x240_lcd_height, (uint16_t *)pixels);
heap_caps_free(pixels);
this->paper_drawn = true;
}
void AppLCD::draw_color(int color)
{
scr_info_t lcd_info;
this->driver.get_info(&lcd_info);
uint16_t *buffer = (uint16_t *)malloc(lcd_info.width * sizeof(uint16_t));
if (buffer)
{
for (size_t i = 0; i < lcd_info.width; i++)
{
buffer[i] = color;
}
for (int y = 0; y < lcd_info.height; y++)
{
this->driver.draw_bitmap(0, y, lcd_info.width, 1, buffer);
}
free(buffer);
}
else
{
ESP_LOGE(TAG, "Memory for bitmap is not enough");
}
}
void AppLCD::update()
{
if (this->key->pressed > _IDLE)
{
if (this->key->pressed == _MENU)
{
this->switch_on = (this->key->menu == MENU_STOP_WORKING) ? false : true;
ESP_LOGD(TAG, "%s", this->switch_on ? "ON" : "OFF");
}
}
if (this->speech->command > COMMAND_NOT_DETECTED)
{
if (this->speech->command >= MENU_STOP_WORKING && this->speech->command <= MENU_MOTION_DETECTION)
{
this->switch_on = (this->speech->command == MENU_STOP_WORKING) ? false : true;
ESP_LOGD(TAG, "%s", this->switch_on ? "ON" : "OFF");
}
}
if (this->switch_on == false)
{
this->paper_drawn = false;
}
}
static void task(AppLCD *self)
{
ESP_LOGD(TAG, "Start");
camera_fb_t *frame = nullptr;
while (true)
{
if (self->queue_i == nullptr)
break;
if (xQueueReceive(self->queue_i, &frame, portMAX_DELAY))
{
if (self->switch_on)
self->driver.draw_bitmap(0, 0, frame->width, frame->height, (uint16_t *)frame->buf);
else if (self->paper_drawn == false)
self->draw_wallpaper();
if (self->queue_o)
xQueueSend(self->queue_o, &frame, portMAX_DELAY);
else
self->callback(frame);
}
}
ESP_LOGD(TAG, "Stop");
self->draw_wallpaper();
vTaskDelete(NULL);
}
void AppLCD::run()
{
xTaskCreatePinnedToCore((TaskFunction_t)task, TAG, 2 * 1024, this, 5, NULL, 0);
}

View File

@ -0,0 +1,124 @@
#include "app_led.hpp"
#include "esp_log.h"
const static char TAG[] = "App/LED";
typedef enum
{
LED_ALWAYS_OFF = 0,
LED_ALWAYS_ON = 1,
LED_OFF_1S = 2,
LED_OFF_2S = 3,
LED_OFF_4S = 4,
LED_ON_1S = 5,
LED_ON_2S = 6,
LED_ON_4S = 7,
LED_BLINK_1S = 8,
LED_BLINK_2S = 9,
LED_BLINK_4S = 10,
} led_mode_t;
LED::LED(const gpio_num_t pin, AppButtom *key, AppSpeech *sr) : pin(pin), key(key), sr(sr)
{
// initialize GPIO
gpio_config_t gpio_conf;
gpio_conf.mode = GPIO_MODE_OUTPUT_OD;
gpio_conf.pull_up_en = GPIO_PULLUP_ENABLE;
gpio_conf.intr_type = GPIO_INTR_DISABLE;
gpio_conf.pin_bit_mask = 1LL << this->pin;
gpio_config(&gpio_conf);
gpio_set_level(this->pin, 0);
}
void LED::update()
{
led_mode_t mode = LED_ALWAYS_OFF;
// parse key
if (this->key->pressed)
{
mode = LED_BLINK_2S;
}
// parse speech recognition
else if (this->sr->detected)
{
if (this->sr->command > COMMAND_NOT_DETECTED)
mode = LED_BLINK_1S;
else
mode = LED_ALWAYS_ON;
}
// do
switch (mode)
{
case LED_ALWAYS_OFF:
gpio_set_level(this->pin, 0);
break;
case LED_ALWAYS_ON:
gpio_set_level(this->pin, 1);
break;
case LED_OFF_1S:
gpio_set_level(this->pin, 0);
vTaskDelay(1000 / portTICK_PERIOD_MS);
gpio_set_level(this->pin, 1);
break;
case LED_OFF_2S:
gpio_set_level(this->pin, 0);
vTaskDelay(2000 / portTICK_PERIOD_MS);
gpio_set_level(this->pin, 1);
break;
case LED_OFF_4S:
gpio_set_level(this->pin, 0);
vTaskDelay(4000 / portTICK_PERIOD_MS);
gpio_set_level(this->pin, 1);
break;
case LED_ON_1S:
gpio_set_level(this->pin, 1);
vTaskDelay(1000 / portTICK_PERIOD_MS);
gpio_set_level(this->pin, 0);
break;
case LED_ON_2S:
gpio_set_level(this->pin, 1);
vTaskDelay(2000 / portTICK_PERIOD_MS);
gpio_set_level(this->pin, 0);
break;
case LED_ON_4S:
gpio_set_level(this->pin, 1);
vTaskDelay(4000 / portTICK_PERIOD_MS);
gpio_set_level(this->pin, 0);
break;
case LED_BLINK_1S:
for (int i = 0; i < 2; ++i)
{
gpio_set_level(this->pin, 1);
vTaskDelay(250 / portTICK_PERIOD_MS);
gpio_set_level(this->pin, 0);
vTaskDelay(250 / portTICK_PERIOD_MS);
}
break;
case LED_BLINK_2S:
for (int i = 0; i < 4; ++i)
{
gpio_set_level(this->pin, 1);
vTaskDelay(250 / portTICK_PERIOD_MS);
gpio_set_level(this->pin, 0);
vTaskDelay(250 / portTICK_PERIOD_MS);
}
break;
case LED_BLINK_4S:
for (int i = 0; i < 8; ++i)
{
gpio_set_level(this->pin, 1);
vTaskDelay(250 / portTICK_PERIOD_MS);
gpio_set_level(this->pin, 0);
vTaskDelay(250 / portTICK_PERIOD_MS);
}
break;
default:
break;
}
}

View File

@ -0,0 +1,82 @@
#include "app_motion.hpp"
#include "assert.h"
#include "esp_log.h"
#include "esp_camera.h"
#include "dl_image.hpp"
static const char TAG[] = "App/Motion";
AppMotion::AppMotion(AppButtom *key,
AppSpeech *speech,
QueueHandle_t queue_i,
QueueHandle_t queue_o,
void (*callback)(camera_fb_t *)) : Frame(queue_i, queue_o, callback),
key(key),
speech(speech),
switch_on(false) {}
void AppMotion::update()
{
if (this->key->pressed > _IDLE)
{
if (this->key->pressed == _MENU)
{
this->switch_on = (this->key->menu == MENU_MOTION_DETECTION) ? true : false;
ESP_LOGD(TAG, "%s", this->switch_on ? "ON" : "OFF");
}
}
if (this->speech->command > COMMAND_NOT_DETECTED)
{
if (this->speech->command >= MENU_STOP_WORKING && this->speech->command <= MENU_MOTION_DETECTION)
{
this->switch_on = (this->speech->command == MENU_MOTION_DETECTION) ? true : false;
ESP_LOGD(TAG, "%s", this->switch_on ? "ON" : "OFF");
}
}
}
static void task(AppMotion *self)
{
ESP_LOGD(TAG, "Start");
while (true)
{
if (self->queue_i == nullptr)
break;
camera_fb_t *frame1 = NULL;
camera_fb_t *frame2 = NULL;
if (xQueueReceive(self->queue_i, &frame1, portMAX_DELAY))
{
if (self->switch_on)
{
if (xQueueReceive(self->queue_i, &frame2, portMAX_DELAY))
{
uint32_t moving_point_number = dl::image::get_moving_point_number((uint16_t *)frame1->buf, (uint16_t *)frame2->buf, frame1->height, frame1->width, 8, 15);
if (moving_point_number > 50)
{
ESP_LOGI(TAG, "Something moved!");
dl::image::draw_filled_rectangle((uint16_t *)frame1->buf, frame1->height, frame1->width, 0, 0, 20, 20);
}
self->callback(frame2);
}
}
if (self->queue_o)
xQueueSend(self->queue_o, &frame1, portMAX_DELAY);
else
self->callback(frame1);
}
}
ESP_LOGD(TAG, "Stop");
vTaskDelete(NULL);
}
void AppMotion::run()
{
xTaskCreatePinnedToCore((TaskFunction_t)task, TAG, 3 * 1024, this, 6, NULL, 0);
}

View File

@ -0,0 +1,214 @@
#include "app_speech.hpp"
#include "driver/i2s.h"
#include "esp_log.h"
#include "dl_lib_coefgetter_if.h"
#include "esp_wn_iface.h"
#include "esp_wn_models.h"
#include "esp_afe_sr_models.h"
#include "esp_mn_iface.h"
#include "esp_mn_models.h"
#include "esp_spiffs.h"
#define I2S_CHANNEL_NUM 1
#define I2S_CH ((i2s_port_t)1)
static const char *TAG = "App/Speech";
static void spiffs_init(void)
{
ESP_LOGI(TAG, "Initializing SPIFFS");
esp_vfs_spiffs_conf_t conf = {
.base_path = "/srmodel",
.partition_label = "model",
.max_files = 5,
.format_if_mount_failed = true};
// Use settings defined above to initialize and mount SPIFFS filesystem.
// Note: esp_vfs_spiffs_register is an all-in-one convenience function.
esp_err_t ret = esp_vfs_spiffs_register(&conf);
if (ret != ESP_OK)
{
if (ret == ESP_FAIL)
{
ESP_LOGE(TAG, "Failed to mount or format filesystem");
}
else if (ret == ESP_ERR_NOT_FOUND)
{
ESP_LOGE(TAG, "Failed to find SPIFFS partition");
}
else
{
ESP_LOGE(TAG, "Failed to initialize SPIFFS (%s)", esp_err_to_name(ret));
}
return;
}
size_t total = 0, used = 0;
ret = esp_spiffs_info("model", &total, &used);
if (ret != ESP_OK)
{
ESP_LOGE(TAG, "Failed to get SPIFFS partition information (%s)", esp_err_to_name(ret));
}
else
{
ESP_LOGI(TAG, "Partition size: total: %d, used: %d", total, used);
}
}
static void i2s_init(void)
{
i2s_config_t i2s_config = {
.mode = (i2s_mode_t)(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
.bits_per_sample = (i2s_bits_per_sample_t)32, // must be the same as DSP configuration
.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT, // must be the same as DSP configuration
.communication_format = I2S_COMM_FORMAT_STAND_I2S,
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL2,
.dma_buf_count = 3,
.dma_buf_len = 300,
};
i2s_pin_config_t pin_config = {
.mck_io_num = I2S_PIN_NO_CHANGE,
.bck_io_num = 41, // IIS_SCLK
.ws_io_num = 42, // IIS_LCLK
.data_out_num = I2S_PIN_NO_CHANGE, // IIS_DSIN
.data_in_num = 2 // IIS_DOUT
};
i2s_driver_install(I2S_CH, &i2s_config, 0, NULL);
i2s_set_pin(I2S_CH, &pin_config);
i2s_zero_dma_buffer(I2S_CH);
}
static void feed_handler(AppSpeech *self)
{
esp_afe_sr_data_t *afe_data = self->afe_data;
int audio_chunksize = self->afe_handle->get_feed_chunksize(afe_data);
int nch = self->afe_handle->get_channel_num(afe_data);
size_t samp_len = audio_chunksize * I2S_CHANNEL_NUM;
size_t samp_len_bytes = samp_len * sizeof(int32_t);
int32_t *i2s_buff = (int32_t *)malloc(samp_len_bytes);
assert(i2s_buff);
size_t bytes_read;
// FILE *fp = fopen("/sdcard/out", "a+");
// if (fp == NULL) ESP_LOGE(TAG,"can not open file\n");
while (true)
{
i2s_read(I2S_CH, i2s_buff, samp_len_bytes, &bytes_read, portMAX_DELAY);
for (int i = 0; i < samp_len; ++i)
{
i2s_buff[i] = i2s_buff[i] >> 14; // 32:8为有效位 8:0为低8位 全为0 AFE的输入为16位语音数据拿2913位是为了对语音信号放大。
}
// FatfsComboWrite(i2s_buff, audio_chunksize * I2S_CHANNEL_NUM * sizeof(int16_t), 1, fp);
self->afe_handle->feed(afe_data, (int16_t *)i2s_buff);
}
self->afe_handle->destroy(afe_data);
vTaskDelete(NULL);
}
static void detect_hander(AppSpeech *self)
{
esp_afe_sr_data_t *afe_data = self->afe_data;
int afe_chunksize = self->afe_handle->get_fetch_chunksize(afe_data);
int nch = self->afe_handle->get_channel_num(afe_data);
int16_t *buff = (int16_t *)malloc(afe_chunksize * sizeof(int16_t));
assert(buff);
static const esp_mn_iface_t *multinet = &MULTINET_MODEL;
model_iface_data_t *model_data = multinet->create((const model_coeff_getter_t *)&MULTINET_COEFF, 5760);
int mu_chunksize = multinet->get_samp_chunksize(model_data);
int chunk_num = multinet->get_samp_chunknum(model_data);
assert(mu_chunksize == afe_chunksize);
// FILE *fp = fopen("/sdcard/out", "w");
// if (fp == NULL) ESP_LOGE(TAG,"can not open file\n");
ESP_LOGI(TAG, "Ready");
self->detected = false;
while (true)
{
int res = self->afe_handle->fetch(afe_data, buff);
if (res == AFE_FETCH_WWE_DETECTED)
{
ESP_LOGI(TAG, ">>> Say your command <<<");
self->detected = true;
self->afe_handle->disable_wakenet(afe_data);
self->notify();
}
if (self->detected)
{
// Detect command
self->command = (command_word_t)multinet->detect(model_data, buff);
// FatfsComboWrite(buff, afe_chunksize * sizeof(int16_t), 1, fp);
if (self->command == COMMAND_NOT_DETECTED)
continue;
else if (self->command == COMMAND_TIMEOUT)
{
self->afe_handle->enable_wakenet(afe_data);
// self->afe_handle->enable_aec(afe_data);
self->detected = false;
ESP_LOGI(TAG, ">>> Waiting to be waken up <<<");
self->notify();
}
else
{
self->notify();
ESP_LOGD(TAG, "Command: %d", self->command);
#ifndef CONFIG_SR_MN_CN_MULTINET3_CONTINUOUS_RECOGNITION
self->afe_handle->enable_wakenet(afe_data);
// self->afe_handle->enable_aec(afe_data);
self->detected = false;
ESP_LOGI(TAG, ">>> Waiting to be waken up <<<");
#endif
self->command = COMMAND_TIMEOUT;
self->notify();
}
}
}
self->afe_handle->destroy(afe_data);
vTaskDelete(NULL);
}
AppSpeech::AppSpeech() : afe_handle(&esp_afe_sr_1mic), detected(false), command(COMMAND_TIMEOUT)
{
spiffs_init();
i2s_init();
// sd_card_mount("/sdcard");
afe_config_t afe_config = {
.aec_init = true,
.se_init = true,
.vad_init = true,
.wakenet_init = true,
.vad_mode = 3,
.wakenet_model = &WAKENET_MODEL,
.wakenet_coeff = (const model_coeff_getter_t *)&WAKENET_COEFF,
.wakenet_mode = DET_MODE_2CH_90,
.afe_mode = SR_MODE_LOW_COST,
.afe_perferred_core = 0,
.afe_perferred_priority = 5,
.afe_ringbuf_size = 50,
.alloc_from_psram = AFE_PSRAM_MEDIA_COST,
.agc_mode = 2,
};
afe_config.aec_init = false;
afe_config.se_init = false;
afe_config.vad_init = false;
afe_config.afe_ringbuf_size = 10;
this->afe_data = this->afe_handle->create_from_config(&afe_config);
}
void AppSpeech::run()
{
xTaskCreatePinnedToCore((TaskFunction_t)feed_handler, "SR_feed", 4 * 1024, this, 5, NULL, 0);
xTaskCreatePinnedToCore((TaskFunction_t)detect_hander, "SR_detect", 5 * 1024, this, 5, NULL, 0);
}

View File

@ -0,0 +1,7 @@
# Name, Type, SubType, Offset, Size, Flags
# Note: if you change the phy_init or app partition offset, make sure to change the offset in Kconfig.projbuild
factory, app, factory, 0x010000, 4000K,
model, data, spiffs, , 3900K,
nvs, data, nvs, , 16K,
fr, data, , , 128K,
1 # Name, Type, SubType, Offset, Size, Flags
2 # Note: if you change the phy_init or app partition offset, make sure to change the offset in Kconfig.projbuild
3 factory, app, factory, 0x010000, 4000K,
4 model, data, spiffs, , 3900K,
5 nvs, data, nvs, , 16K,
6 fr, data, , , 128K,

View File

@ -0,0 +1,59 @@
# General Configuration
CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y
CONFIG_ESPTOOLPY_FLASHFREQ_80M=y
CONFIG_ESPTOOLPY_FLASHMODE_QIO=y
CONFIG_SPIRAM_SPEED_80M=y
CONFIG_SPIRAM_USE_CAPS_ALLOC=y
CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y
CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
CONFIG_ESPTOOLPY_NO_STUB=y
CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG=y
CONFIG_SPIRAM_MODE_OCT=y
# ESP32-S3 Configuration
CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240=y
CONFIG_ESP32S3_SPIRAM_SUPPORT=y
CONFIG_ESP32S3_DATA_CACHE_64KB=y
CONFIG_ESP32S3_DATA_CACHE_8WAYS=y
CONFIG_ESP32S3_DATA_CACHE_LINE_64B=y
# Image Relation
CONFIG_CAMERA_MODULE_ESP_S3_EYE=y
CONFIG_LCD_DRIVER_SCREEN_CONTROLLER_ST7789=y
CONFIG_MFN_V1_Q8=y
# Speech Relation
# Chinese
CONFIG_SR_WN_MODEL_WN7_QUANT8=y
CONFIG_SR_WN_WN7_HILEXIN=y
CONFIG_SR_MN_CHINESE=y
CONFIG_SR_MN_CN_MULTINET4_5_SINGLE_RECOGNITION=y
CONFIG_CN_SPEECH_COMMAND_ID0="ting zhi gong zuo"
CONFIG_CN_SPEECH_COMMAND_ID1="jin xian shi"
CONFIG_CN_SPEECH_COMMAND_ID2="ren lian shi bie"
CONFIG_CN_SPEECH_COMMAND_ID3="yi dong zhen ce"
CONFIG_CN_SPEECH_COMMAND_ID4="tian jia ren lian"
CONFIG_CN_SPEECH_COMMAND_ID5="shan chu ren lian"
CONFIG_CN_SPEECH_COMMAND_ID6="shi bie yi xia"
# English
# CONFIG_SR_WN_MODEL_WN8_QUANT8=y
# CONFIG_SR_WN_WN8_HIESP=y
#
# CONFIG_SR_MN_ENGLISH=y
# CONFIG_SR_MN_EN_MULTINET5_SINGLE_RECOGNITION_QUANT8=y
# CONFIG_EN_SPEECH_COMMAND_ID0="STnP WkKgl"
# CONFIG_EN_SPEECH_COMMAND_ID1="DgSPLd bNLm"
# CONFIG_EN_SPEECH_COMMAND_ID2="FdS RfKcGNgscN"
# CONFIG_EN_SPEECH_COMMAND_ID3="MbscN DgTfKscN"
# CONFIG_EN_SPEECH_COMMAND_ID4="fNTk FdS"
# CONFIG_EN_SPEECH_COMMAND_ID5="DgLmT FdS"
# CONFIG_EN_SPEECH_COMMAND_ID6="RfKcGNiZ FdS"