ESP32-cam SD卡读写图片
程序员文章站
2022-07-12 10:55:31
...
因为最近要做一个项目,机器需要先拍摄照片,然后存储在SD卡,然后读取出来发送出去,由于巴发云物联网平台已经免费提供了图传的服务,因此省去我不少时间,所以剩下的就是SD卡的读写了。
将图片储存到SD卡里面
/********拍照并且存储到SD卡*********/
static esp_err_t take_photo( ) //将照片存储到sd卡中,从0开始命名 如:0.jpg
{
camera_fb_t * fb = esp_camera_fb_get();
static int num = 0;
Serial.println("Taking picture...");
if (!fb) {
Serial.println("Camera capture failed");
return ESP_FAIL;
}
else
{
//以下就是上一篇文章讲到的写入文件得到过程,但是一点点小区别
fs::FS &fs = SD_MMC;
// Serial.printf("Writing file: %s\n", path);
num_to_str(num,path);
Serial.println(path);
File file = fs.open(path, FILE_WRITE);
if (!file)
{
Serial.println("文件创建失败");
}
else
{
file.write(fb->buf , fb->len); //payload , lengte vd payload
Serial.println("成功写入照片");
num++;
file.close();//一定要关文件
}
//return the frame buffer back to the driver for reuse
esp_camera_fb_return(fb);
}
}
读取SD卡中的图片
注意看我的file.read()函数,网络上都是用循环读取文件参数,而我这个方法网上找不到,这也就是我在读取sd卡的时候耗费了2天的时间的原因,因为arduino很难去找库函数的位置,直接看代码吧,源码会贴在文章末尾
static esp_err_t send_photo( )
{
将sd卡图片数据提取到fb中//
camera_fb_t * fb =esp_camera_fb_get();
fb->len=0;
*fb->buf=NULL;
Serial.println(*fb->buf);
fs::FS &fs = SD_MMC;
num_to_str(0,path);//文件名
Serial.println(path);
File file = fs.open(path,FILE_READ);
if (!file)
{
Serial.println("文件打开失败");
file.close();
}
else
{
fb->len = file.size();//读取文件内大小
file.read( fb->buf, fb->len);//第一个参数是储存的buf,第二个是读取的信息长度
file.close();
Serial.println("成功读取照片");
}
网络申请,发出图片//
HTTPClient http;
//设置请求url
http.begin(post_url);
//设置请求头部信息
http.addHeader("Content-Type", "image/jpg");
http.addHeader("Authorization", uid);
http.addHeader("Authtopic", topic);
if(sentWechat){ //判断是否需要推送到微信
http.addHeader("Wechatmsg", wechatMsg); //设置 http 请求头部信息
}
//发起请求,并获取状态码
int httpResponseCode = http.POST((uint8_t *)fb->buf, fb->len);
if(httpResponseCode==200){
//获取post请求后的服务器响应信息,json格式
String response = http.getString(); //Get the response to the request
Serial.print("Response Msg:");
Serial.println(response); // 打印服务器返回的信息
//json数据解析
StaticJsonDocument<200> doc;
DeserializationError error = deserializeJson(doc, response);
if (error) {
Serial.print(F("deserializeJson() failed: "));
Serial.println(error.c_str());
}
const char* url = doc["url"];
Serial.print("Get URL:");
Serial.println(url);//打印获取的URL
}else{
//错误请求
Serial.print("Error on sending POST: ");
Serial.println(httpResponseCode);
}
Serial.print("HTTP Response code: ");
Serial.println(httpResponseCode);
//清空数据
esp_camera_fb_return(fb);
//回收下次再用
http.end();
}
源码链接:
提取码:x91d
经验总结
由于C语言文件处理方面的知识不扎实,导致我走了很多弯路,费了很多时间
1:文件打开忘记关闭,程序会报错内存异常
2:
file.write(fb->buf , fb->len);
file.read(fb->buf, fb->len);
读取和写入,第一个参数都是指针参数,都是一个地址,指向储存信息的内存空间,第二个是长度
3:
typedef struct camera_fb_s {
uint8_t * buf;
size_t len;
size_t width;
size_t height;
pixformat_t format;
struct timeval timestamp;
size_t size;
uint8_t ref;
uint8_t bad;
struct camera_fb_s * next;
} camera_fb_int_t;
结构体中,buf是指针变量,所以fb->buf是缓存的地址,*fb->buf才是真正的内容,所以我们要清除缓存与字节长度的时候应该是这样操作:
fb->len=0;
*fb->buf=0;
刚开始时候一直在清除buf的地址,一直报错。。比如这样:fb->buf=0(指针方面的基础不牢啊)
如果对你有帮助麻烦点个赞,因为我在查资料的时候搜了全网都没有能正确读取SD卡数据的,网上的大多长这样;
while (file.available()) {
*fb->buf=file.read();//不断循环读取直到没有其他内容
}
这样读程序不会报错,但是出来的图片数据是有问题的,我猜测是因为fb->buf的指针需要依次位移才能全部读出来,反正我在这边饶了很久,后面一直尝试才把数据读出来的,真的花了很多时间啊…
还有就是尽量用vscode写程序吧,用Arduno真的出了问题很难找到解决方案,很难查找函数内容,各种库相当多,提供了便利的同时,也增大了修复的难度,就比如我那个file.read()函数,换做在vscode上面我只需要沿着函数一直找下去就能知道这个函数怎么用了,或者问题出在哪,而arduino就是硬试才能试出来,很费时间…
上一篇: jdbc调用存储过程。 JDBCSQL