最简单DIY基于ESP32CAM的物联网相机系统①(用网页实现拍照图传)

Posted daodanjishui

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最简单DIY基于ESP32CAM的物联网相机系统①(用网页实现拍照图传)相关的知识,希望对你有一定的参考价值。

最简单DIY基于ESP32CAM的物联网相机系统系列文章目录

第一篇:最简单DIY基于ESP32CAM的物联网相机系统①(用网页实现拍照图传)



前言

    daodanjishui物联网核心原创技术之最简单DIY基于ESP32CAM的物联网相机系统①(用网页实现拍照图传)。
    发布这篇博文的季节是我发布第一个ESP32教程的第一周年纪念时期,翻看我备份的第一个源码是2020.5.23,也说明了周年纪念日也是我接触和入门ESP32的周年纪念日。而ESP32CAM这个款单片机在国内确实用得不多,使用者和开发者也不多,所以说在网上学习的资源更是少之又少,甚至能搜到的教程还有我自己出品的,ESP32CAM是一个待开发的新大陆,在这里我要创立一个:最简单DIY基于ESP32CAM的物联网相机系统系列专栏记录下我原创开源的幸福瞬间。
    因为这个ESP32,所以我才接触了Arduino这个调包调库的IDE。以前十年的嵌入式积累也比不上使用这个IDE能达到的高度,几天时间就可以编写出一个成型的电子设计。呵呵,但是也感谢我十年前没有接触这个Arduino集成开发环境,因为不断地“吃快餐”和“拿来主义”会让我提前“发育不良”。嵌入式开发的功力来源于时间积累而不是一个开发工具。当一个嵌入式开发人员“成年”之后,再吃“Arduino快餐”,你会发现节约时间和精力又不影响“发育”,确实是一件美差事,这时候要底层技术有底层技术,要调包调库也轻轻松松,到了这样的地步,其实感觉嵌入式开发也没有人们想象中那么痛苦吧。
    现在很多学校直接教授高级语言:C++、Python、Java等等,甚至都越过底层的C语言,甚至很多同学觉得连最基本的C语言版本的socket套接字编程变得比登天还难。社会的需求也造就了“吃快餐”环境,嵌入式开发的岗位工资比前端开发的工资少了至少5K。在国内献身于嵌入式的人才不多,大多数到半途就转行了,太残酷了。市面上活跃的总是那些用java写的网络斗地主,安卓客户端运行的麻辣炸金花,普通上班族下班之后玩玩斗地主,看看网络主播小视频打赏下主播也成了平常事。
    那么网上虚拟的东西那么多?哪些会用到嵌入式开发的知识呢?是不是嵌入式开发钱途渺茫呢?芯片又那么贵,硬件又那么烧钱,那么daodanjishui还要开个“最简单DIY基于ESP32CAM的物联网相机系统”CSDN专栏还有意义么?目前来说,物联网时代的来临,各种嵌入式实时操作系统能够在廉价的单片机上运行,还有鸿蒙系统的出炉,虽然很多友商不愿意基于鸿蒙开发产品,但是该系统给国内物联网技术注入新鲜的血液,有些人会说其实很少人用鸿蒙系统来开发嵌入式的吧,目前确实是这个情况。但是现在物联网技术的应用确实很广泛:平衡车、自动售卖机、共享电车、共享汽车、共享充电宝、共享按摩椅、智慧屏、广告屏、智能监控摄像头、智能手环、智能秤、机顶盒、智能路由器、智能家居和还有我正在推出的智能彩灯,闭着眼睛都能数出一大堆未来将要流行起来的高性价比的电子设备。随着“共享时代”和“物联网时代”的悄悄来临,国内以物联网形态下的嵌入式开发将会迎来新的发展时机。作为嵌入式技术的开发人员如果真的能坚持下来咬住青山不放松,我坚信属于他们的春天即将会到来的。


一、最简单DIY基于ESP32CAM的物联网相机系统①(用网页实现拍照图传)是什么?

     在我的一篇博文:高性价比WIFI图传方案快速入门教程因为我只用了170行代码实现了嵌入式服务器ESP32高速wifi图传,在CSDN很多博主还在采用以前那个硬件串口线传输STM32单片机驱动的OV7670摄像头模块采集的图片,价格昂贵带FIFO的OV7670单摄像头就50块,STM32单片机的价格我还没有计算呢!ST公司芯片涨价了,STM32价格贵到离谱,成本也高,OV7670的像素才30万,图像也不清晰,还有些博主用ESP8266来传输STM32驱动OV7670拍摄的图片,这样用了三片单片机才完成无线图传,太麻烦了。
     而我这个ESP32CAM搭载的是OV 2640高清摄像头像素达到130万,ESP32+OV2640在某宝价格才24块,国产芯片不会受到芯片涨价潮流而涨价,并且我ESP32CAM的Arduino开发环境下的库自带摄像头SCCB控制总线的方案,把底层驱动剥离开来,要是用STM32来驱动摄像头,要在SCCB上下功夫了,而在ESP32CAM的摄像头二次开发上,开发者能在上层应用上开发自己喜欢的功能,非常潮流,只是国内用的人少,大部分国内开发者跑了老外对这个国产芯片写的摄像头测试程序,想起来都觉得尴尬,ESP32相比ESP8266的WIFI传输速度快了很多,处理速度也快了很多。在我这里,读者可以学到一个系列的中文版本的物联网ESP32CAM高清高速摄像头二次开发的原创开源核心技术,攻破上位机和下位机和服务器的开发。
     回到正题,本文要用ESP32CAM和摄像头实现在嵌入式主页(网页)采集图片信息显示在网页上,提取网页的图像信息,解码显示出图片。

二、实现需求

1.搭建ESP32CAM开发环境

    前面的博文写过详细的搭建步骤了:https://blog.csdn.net/niruxi0401/article/details/118500369
直接跳转

2.复制我写好原创开源源码

    通过用Arduino新建工程粘贴我的源码即可
第一个文件
camera_pins.h


#if defined(CAMERA_MODEL_WROVER_KIT)
#define PWDN_GPIO_NUM    -1
#define RESET_GPIO_NUM   -1
#define XCLK_GPIO_NUM    21
#define SIOD_GPIO_NUM    26
#define SIOC_GPIO_NUM    27

#define Y9_GPIO_NUM      35
#define Y8_GPIO_NUM      34
#define Y7_GPIO_NUM      39
#define Y6_GPIO_NUM      36
#define Y5_GPIO_NUM      19
#define Y4_GPIO_NUM      18
#define Y3_GPIO_NUM       5
#define Y2_GPIO_NUM       4
#define VSYNC_GPIO_NUM   25
#define HREF_GPIO_NUM    23
#define PCLK_GPIO_NUM    22

#elif defined(CAMERA_MODEL_ESP_EYE)
#define PWDN_GPIO_NUM    -1
#define RESET_GPIO_NUM   -1
#define XCLK_GPIO_NUM    4
#define SIOD_GPIO_NUM    18
#define SIOC_GPIO_NUM    23

#define Y9_GPIO_NUM      36
#define Y8_GPIO_NUM      37
#define Y7_GPIO_NUM      38
#define Y6_GPIO_NUM      39
#define Y5_GPIO_NUM      35
#define Y4_GPIO_NUM      14
#define Y3_GPIO_NUM      13
#define Y2_GPIO_NUM      34
#define VSYNC_GPIO_NUM   5
#define HREF_GPIO_NUM    27
#define PCLK_GPIO_NUM    25

#elif defined(CAMERA_MODEL_M5STACK_PSRAM)
#define PWDN_GPIO_NUM     -1
#define RESET_GPIO_NUM    15
#define XCLK_GPIO_NUM     27
#define SIOD_GPIO_NUM     25
#define SIOC_GPIO_NUM     23

#define Y9_GPIO_NUM       19
#define Y8_GPIO_NUM       36
#define Y7_GPIO_NUM       18
#define Y6_GPIO_NUM       39
#define Y5_GPIO_NUM        5
#define Y4_GPIO_NUM       34
#define Y3_GPIO_NUM       35
#define Y2_GPIO_NUM       32
#define VSYNC_GPIO_NUM    22
#define HREF_GPIO_NUM     26
#define PCLK_GPIO_NUM     21

#elif defined(CAMERA_MODEL_M5STACK_WIDE)
#define PWDN_GPIO_NUM     -1
#define RESET_GPIO_NUM    15
#define XCLK_GPIO_NUM     27
#define SIOD_GPIO_NUM     22
#define SIOC_GPIO_NUM     23

#define Y9_GPIO_NUM       19
#define Y8_GPIO_NUM       36
#define Y7_GPIO_NUM       18
#define Y6_GPIO_NUM       39
#define Y5_GPIO_NUM        5
#define Y4_GPIO_NUM       34
#define Y3_GPIO_NUM       35
#define Y2_GPIO_NUM       32
#define VSYNC_GPIO_NUM    25
#define HREF_GPIO_NUM     26
#define PCLK_GPIO_NUM     21

#elif defined(CAMERA_MODEL_AI_THINKER)
#define PWDN_GPIO_NUM     32
#define RESET_GPIO_NUM    -1
#define XCLK_GPIO_NUM      0
#define SIOD_GPIO_NUM     26
#define SIOC_GPIO_NUM     27

#define Y9_GPIO_NUM       35
#define Y8_GPIO_NUM       34
#define Y7_GPIO_NUM       39
#define Y6_GPIO_NUM       36
#define Y5_GPIO_NUM       21
#define Y4_GPIO_NUM       19
#define Y3_GPIO_NUM       18
#define Y2_GPIO_NUM        5
#define VSYNC_GPIO_NUM    25
#define HREF_GPIO_NUM     23
#define PCLK_GPIO_NUM     22

#elif defined(CAMERA_MODEL_TTGO_T_JOURNAL)
#define PWDN_GPIO_NUM      0
#define RESET_GPIO_NUM    15
#define XCLK_GPIO_NUM     27
#define SIOD_GPIO_NUM     25
#define SIOC_GPIO_NUM     23

#define Y9_GPIO_NUM       19
#define Y8_GPIO_NUM       36
#define Y7_GPIO_NUM       18
#define Y6_GPIO_NUM       39
#define Y5_GPIO_NUM        5
#define Y4_GPIO_NUM       34
#define Y3_GPIO_NUM       35
#define Y2_GPIO_NUM       17
#define VSYNC_GPIO_NUM    22
#define HREF_GPIO_NUM     26
#define PCLK_GPIO_NUM     21

#else
#error "Camera model not selected"
#endif

第二个文件:CameraWebServer.ino

//国内ESP32CAM物联网相机开源项目
//作者:daodanjishui
//时间:2021.4.18
//QQ:
#include "esp_camera.h"
#include <WiFi.h>
#include <WebServer.h>
#include <WiFiClient.h>
#define CAMERA_MODEL_AI_THINKER // Has PSRAM
#include "camera_pins.h"
IPAddress apIP(192, 168, 4, 1);//ESP32主页的IP地址,写死了地址
const int serverPort0 = 80;//ESP32主页的端口号
WebServer webServer(serverPort0); 
String msg;//图片信息字符串
//网页函数,传入参数是服务器IP,返回的是网页字符串
//首页示例网址,http://192.168.4.1
//采集图像信息网址,http://192.168.4.1/HandleVal?ssid=snapshot&password=daodanjishui
String  index_html(String WiFiAddr){
return  String("")+"<html> <meta http-equiv=\\"Content-Type\\" content=\\"text/html; charset=utf-8\\" /"+
"<head><meta http-equiv=\\"Content-Type\\" content=\\"text/html; charset=UTF-8\\">"+
"</head>"+
"<body>"+
"<h1>daodanjishui 经典图传程序</h1>"+
"<p></p> <form action=\\"HandleVal\\" method=\\"\\" name=\\"\\" >第一个参数是snapshot,第二个参数是daodanjishui,点击send发送图片给ESP主页<br>"+
"<input type=\\"text\\" value=\\"snapshot\\" name=\\"ssid\\" id=\\"cmd\\" size=\\"10\\" maxlength=\\"20\\">"+
"<input type=\\"text\\" value=\\"daodanjishui\\" name=\\"password\\" id=\\"cmd1\\" size=\\"10\\" maxlength=\\"20\\">"+
"<input type=\\"submit\\" value=\\"send\\" ><br>"+
"<h2>daodanjishui 原创经典值得期待!</h2>"+
" </form>"+
"</body>"+
"</html>";
}

void camera_init();
void wifi_init();
void webServer_init();
void handleRoot();
String getsnapshotstring();//给客户端发送图片十六进制字符串数据,没有多余的字符串
String getsnapshotstring(){//这个函数的功能是在ESP32的主页输入serial返回图片纯净十六进制字符串
    camera_fb_t *fb = esp_camera_fb_get();   
    if (fb){                   
                //Serial.printf("width: %d, height: %d, buf: 0x%x, len: %d\\n", fb->width, fb->height, fb->buf, fb->len);       
                 char data[10];
                 msg = "";
                for (int i = 0; i < fb->len; i++)
                {
                    sprintf(data, "%02X", *((fb->buf + i)));
                    msg += data;                     
                }
                    if (msg.length()>0){                                    
                         Serial.print(msg);//直接打印十六进制的字符串,客户端不能直接解码
                    }    

        esp_camera_fb_return(fb);
        return msg;//这个图片信息字符串是给浏览器查看的
    }
    return "";
  }

void camera_init(){
  camera_config_t config;
  config.ledc_channel = LEDC_CHANNEL_0;
  config.ledc_timer = LEDC_TIMER_0;
  config.pin_d0 = Y2_GPIO_NUM;
  config.pin_d1 = Y3_GPIO_NUM;
  config.pin_d2 = Y4_GPIO_NUM;
  config.pin_d3 = Y5_GPIO_NUM;
  config.pin_d4 = Y6_GPIO_NUM;
  config.pin_d5 = Y7_GPIO_NUM;
  config.pin_d6 = Y8_GPIO_NUM;
  config.pin_d7 = Y9_GPIO_NUM;
  config.pin_xclk = XCLK_GPIO_NUM;
  config.pin_pclk = PCLK_GPIO_NUM;
  config.pin_vsync = VSYNC_GPIO_NUM;
  config.pin_href = HREF_GPIO_NUM;
  config.pin_sscb_sda = SIOD_GPIO_NUM;
  config.pin_sscb_scl = SIOC_GPIO_NUM;
  config.pin_pwdn = PWDN_GPIO_NUM;
  config.pin_reset = RESET_GPIO_NUM;
  config.xclk_freq_hz = 20000000;
  config.pixel_format = PIXFORMAT_JPEG;
  // if PSRAM IC present, init with UXGA resolution and higher JPEG quality
  //                      for larger pre-allocated frame buffer.
  if(psramFound()){
    config.frame_size = FRAMESIZE_UXGA;
    config.jpeg_quality = 10;
    config.fb_count = 2;
  } else {
    config.frame_size = FRAMESIZE_SVGA;
    config.jpeg_quality = 12;
    config.fb_count = 1;
  }
#if defined(CAMERA_MODEL_ESP_EYE)
  pinMode(13, INPUT_PULLUP);
  pinMode(14, INPUT_PULLUP);
#endif
  // camera init
  esp_err_t err = esp_camera_init(&config);
  if (err != ESP_OK) {
    Serial.printf("Camera init failed with error 0x%x", err);
    return;
  }
  sensor_t * s = esp_camera_sensor_get();
  // initial sensors are flipped vertically and colors are a bit saturated
  if (s->id.PID == OV3660_PID) {
    s->set_vflip(s, 1); // flip it back
    s->set_brightness(s, 1); // up the brightness just a bit
    s->set_saturation(s, -2); // lower the saturation
  }
  // drop down frame size for higher initial frame rate
  s->set_framesize(s, FRAMESIZE_QVGA);
#if defined(CAMERA_MODEL_M5STACK_WIDE)
  s->set_vflip(s, 1);
  s->set_hmirror(s, 1);
#endif    
}

void wifi_init(){
  WiFi.mode(WIFI_AP);
  WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));
  WiFi.softAP("dandaojishui ESP32CAM");
  WiFi.begin();
  Serial.println("AP is ok");  
}

void webServer_init(){
   webServer.on("/", HTTP_GET,handleRoot);//显示主页
   webServer.on("/HandleVal", HTTP_GET, HandleVal);//接收配网提交的参数
   webServer.onNotFound([]() {
    String message = "Hello daodanjishui!\\n\\n";
    message += "URI: ";
    message += webServer.uri();
    webServer.send(200, "text/plain", message);
  });

    webServer.begin();
    Serial.println("webServer is ok");   
}

void handleRoot() {//对客户端请求返回值处理
  webServer.send(200, "text/html", index_html("192.168.4.1")); //!!!注意返回网页需要用"text/html" !!!
  Serial.println("用户访问了ESP32主页");
}
void HandleVal()//对客户端请求返回值处理
{
    String wifis = webServer.arg("ssid"); //从javascript发送的数据中找ssid的值
    String wifip = webServer.arg("password"); //从JavaScript发送的数据中找password的值
    if(wifis.equals("snapshot")){      
      String mymsg=getsnapshotstring();//这个函数的功能是在ESP32的主页输入serial返回

以上是关于最简单DIY基于ESP32CAM的物联网相机系统①(用网页实现拍照图传)的主要内容,如果未能解决你的问题,请参考以下文章

最简单DIY基于ESP32CAM的物联网相机系统⑥(用上位机VS2013 MFC实现WIFI图传)

ESP32CAM拍照POST上传

Python + ESP32 DIY炫酷的物联网远程机械臂

Python + ESP32 DIY炫酷的物联网远程机械臂

最简单DIY基于ESP8266的智能彩灯⑥(Android开发通过WIFI控制彩灯实现表白神器)

Arduino ESP32-CAM 学习之旅① 认识ESP32-CAM,搭建环境,运行第一个程序