边缘 AI 方案介绍 - - — ESP-Techpedia latest 文档
ESP-IoT-Solution 编程指南 - - — ESP-IoT-Solution latest 文档
ESP-IoT-Solution 编程指南 - - — ESP-IoT-Solution latest 文档
ESP-DL(DEEP LEARINIG)
入门指南 - - — ESP-DL 用户指南 latest 文档
git clone https://gitee.com/esp-components/esp-dl
//
一键安装依赖库 pip install -r requirests.txt
// 量化工具 ppq
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu
pip install esp-ppq
pip install Numba
pip install ONNX
pip install ONNX Runtime
pip install ONNX Optimizer
一锓转模型
//
一键加载
//
安装 使用
https://blog.csdn.net/espressif/article/details/128248431
人脸识别
https://gitee.com/EspressifSystems/esp-who
//
语音识别(asr -tts )
sr-skaint (示例 examples components ,include test MULTINET_module ,documents
https://gitee.com/xv-shuai/esp-skainet
https://gitee.com/xv-shuai/esp-skainet
入门指南 - ESP32-S3 - — ESP-SR latest 文档
安可信
A1S
JSON
json(直接搜 idf cjson) components 目录下
事件循环库
事件循环库 - ESP32 - — ESP-IDF 编程指南 v5.5 文档(什么时候用,什么时候不用,效率,快速,多任务)
//
// 1. 定义事件处理程序
void run_on_event(void* handler_arg, esp_event_base_t base, int32_t id, void* event_data)
{
// 事件处理程序逻辑
}
void app_main()
{
// 2. 用一个类型为 esp_event_loop_args_t 的配置结构体,指定所创建循环的属性。获取一个类型为 esp_event_loop_handle_t 的句柄,用于其他 API 引用循环、执行操作。
esp_event_loop_args_t loop_args = {
.queue_size = ...,
.task_name = ...
.task_priority = ...,
.task_stack_size = ...,
.task_core_id = ...
};
esp_event_loop_handle_t loop_handle;
esp_event_loop_create(&loop_args, &loop_handle);
// 3. 注册在 (1) 中定义的事件处理程序。MY_EVENT_BASE 和 MY_EVENT_ID 指定了一个假设事件:将处理程序 run_on_event 发布到循环中时,执行该处理程序。
esp_event_handler_register_with(loop_handle, MY_EVENT_BASE, MY_EVENT_ID, run_on_event, ...);
...
// 4. 将事件发布到循环中。此时,事件排入事件循环队列,在某个时刻,事件循环会执行已注册到发布事件的事件处理程序,例如此处的 run_on_event。为简化过程,此示例从 app_main 调用 esp_event_post_to,实际应用中可从任何其他任务中发布事件。
esp_event_post_to(loop_handle, MY_EVENT_BASE, MY_EVENT_ID, ...);
...
// 5. 注销无用的处理程序。
esp_event_handler_unregister_with(loop_handle, MY_EVENT_BASE, MY_EVENT_ID, run_on_event);
...
// 6. 删除无用的事件循环。
esp_event_loop_delete(loop_handle);
}
//esp-adf\examples\ai_agent\volc_rtc\main\coze_http_request.c
coze_http_req_result_t *result = (coze_http_req_result_t *)impl_malloc_fn(sizeof(coze_http_req_result_t));
cJSON *root = cJSON_Parse(rsp_string);
if (root == NULL) {
ESP_LOGW(TAG, "Error parsing JSON\n");
return NULL;
}
cJSON *data = cJSON_GetObjectItem(root, "data");
if (data != NULL) {
cJSON *token = cJSON_GetObjectItem(data, "token");
if (token != NULL && cJSON_IsString(token)) {
ESP_LOGD(TAG, "Token: %s\n", token->valuestring);
result->token = impl_strdup_fn(token->valuestring);
HTTP_REQ_MEM_CHECK( result->token, goto _exit);
}
cJSON *uid = cJSON_GetObjectItem(data, "uid");
if (uid != NULL && cJSON_IsString(uid)) {
ESP_LOGD(TAG, "UID: %s\n", uid->valuestring);
result->uid = impl_strdup_fn(uid->valuestring);
HTTP_REQ_MEM_CHECK( result->uid, goto _exit);
}
cJSON *room_id = cJSON_GetObjectItem(data, "room_id");
if (room_id != NULL && cJSON_IsString(room_id)) {
ESP_LOGD(TAG, "Room ID: %s\n", room_id->valuestring);
result->room_id = impl_strdup_fn(room_id->valuestring);
HTTP_REQ_MEM_CHECK( result->uid, goto _exit);
}
cJSON *app_id = cJSON_GetObjectItem(data, "app_id");
if (app_id != NULL && cJSON_IsString(app_id)) {
ESP_LOGD(TAG, "App ID: %s\n", app_id->valuestring);
result->app_id = impl_strdup_fn(app_id->valuestring);
HTTP_REQ_MEM_CHECK(result->app_id, goto _exit);
}
}
cJSON *code = cJSON_GetObjectItem(root, "code");
if (code != NULL && cJSON_IsNumber(code)) {
ESP_LOGD(TAG, "Code: %d\n", code->valueint);
} else {
ESP_LOGE(TAG, "Code not found in response");
goto _exit;
}
cJSON_Delete(root);
return result;
_exit:
coze_http_request_free(result);
cJSON_Delete(root);
return NULL;
First up, how do I build?
Add cJSON.c to your project, and put cJSON.h somewhere in the header search path.
For example, to build the test app:
gcc cJSON.c test.c -o test -lm
./test
As a library, cJSON exists to take away as much legwork as it can, but not get in your way.
As a point of pragmatism (i.e. ignoring the truth), I'm going to say that you can use it
in one of two modes: Auto and Manual. Let's have a quick run-through.
I lifted some JSON from this page: http://www.json.org/fatfree.html
That page inspired me to write cJSON, which is a parser that tries to share the same
philosophy as JSON itself. Simple, dumb, out of the way.
Some JSON:
{
"name": "Jack (\"Bee\") Nimble",
"format": {
"type": "rect",
"width": 1920,
"height": 1080,
"interlace": false,
"frame rate": 24
}
}
Assume that you got this from a file, a webserver, or magic JSON elves, whatever,
you have a char * to it. Everything is a cJSON struct.
Get it parsed:
cJSON *root = cJSON_Parse(my_json_string);
This is an object. We're in C. We don't have objects. But we do have structs.
What's the framerate?
cJSON *format = cJSON_GetObjectItem(root,"format");
int framerate = cJSON_GetObjectItem(format,"frame rate")->valueint;
Want to change the framerate?
cJSON_GetObjectItem(format,"frame rate")->valueint=25;
Back to disk?
char *rendered=cJSON_Print(root);
Finished? Delete the root (this takes care of everything else).
cJSON_Delete(root);
That's AUTO mode. If you're going to use Auto mode, you really ought to check pointers
before you dereference them. If you want to see how you'd build this struct in code?
cJSON *root,*fmt;
root=cJSON_CreateObject();
cJSON_AddItemToObject(root, "name", cJSON_CreateString("Jack (\"Bee\") Nimble"));
cJSON_AddItemToObject(root, "format", fmt=cJSON_CreateObject());
cJSON_AddStringToObject(fmt,"type", "rect");
cJSON_AddNumberToObject(fmt,"width", 1920);
cJSON_AddNumberToObject(fmt,"height", 1080);
cJSON_AddFalseToObject (fmt,"interlace");
cJSON_AddNumberToObject(fmt,"frame rate", 24);
Hopefully we can agree that's not a lot of code? There's no overhead, no unnecessary setup.
Look at test.c for a bunch of nice examples, mostly all ripped off the json.org site, and
a few from elsewhere.
What about manual mode? First up you need some detail.
Let's cover how the cJSON objects represent the JSON data.
cJSON doesn't distinguish arrays from objects in handling; just type.
Each cJSON has, potentially, a child, siblings, value, a name.
The root object has: Object Type and a Child
The Child has name "name", with value "Jack ("Bee") Nimble", and a sibling:
Sibling has type Object, name "format", and a child.
That child has type String, name "type", value "rect", and a sibling:
Sibling has type Number, name "width", value 1920, and a sibling:
Sibling has type Number, name "height", value 1080, and a sibling:
Sibling has type False, name "interlace", and a sibling:
Sibling has type Number, name "frame rate", value 24
Here's the structure:
typedef struct cJSON {
struct cJSON *next,*prev;
struct cJSON *child;
int type;
char *valuestring;
int valueint;
double valuedouble;
char *string;
} cJSON;
By default all values are 0 unless set by virtue of being meaningful.
next/prev is a doubly linked list of siblings. next takes you to your sibling,
prev takes you back from your sibling to you.
Only objects and arrays have a "child", and it's the head of the doubly linked list.
A "child" entry will have prev==0, but next potentially points on. The last sibling has next=0.
The type expresses Null/True/False/Number/String/Array/Object, all of which are #defined in
cJSON.h
A Number has valueint and valuedouble. If you're expecting an int, read valueint, if not read
valuedouble.
Any entry which is in the linked list which is the child of an object will have a "string"
which is the "name" of the entry. When I said "name" in the above example, that's "string".
"string" is the JSON name for the 'variable name' if you will.
Now you can trivially walk the lists, recursively, and parse as you please.
You can invoke cJSON_Parse to get cJSON to parse for you, and then you can take
the root object, and traverse the structure (which is, formally, an N-tree),
and tokenise as you please. If you wanted to build a callback style parser, this is how
you'd do it (just an example, since these things are very specific):
void parse_and_callback(cJSON *item,const char *prefix)
{
while (item)
{
char *newprefix=malloc(strlen(prefix)+strlen(item->name)+2);
sprintf(newprefix,"%s/%s",prefix,item->name);
int dorecurse=callback(newprefix, item->type, item);
if (item->child && dorecurse) parse_and_callback(item->child,newprefix);
item=item->next;
free(newprefix);
}
}
The prefix process will build you a separated list, to simplify your callback handling.
The 'dorecurse' flag would let the callback decide to handle sub-arrays on it's own, or
let you invoke it per-item. For the item above, your callback might look like this:
int callback(const char *name,int type,cJSON *item)
{
if (!strcmp(name,"name")) { /* populate name */ }
else if (!strcmp(name,"format/type") { /* handle "rect" */ }
else if (!strcmp(name,"format/width") { /* 800 */ }
else if (!strcmp(name,"format/height") { /* 600 */ }
else if (!strcmp(name,"format/interlace") { /* false */ }
else if (!strcmp(name,"format/frame rate") { /* 24 */ }
return 1;
}
Alternatively, you might like to parse iteratively.
You'd use:
void parse_object(cJSON *item)
{
int i; for (i=0;i<cJSON_GetArraySize(item);i++)
{
cJSON *subitem=cJSON_GetArrayItem(item,i);
// handle subitem.
}
}
Or, for PROPER manual mode:
void parse_object(cJSON *item)
{
cJSON *subitem=item->child;
while (subitem)
{
// handle subitem
if (subitem->child) parse_object(subitem->child);
subitem=subitem->next;
}
}
Of course, this should look familiar, since this is just a stripped-down version
of the callback-parser.
freertos
FreeRTOS 常用 API - - — ESP-Techpedia latest 文档
//
int i = 0;
static void task(void *arg)
{
while(1){
printf("%d",i);
i++;
}
}
void app_main(void)
{
xTaskCreate(task,"task",2048,NULL,5,NULL); //fun,name,stack,arg,prio,handle 函数,名,堆大小,参数,级别,句柄
}
xtaskcreate(fun,"name",2048,arg,5,handle)
消息队列
消息队列
QueueHandle_t gpio_queue = NULL;
gpio_queue = xQueueCreate(10,sizeof(uint32_t));
isr:
xQueueSendFromISR(gpio_queue,&gpio_num,NULL);
xQueueReceive(gpio_queue,&io_num,1000);
WIFI
socket
wifi example
#include <stdint.h>
#include "esp_log.h"
#include "esp_event.h"
#include "esp_netif.h"
#include "protocol_examples_common.h"
#include "esp_wifi.h"
#include "nvs_flash.h"
void app_main(){
nvs_flash_init(); //存储断网重连数据
esp_netif_init();
esp_event_loop_create_default();
example_connect();
wifi_ap_record_t ap_info;
esp_wifi_sta_get_ap_info(&ap_info);
//print information
ESP_LOG_BUFFER_HEX("MAC Address",ap_info.bssid,sizeof(ap_info.bssid));
ESP_LOG_BUFFER_CHAR("SSID",ap_info.ssid,sizeof(ap_info.ssid));
ESP_LOGI("WIFI","Primary Channel:%d",ap_info.primary);
ESP_LOGI("WIFI","RSSI:%d",ap_info.rssi);
ESP_ERROR_CHECK(example_disconnect());
}
//idf.py create-manifest
//dependencies:
// protocol_examples_common:
// path: ${IDF_PATH}/examples/common_components/protocol_examples_common
wifi http
HFP事件
GAP 回调事件
enumerator ESP_BT_GAP_DISC_RES_EVT
Device discovery result event 设备发现结果事件
enumerator ESP_BT_GAP_DISC_STATE_CHANGED_EVT
Discovery state changed event 发现状态更改事件
enumerator ESP_BT_GAP_RMT_SRVCS_EVT
Get remote services event 获取远程服务事件
enumerator ESP_BT_GAP_RMT_SRVC_REC_EVT
Get remote service record event 获取远程服务记录
enumerator ESP_BT_GAP_AUTH_CMPL_EVT
Authentication complete event 认证完成
enumerator ESP_BT_GAP_PIN_REQ_EVT
Legacy Pairing Pin code request 传统配对密码请示
enumerator ESP_BT_GAP_CFM_REQ_EVT
Security Simple Pairing User Confirmation request. 安全简单配对用户确认
enumerator ESP_BT_GAP_KEY_NOTIF_EVT
Security Simple Pairing Passkey Notification 安全简单配对密码通知
enumerator ESP_BT_GAP_KEY_REQ_EVT
Security Simple Pairing Passkey request 安全简单配对密码请求
enumerator ESP_BT_GAP_READ_RSSI_DELTA_EVT
Read rssi event 阅读rssi事件
enumerator ESP_BT_GAP_CONFIG_EIR_DATA_EVT
Config EIR data event 配置eir数据事件
enumerator ESP_BT_GAP_SET_AFH_CHANNELS_EVT
Set AFH channels event 设置AFH频道事件
enumerator ESP_BT_GAP_READ_REMOTE_NAME_EVT
Read Remote Name event 读取过程名称事件
enumerator ESP_BT_GAP_MODE_CHG_EVT
enumerator ESP_BT_GAP_REMOVE_BOND_DEV_COMPLETE_EVT
remove bond device complete event 移除设备完成
enumerator ESP_BT_GAP_QOS_CMPL_EVT
QOS complete event QOS完成事件
enumerator ESP_BT_GAP_ACL_CONN_CMPL_STAT_EVT
ACL connection complete status event ACL连接完成状态事件
enumerator ESP_BT_GAP_ACL_DISCONN_CMPL_STAT_EVTACL断开连接完成事件
ACL disconnection complete status event
enumerator ESP_BT_GAP_SET_PAGE_TO_EVT设置页面超时事件
Set page timeout event
enumerator ESP_BT_GAP_GET_PAGE_TO_EVT获取页面超时事件
Get page timeout event
enumerator ESP_BT_GAP_ACL_PKT_TYPE_CHANGED_EVT 设置ACL数据包类型事件
Set ACL packet types event
enumerator ESP_BT_GAP_ENC_CHG_EVT加密更改事件
Encryption change event
enumerator ESP_BT_GAP_SET_MIN_ENC_KEY_SIZE_EVT 设置最低加密密钥
Set minimum encryption key size
enumerator ESP_BT_GAP_GET_DEV_NAME_CMPL_EVT获取设备完整名称事件
Get device name complete event
enumerator ESP_BT_GAP_EVT_MAX 查询模式 一般查询模式 有限查询模式
//-------------------------------------------------------------------
HFP 回调事件
enumerator ESP_HF_CLIENT_CONNECTION_STATE_EVT
连接状态改变事件
enumerator ESP_HF_CLIENT_AUDIO_STATE_EVT
音频连接状态变化事件
enumerator ESP_HF_CLIENT_BVRA_EVT
语音识别状态变更事件
enumerator ESP_HF_CLIENT_CIND_CALL_EVT
呼叫指示
enumerator ESP_HF_CLIENT_CIND_CALL_SETUP_EVT
呼叫建立指示
enumerator ESP_HF_CLIENT_CIND_CALL_HELD_EVT
呼叫被占指示
enumerator ESP_HF_CLIENT_CIND_SERVICE_AVAILABILITY_EVT
网络服务可用性指示
enumerator ESP_HF_CLIENT_CIND_SIGNAL_STRENGTH_EVT
信号强度指示
enumerator ESP_HF_CLIENT_CIND_CALL_SETUP_EVT
呼叫建立指示
enumerator ESP_HF_CLIENT_CIND_CALL_HELD_EVT
呼叫被占指示
enumerator ESP_HF_CLIENT_CIND_SERVICE_AVAILABILITY_EVT
网络服务可用性指示
enumerator ESP_HF_CLIENT_CIND_SIGNAL_STRENGTH_EVT
信号强度指示
enumerator ESP_HF_CLIENT_CIND_ROAMING_STATUS_EVT
漫游状态指示
enumerator ESP_HF_CLIENT_CIND_BATTERY_LEVEL_EVT
电量指示
enumerator ESP_HF_CLIENT_COPS_CURRENT_OPERATOR_EVT
当前运营商信息
enumerator ESP_HF_CLIENT_BTRH_EVT
呼叫响应与保留事件
enumerator ESP_HF_CLIENT_CLIP_EVT
呼叫线路识别通知
enumerator ESP_HF_CLIENT_CCWA_EVT
呼叫等待通知
enumerator ESP_HF_CLIENT_CLCC_EVT
当前呼叫通知列表
enumerator ESP_HF_CLIENT_VOLUME_CONTROL_EVT
来自AG的音频音量控制命令, provided by +VGM or +VGS message
enumerator ESP_HF_CLIENT_AT_RESPONSE_EVT
AT命令响应事件
enumerator ESP_HF_CLIENT_CNUM_EVT
来自AG的用户信息回复
enumerator ESP_HF_CLIENT_BSIR_EVT
带内铃声的设置
enumerator ESP_HF_CLIENT_BINP_EVT
AG要求的最后一个语音标签量
requested number of last voice tag from AG
enumerator ESP_HF_CLIENT_RING_IND_EVT
ring indication event
enumerator ESP_HF_CLIENT_PKT_STAT_NUMS_GET_EVT请求数据包数量差异
requested number of packet different status
enumerator ESP_HF_CLIENT_PROF_STATE_EVT指示HF CLIENT 初始化或结束完成
Indicate HF CLIENT init or deinit complete
bluedroid
esp_bluedroid_status_t esp_bluedroid_get_status(void) 获取蓝牙堆栈状态。
esp_err_t esp_bluedroid_enable(void) 启用蓝牙,必须在esp_bluedroid_init()/esp_bluedroid_init_with_cfg()之后
esp_err_t esp_bluedroid_disable(void) 禁用蓝牙,必须在esp_bluedroid_deinit()之前调用
esp_err_t esp_bluedroid_init(void) 初始化并分配蓝牙资源,必须在任何蓝牙操作之前。
esp_err_t esp_bluedroid_init_with_cfg(esp_bluedroid_config_t *cfg) 初始化并分配蓝牙资源,必须在任何蓝牙操作之前。
esp_err_t esp_bluedroid_deinit(void) 解除蓝牙资源的初始化并释放资源,必须在每次使用蓝牙之后进行
device
esp_err_t esp_bt_config_file_path_update 此函数用于更新保存在NVS模块中的蓝牙绑定键的路径名,需要在esp_bluedroid_init()之前调用。
esp_err_t esp_bt_config_file_path_get 该函数用于获取保存在NVS模块中的蓝牙绑定密钥的路径名。
esp_err_t esp_bt_dev_coex_status_config 配置蓝牙设备共存状态。此函数应在esp_bluedroid_enable()成功完成后调用。
esp_err_t esp_bt_dev_get_device_nam 获取蓝牙设备名称。此函数应在esp_bluedroid_enable()成功完成后调用。
esp_err_t esp_bt_dev_set_device_name 设置蓝牙设备名称。此函数应在esp_bluedroid_enable()成功完成后调用。
const uint8_t *esp_bt_dev_get_address 获取蓝牙设备地址。必须在“esp_bluedroid_enable”之后使用。
esp_err_t esp_bt_dev_register_callback 注册回调函数。此函数应在esp_bluedroid_enable()成功完成后调用
contrl &HCI
esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) //初始化蓝牙控制器以分配任务和其他资源。
esp_err_t esp_bt_controller_deinit(void) //解除蓝牙控制器的初始化,以释放资源并删除任务。
esp_err_t esp_bt_controller_enable(esp_bt_mode_t mode) //启用蓝牙控制器
esp_err_t esp_bt_controller_disable(void) //禁用蓝牙控制器
esp_bt_controller_status_t esp_bt_controller_get_status(void) //获取状态
esp_err_t esp_bt_controller_mem_release(esp_bt_mode_t mode) //释放空间用于BT或BLE (内存不足时)
esp_err_t esp_bt_mem_release(esp_bt_mode_t mode) //根据模式释放控制器内存、BSS和经典蓝牙/BLE主机堆栈的数据部分。
esp_err_t esp_bt_sleep_enable(void) //睡眠功能
esp_err_t esp_bt_sleep_disable(void) //关闭睡眠
esp_err_t esp_ble_tx_power_set(esp_ble_power_type_t power_type, esp_power_level_t power_level) 设置BLE传输功率。
esp_power_level_t esp_ble_tx_power_get(esp_ble_power_type_t power_type) 获取蓝牙传输功率。
esp_err_t esp_ble_scan_duplicate_list_flush(void) 手动清除蓝牙扫描重复列表。
esp_err_t esp_ble_scan_dupilcate_list_flush(void)
esp_err_t esp_bredr_tx_power_set(esp_power_level_t min_power_level, esp_power_level_t max_power_level) 设置BR/EDR传输功率。
esp_err_t esp_bredr_tx_power_get(esp_power_level_t *min_power_level, esp_power_level_t *max_power_level)
esp_err_t esp_bredr_sco_datapath_set(esp_sco_data_path_t data_path)
bool esp_vhci_host_check_send_available(void)
void esp_vhci_host_send_packet(uint8_t *data, uint16_t len)
esp_err_t esp_vhci_host_register_callback(const esp_vhci_host_callback_t *callback)
esp_bt_sleep_clock_t esp_bt_get_lpclk_src(void)
esp_err_t esp_bt_set_lpclk_src(esp_bt_sleep_clock_t lpclk)
高级功能:
蓝牙
bta btc bdm(device manage)
ESP Friends - - — ESP-Techpedia latest 文档
mesh zigbee now 区别
不同 Mesh 方案的对比 - - — ESP-Techpedia latest 文档
Feature | ESP BLE Mesh | ESP Thread Mesh | ESP-Mesh-Lite | ZigBee Mesh | ESP-Now |
---|---|---|---|---|---|
节点数量 | 理论不大于 32767 个,内部测试可达 100 个节点 | 内部测试可达 300 个节点 | 内部测试可达 100 个节点 | 理论上限 65000 个,内部测试可达 300 个节点 | 小于 100 个节点 |
节点间通信距离 | 视发包功率而定,推荐相邻节点距离不大于 50 m | 维持连接的距离可达 200 m | 小于 100 m,经测试可达 170 m | 维持连接的距离可达 300 m | 推荐不大于 150 m |
吞吐量 | 低,小于 1 Kbps | 低,实际测试约为 4 - 5 KB/s | 高,实际测试最高为 20 Mbps,层级越深吞吐越低 | 低,实际测试约为 16.9 Kbps | 低,小于 0.5 Mbps |
单跳延时 | 50 m 极限距离时为 100 ms 以内,正常距离(低于 50 m 时)为 50 ms 以内 | 平均 10 ms | 100 ms 以内 | 平均 16 ms | 10 ms 以内 |
乐鑫各类 Mesh 方案核心参数说明如下。
组网:
now
airkiss
mesh
蓝牙
ad2p
//
hfp
//
摄像头(官网源码)
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sdkconfig.h"
#include "esp_attr.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "esp_lcd_mipi_dsi.h"
#include "esp_lcd_panel_ops.h"
#include "esp_ldo_regulator.h"
#include "esp_cache.h"
#include "driver/i2c_master.h"
#include "driver/isp.h"
#include "esp_cam_ctlr_isp_dvp.h"
#include "esp_cam_ctlr.h"
#include "example_dsi_init.h"
#include "example_dsi_init_config.h"
#include "example_sensor_init.h"
#include "example_config.h"
#include "driver/ledc.h"
static const char *TAG = "dvp_isp_dsi";
static bool s_camera_get_new_vb(esp_cam_ctlr_handle_t handle, esp_cam_ctlr_trans_t *trans, void *user_data);
static bool s_camera_get_finished_trans(esp_cam_ctlr_handle_t handle, esp_cam_ctlr_trans_t *trans, void *user_data);
// Generate a 20MHz clock for DVP XCLK
static void s_ledc_generate_dvp_xclk(void)
{
ledc_timer_config_t ledc_timer = {
.speed_mode = LEDC_LOW_SPEED_MODE,
.duty_resolution = LEDC_TIMER_1_BIT,
.timer_num = LEDC_TIMER_0,
.freq_hz = EXAMPLE_ISP_DVP_CAM_XCLK_FREQ_HZ, // Set output frequency at 20 MHz
.clk_cfg = LEDC_AUTO_CLK
};
ESP_ERROR_CHECK(ledc_timer_config(&ledc_timer));
// Prepare and then apply the LEDC PWM channel configuration
ledc_channel_config_t ledc_channel = {
.speed_mode = LEDC_LOW_SPEED_MODE,
.channel = LEDC_CHANNEL_0,
.timer_sel = LEDC_TIMER_0,
.intr_type = LEDC_INTR_DISABLE,
.gpio_num = EXAMPLE_ISP_DVP_CAM_XCLK_IO,
.duty = 1, // Set duty to 50%
.hpoint = 0
};
ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel));
}
void app_main(void)
{
esp_err_t ret = ESP_FAIL;
esp_lcd_dsi_bus_handle_t mipi_dsi_bus = NULL;
esp_lcd_panel_io_handle_t mipi_dbi_io = NULL;
esp_lcd_panel_handle_t mipi_dpi_panel = NULL;
void *frame_buffer = NULL;
size_t frame_buffer_size = 0;
//mipi ldo
esp_ldo_channel_handle_t ldo_mipi_phy = NULL;
esp_ldo_channel_config_t ldo_mipi_phy_config = {
.chan_id = CONFIG_EXAMPLE_USED_LDO_CHAN_ID,
.voltage_mv = CONFIG_EXAMPLE_USED_LDO_VOLTAGE_MV,
};
ESP_ERROR_CHECK(esp_ldo_acquire_channel(&ldo_mipi_phy_config, &ldo_mipi_phy));
/**
* @background
* Sensor use RAW8
* ISP convert to RGB565
*/
//---------------DSI Init------------------//
example_dsi_resource_alloc(&mipi_dsi_bus, &mipi_dbi_io, &mipi_dpi_panel, &frame_buffer);
//---------------Necessary variable config------------------//
frame_buffer_size = CONFIG_EXAMPLE_CAM_HRES * CONFIG_EXAMPLE_MIPI_DSI_DISP_VRES * EXAMPLE_RGB565_BITS_PER_PIXEL / 8;
ESP_LOGD(TAG, "CONFIG_EXAMPLE_CAM_HRES: %d, CONFIG_EXAMPLE_MIPI_DSI_DISP_VRES: %d, bits per pixel: %d", CONFIG_EXAMPLE_CAM_HRES, CONFIG_EXAMPLE_MIPI_DSI_DISP_VRES, EXAMPLE_RGB565_BITS_PER_PIXEL);
ESP_LOGD(TAG, "frame_buffer_size: %zu", frame_buffer_size);
ESP_LOGD(TAG, "frame_buffer: %p", frame_buffer);
esp_cam_ctlr_trans_t cam_trans = {
.buffer = frame_buffer,
.buflen = frame_buffer_size,
};
//--------Camera Sensor and SCCB Init-----------//
s_ledc_generate_dvp_xclk();
example_sensor_config_t cam_sensor_config = {
.i2c_port_num = I2C_NUM_0,
.i2c_sda_io_num = EXAMPLE_ISP_DVP_CAM_SCCB_SDA_IO,
.i2c_scl_io_num = EXAMPLE_ISP_DVP_CAM_SCCB_SCL_IO,
.port = ESP_CAM_SENSOR_DVP,
.format_name = EXAMPLE_CAM_FORMAT,
};
i2c_master_bus_handle_t i2c_bus_handle = NULL;
example_sensor_init(&cam_sensor_config, &i2c_bus_handle);
//---------------ISP Init------------------//
isp_proc_handle_t isp_proc = NULL;
esp_isp_processor_cfg_t isp_config = {
.clk_hz = 80 * 1000 * 1000,
.input_data_source = ISP_INPUT_DATA_SOURCE_DVP,
.input_data_color_type = ISP_COLOR_RAW8,
.output_data_color_type = ISP_COLOR_RGB565,
.has_line_start_packet = false,
.has_line_end_packet = false,
.h_res = CONFIG_EXAMPLE_CAM_HRES,
.v_res = CONFIG_EXAMPLE_CAM_VRES,
};
ESP_ERROR_CHECK(esp_isp_new_processor(&isp_config, &isp_proc));
ESP_ERROR_CHECK(esp_isp_enable(isp_proc));
//----------CAM Controller Init------------//
esp_cam_ctlr_handle_t cam_handle = NULL;
esp_cam_ctlr_isp_dvp_cfg_t dvp_config = {
.data_width = EXAMPLE_ISP_DVP_CAM_DATA_WIDTH,
.data_io = {
EXAMPLE_ISP_DVP_CAM_D0_IO,
EXAMPLE_ISP_DVP_CAM_D1_IO,
EXAMPLE_ISP_DVP_CAM_D2_IO,
EXAMPLE_ISP_DVP_CAM_D3_IO,
EXAMPLE_ISP_DVP_CAM_D4_IO,
EXAMPLE_ISP_DVP_CAM_D5_IO,
EXAMPLE_ISP_DVP_CAM_D6_IO,
EXAMPLE_ISP_DVP_CAM_D7_IO,
},
.pclk_io = EXAMPLE_ISP_DVP_CAM_PCLK_IO,
.hsync_io = EXAMPLE_ISP_DVP_CAM_HSYNC_IO,
.vsync_io = EXAMPLE_ISP_DVP_CAM_VSYNC_IO,
.de_io = EXAMPLE_ISP_DVP_CAM_DE_IO,
.io_flags.vsync_invert = 1,
.queue_items = 10,
};
ret = esp_cam_new_isp_dvp_ctlr(isp_proc, &dvp_config, &cam_handle);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "isp dvp init fail[%d]", ret);
return;
}
esp_cam_ctlr_evt_cbs_t cbs = {
.on_get_new_trans = s_camera_get_new_vb,
.on_trans_finished = s_camera_get_finished_trans,
};
if (esp_cam_ctlr_register_event_callbacks(cam_handle, &cbs, &cam_trans) != ESP_OK) {
ESP_LOGE(TAG, "ops register fail");
return;
}
ESP_ERROR_CHECK(esp_cam_ctlr_enable(cam_handle));
//---------------DPI Reset------------------//
example_dpi_panel_reset(mipi_dpi_panel);
//init to all white
memset(frame_buffer, 0xFF, frame_buffer_size);
esp_cache_msync((void *)frame_buffer, frame_buffer_size, ESP_CACHE_MSYNC_FLAG_DIR_C2M);
example_dpi_panel_init(mipi_dpi_panel);
if (esp_cam_ctlr_start(cam_handle) != ESP_OK) {
ESP_LOGE(TAG, "Driver start fail");
return;
}
while (1) {
ESP_ERROR_CHECK(esp_cam_ctlr_receive(cam_handle, &cam_trans, ESP_CAM_CTLR_MAX_DELAY));
}
}
static bool s_camera_get_new_vb(esp_cam_ctlr_handle_t handle, esp_cam_ctlr_trans_t *trans, void *user_data)
{
esp_cam_ctlr_trans_t cam_trans = *(esp_cam_ctlr_trans_t *)user_data;
trans->buffer = cam_trans.buffer;
trans->buflen = cam_trans.buflen;
return false;
}
static bool s_camera_get_finished_trans(esp_cam_ctlr_handle_t handle, esp_cam_ctlr_trans_t *trans, void *user_data)
{
return false;
}
飞控
//
低功耗 关闭蓝牙 WIFI
//
深度睡眠
mp4 jpg
avi esp friends
sd卡 存储 sdmcc spi 区别 速度 线数