arduino 天下第一(暴论) -- 智能猫眼与 SDDC 连接器移植到 arduino 上
前言
之前看了官方玩过一个智能猫眼摄像头,我很有兴趣,但是那个 IDF 平台属实难整,我光安装都整了一天,网不好下载的包可能有问题。然后命令行操作也比较麻烦,我就想到了无敌的 arduino ,ESP32-CAM 这个板子本来就是 arduino 支持的,移植上去问题不大。SDDC 连接器的移植,按之前我移植 SDDC 的经验,官方代码的代码规范和可移植性都很不错,移植的难度不大。那就开干!
硬件选择
这我用的是和爱智官方一样的,安信可的ESP32 - CAM 摄像头,这里推荐这种分成两块板子的这种,还有一种把串口集成到一块板子上的,发热太严重,烧录程序的时候需要手动按 IO0 然后按 RST 按键。


然后在 arduino 上选择对应的开发板:

代码获取
从爱智官方的示例文章:ESP32 SDDC 设备开发 中可以获取到SDDC 连接器的示例代码,和 SDDC 连接器的库,然后 arduino 的设备代码可以直接用 arduino 提供的示例代码来改。

当然,你们看到篇文章的时候,就不用管这么多啦︿( ̄︶ ̄)︿
看过我之前文章的朋友肯定都知道,我早就帮大伙打包好了~
只需要去 -- 我们的微信公众号 我最讨厌添加各种微信公众号才能获取资源了,所以还是老样子, 直接去灵感桌面的秘密宝库 获取代码,或者直接 clone:
这次用到的是下图红圈的三个文件夹:

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 示例代码的配置
总结
我智能猫眼的应用代码被我搞丢了,得去找官方看看那边有没有保留,所以暂时没法展示。

arduino 天下第一(暴论) -- 智能猫眼与 SDDC 连接器移植到 arduino 上的更多相关文章
- 进阶之路(中级篇) - 018 基于arduino的简易版智能衣架
一. 设备及要求 目的:制作一个可以自动根据事实的天气的状况进行对衣架上的衣服进行晾晒. 基础装置:可伸缩的晾衣架. 开发环境:Arduino1. 8.1 主控板:Arduino UNO 动力装 ...
- (树莓派、Arduino、物联网、智能家居、机器人)传感器、机械装置、电子元件
定制 PCB 1. 机械类 履带底盘 2. 传感器 温度传感器(temperature).湿度传感器(humidity) DHT11/DHT22 驱动:BCM2835 (被动)红外传感器(Passiv ...
- Eclipse配置详解(包括智能提示设置、智能提示插件修改,修改空格自动上屏、JDK配置、各种快捷键列表……)
Eclipse编辑器基本设置 1.添加行号 在边缘处右键 2.改字体 字体的一般配置 3.去掉拼写错误检查 4.Java代码风格 代码格式化 Ctrl + Shift + F 之后点击右边的New按钮 ...
- BootStrap 智能表单系列 九 表单图片上传的支持
本章介绍如何在生成表单后,可以支持上传图片后可以及时预览图片 代码如下(连接地址:https://github.com/xiexingen/Bootstrap-SmartForm/blob/maste ...
- Arduino control Eeprom by IIC method of using device address in Arduino
参考: 1.https://www.arduino.cc/ 2.https://www.arduino.cc/reference/en/ 3.https://www.arduino.cc/en/Ref ...
- Arduino+ESP32 之 驱动GC9A01圆形LCD(二),移植LVGL,跑示例程序,显示自制图片
在前文Arduino+ESP32 之 驱动GC9A01圆形LCD(一), 我们已经移植好了arduino GFX库, 该库的示例程序内,还有LVGL的示例程序哦. arduino环境下移植lvgl是很 ...
- 【智能家居篇】wifi网络接入原理(上)——扫描Scanning
转载请注明出处:http://blog.csdn.net/Righthek 谢谢! 对于低头党来说,在使用WIFI功能时,常常性的操作是打开手机上的WIFI设备,搜索到心目中的热点,输入passwor ...
- 【智能无线小车系列八】在树莓派上使用USB网卡
在这个腾“云”驾“物”(云:云计算,物:物联网)的时代,什么都可以没有,就是不能没有网络,树莓派也离不开它.本章节将详细介绍如何将树莓派接入互联网,因为有一些后期将要使用到的小软件需要联网进行下载和安 ...
- 【智能无线小车系列九】在树莓派上使用USB摄像头
材料准备: 1.树莓派 2.AS 4WD小车 3.WebCam 4.小米移动电源 5.TP—LINK 高增益150MUSB无线网卡 操作流程: 1.将WebCam插上树莓派后,首先要确认树莓派是否支持 ...
随机推荐
- Oracle 数据库应用开发 30 忌
原创 LaoYuanPython CSDN 今天 作者 | LaoYuanPython 责编 | 欧阳姝黎出品 | CSDN原力计划 引言 笔者及所在团队从 2000 年开始的 CRM 等 ...
- [邮件服务]Foxmail安装及配置指引(Windows)
操作指引: Step1:访问Foxmail邮箱官网:https://www.foxmail.com/,选择"Windows"版,点击"立即下载". Step2: ...
- Java容器基础概况
一.什么是Java容器 书写程序时,我们常常需要对大量的对象引用进行管理.为了实现有效的归类管理,我们常常将同类的引用放置在同一个数据容器中.Java容器类是java提供的工具包,包含了常用的数据结构 ...
- 部署新项目自动对数据库进行migrate和让用户收到创建用户/超级用户信息
当项目中的models有数据表的时候,普通做法是用docke exec -it hello_web_1 bash,进入容器进行migrate,但是我们想要容器一启动就自动创建数据表,可以修改docke ...
- Spring AOP and AspectJ AOP 有什么区别?
Spring AOP 基于动态代理方式实现:AspectJ 基于静态代理方式实现.Spring AOP 仅支持方法级别的 PointCut:提供了完全的 AOP 支持,它还支持属性级别的 PointC ...
- 全页缓存FPC?
除基本的会话 token 之外,Redis 还提供很简便的 FPC 平台.回到一致性问题, 即使重启了 Redis 实例,因为有磁盘的持久化,用户也不会看到页面加载速度的 下降,这是一个极大改进,类似 ...
- jsp:useBean报错The value for the useBean class attribute X is invalid
一.解决方法 1.先检查<jsp:useBean id="dog" class="cn.edu.dgut.el.tools.Dog" scope=&quo ...
- BMZCTF WEB_ezeval
WEB_ezeval 进入环境,源码给出 <?php highlight_file(__FILE__); $cmd=$_POST['cmd']; $cmd=htmlspecialchars($c ...
- C++ | 简单工厂模式 | 复数计算器
简单工厂模式最直观的一个应用便是实现一个计算器的程序. 比如,公司让你给计算器添加一个幂运算的功能,你只需要设计一个幂运算的类,并实现幂运算的逻辑,然后让该类继承自运算类即可. 简单工厂模式: 简单工 ...
- 你不需要基于 CSS Grid 的栅格布局系统
在过去的几个星期里,我开始看到基于 CSS Grid 的布局框架和栅格系统的出现.我们惊讶它为什么出现的这么晚.但除了使用 CSS Grid 栅格化布局,我至今还没有看到任何框架能提供其他有价值的东西 ...