欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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就是硬试才能试出来,很费时间…

相关标签: ESP32-CAM