共计 4639 个字符,预计需要花费 12 分钟才能阅读完成。
前言
之前看了官网玩过一个智能猫眼摄像头,我很有趣味,然而那个 IDF 平台属实难整,我光装置都整了一天,网不好下载的包可能有问题。而后命令行操作也比拟麻烦,我就想到了无敌的 arduino,ESP32-CAM 这个板子原本就是 arduino 反对的,移植下来问题不大。SDDC 连接器的移植,按之前我移植 SDDC 的教训,官网代码的代码标准和可移植性都很不错,移植的难度不大。那就开干!
硬件抉择
这我用的是和爱智官网一样的,安信可的 ESP32 – CAM 摄像头,这里举荐这种分成两块板子的这种,还有一种把串口集成到一块板子上的,发热太重大,烧录程序的时候须要手动按 IO0 而后按 RST 按键。
而后在 arduino 上抉择对应的开发板:
代码获取
从爱智官网的示例文章:ESP32 SDDC 设施开发 中能够获取到 SDDC 连接器的示例代码,和 SDDC 连接器的库,而后 arduino 的设施代码能够间接用 arduino 提供的示例代码来改。
当然,你们看到篇文章的时候,就不必管这么多啦︿(~︶~)︿
看过我之前文章的敌人必定都晓得,我早就帮大伙打包好了~
只须要去 — 咱们的微信公众号 我最厌恶增加各种微信公众号能力获取资源了,所以还是老样子,间接去灵感桌面的机密宝库 获取代码,或者间接 clone:
https://gitee.com/inspiration…
这次用到的是下图红圈的三个文件夹:
cjson:我移植的 cjson 库,就是规范的 cjson 库,放到 arduino 装置目录下的 libraries 文件夹里,百度一下 cjson 的函数应用就行了。
LIBESP32_CAM:是我移植自官网的 SDDC 连接器库,也是放入 libraries 文件夹里就行。外面是 SDDC 协定的处理函数,咱们不必管。因为这个库蕴含了 SDDC 协定相干内容,咱们就不再用原来的 libsddc 库了
sddc_demo 文件夹外面就是咱们各种传感器的 demo 代码了:
红圈的 ESP32_Camera 文件夹外面就是咱们代码,点进去就能看见 ESP32_Camera.ino 文件,双击文件会主动启动 arduino-IDE 关上代码。在工具 -> 端口 抉择对应的 COM 口而后点击上传就能够把代码烧录到板子里:
具体 arduino 应用教程能够看我之前的文章 arduino 开发领导 和 手把手带你 arduino 开发:基于 ESP32S 的第一个利用 - 红外测温枪(带引脚图)
代码解析
这个代码因为是移植爱智和 arduino 官网的代码,相干解析曾经很多了,我就重点讲一下我批改的局部。
我次要批改了 esp_on_message() 和 esp_send_image(),esp_connector_task() 函数。
代码如下:
/*
* Send image to connector
*/
static void esp_send_image(sddc_connector_t *conn)
{
void *data;
size_t size;
size_t totol_len = 0;
size_t len;
int ret;
data = fb->buf;
size = fb->len;
while (totol_len < size)
{//len = min((size - totol_len), (1460 - 16));
len = min((size - totol_len), 1420);
ret = sddc_connector_put(conn, data, len, (totol_len + len) == size);
if (ret < 0)
{sddc_printf("Failed to put!\n");
break;
}
totol_len += len;
data += len;
}
sddc_printf("Total put %d byte\n", totol_len);
esp_camera_fb_return(fb);
}
esp_send_image() 函数这次要是删掉了原有的调用拍照的函数,因为拍照的逻辑放在了 esp_on_message 函数中,而且 esp_camera_fb_get() 会返回一个 fd 作为全局变量应用,就不须要在这从新拍一张照片了。
/*
* sddc connector task
*/
static void esp_connector_task(void *arg)
{
sddc_connector_t *conn;
BaseType_t ret;
while (1)
{ret = xQueueReceive(conn_mqueue_handle, &conn, portMAX_DELAY);
if (ret == pdTRUE)
{esp_send_image(conn);
sddc_connector_destroy(conn);
cam_flag = 0;
}
}
vTaskDelete(NULL);
}
/*
* Lock timer callback function
*/
static void esp_lock_timer_callback(TimerHandle_t handle)
{sddc_printf("Close the door!\n");
}
esp_connector_task 函数退出了一个全局变量 cam_flag 防止因为拍照太快导致发送不及时。
/*
* Handle MESSAGE
*/
static sddc_bool_t esp_on_message(sddc_t *sddc, const uint8_t *uid, const char *message, size_t len)
{cJSON *root = cJSON_Parse(message);
cJSON *value;
cJSON *cam;
char *str;
int ret;
sddc_return_value_if_fail(root, SDDC_TRUE);
str = cJSON_Print(root);
sddc_goto_error_if_fail(str);
sddc_printf("esp_on_message: %s\n", str);
cJSON_free(str);
cam = cJSON_GetObjectItem(root, "cam");
if (cJSON_IsString(cam))
{if (strcmp(cam->valuestring, "image") == 0 && (cam_flag == 0))
{
char *str;
size_t size;
cam_flag = 1;
// 拍照
fb = esp_camera_fb_get();
sddc_goto_error_if_fail(fb);
// 取得图像数据大小
size = fb->len;
// 连接器
cJSON *connector = cJSON_GetObjectItem(root, "connector");
sddc_goto_error_if_fail(cJSON_IsObject(connector));
cJSON *port = cJSON_GetObjectItem(connector, "port");
sddc_goto_error_if_fail(cJSON_IsNumber(port));
cJSON *token = cJSON_GetObjectItem(connector, "token");
sddc_goto_error_if_fail(!token || cJSON_IsString(token));
sddc_connector_t *conn = sddc_connector_create(sddc, uid, port->valuedouble, token ? token->valuestring : NULL, SDDC_FALSE);
if (conn == NULL)
{
cam_flag = 0;
printf("error!\n");
}else
{printf("连贯创立胜利!\n");
}
sddc_goto_error_if_fail(conn);
// 创立 cJSON 对象
value = cJSON_CreateObject();
sddc_goto_error_if_fail(value);
// size 为图像数据大小
cJSON_AddNumberToObject(value, "size", size);
sddc_printf("Send picture to EdgerOS, file size %d\n", size);
// cJSON 对象转换成字符串
str = cJSON_Print(value);
sddc_goto_error_if_fail(str);
// 发送图片大小音讯
sddc_broadcast_message(sddc, str, strlen(str), 1, SDDC_FALSE, NULL);
cJSON_free(str);
if(conn_mqueue_handle == NULL)
{Serial.println("conn_mqueue_handle ERROR");
}
if(&conn == NULL)
{Serial.println("&conn ERROR");
}
ret = xQueueSend(conn_mqueue_handle, &conn, 0);
if (ret != pdTRUE)
{sddc_connector_destroy(conn);
sddc_goto_error_if_fail(ret == pdTRUE);
}
} else if (strcmp(cam->valuestring, "shoot") == 0)
{
cJSON *root = NULL;
char *str;
size_t size;
// 摄像头捕获一帧图像
fb = esp_camera_fb_get();
sddc_goto_error_if_fail(fb);
// 取得图像数据大小
size = fb->len;
// 创立 cJSON 对象
root = cJSON_CreateObject();
sddc_goto_error_if_fail(root);
// cmd 为 recv
cJSON_AddStringToObject(root, "cam", "image");
// size 为图像数据大小
cJSON_AddNumberToObject(root, "size", size);
sddc_printf("Send picture to EdgerOS, file size %d\n", size);
// cJSON 对象转换成字符串
str = cJSON_Print(root);
sddc_goto_error_if_fail(str);
// 发送音讯
sddc_broadcast_message(sddc, str, strlen(str), 1, SDDC_FALSE, NULL);
cJSON_free(str);
}
} else
{sddc_printf("Command no specify!\n");
}
error:
cJSON_Delete(root);
esp_camera_fb_return(fb);
return SDDC_TRUE;
}
次要改变是因为这一份官网代码的锁和摄像头是一体的,而且官网的 IDF 平台应用的 camera_run(),camera_get_data_size() 和 camera_get_fb() 这几个函数在 arduino 上没有,我改成了 esp_camera_fb_get(),还增加了一个在连接器之前先发送一个 size 用来校验图片完整性。
其余的设施初始化和配置啥的我都用的 arduino 示例代码的配置
总结
我智能猫眼的利用代码被我搞丢了,得去找官网看看那边有没有保留,所以临时没法展现。