200浏览
查看: 200|回复: 4

[项目] 【花雕学编程】Arduino动手做(230)---IP 视频流 Web 服务器

[复制链接]
【花雕学编程】Arduino动手做(230)---IP 视频流 Web 服务器图1

ESP32-Cam 是一款运行在 ESP32-S 芯片上并使用 OV2640 摄像头的小型摄像头模块。ESP32_Cam 也可以 OV7670 摄像头,但 OV2640 更好(更高的分辨率和内置的 JPEG 编码,这消除了 ESP32-S 的处理任务)。
ESP-32 Cam 规格ESP-32 系列
它支持 Wi-Fi (802.11b/g/n)
支持蓝牙 (4.2 带 BLE)
内置 LED 闪光灯
9 个 IO 端口
支持 UART、SPI、I2C 和 PWM
内置 micro SD 读卡器
输入电源:3.3V / 5V(据报道,5V 供电比 3.3V 更稳定)
OV2640 摄像头
2 百万像素
阵列尺寸:UXGA (1600 x 1200)
镜头尺寸:1/4 英寸(6.35 毫米)
最大图像传输速率:15 帧/秒


【花雕学编程】Arduino动手做(230)---IP 视频流 Web 服务器图2

驴友花雕  中级技神
 楼主|

发表于 2024-9-12 18:17:35

【花雕学编程】Arduino动手做(230)---IP 视频流 Web 服务器

  【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
  实验二百三十:ESP32 CAM开发板 带OV2640摄像头模块 WIFI+蓝牙模块
  项目实验之十三:ESP32-CAM监控 IP 摄像头托管一个视频流 Web 服务器

实验开源代码

  1. /*
  2.   【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
  3.   实验二百三十:ESP32 CAM开发板 带OV2640摄像头模块 WIFI+蓝牙模块
  4.   项目实验之十三:ESP32-CAM监控 IP 摄像头托管一个视频流 Web 服务器
  5. */
  6. #include "esp_camera.h" // 引入ESP32摄像头库
  7. #include <WiFi.h> // 引入Wi-Fi库
  8. #include "esp_timer.h" // 引入定时器库
  9. #include "img_converters.h" // 引入图像转换库
  10. #include "Arduino.h" // 引入Arduino核心库
  11. #include "fb_gfx.h" // 引入帧缓冲图形库
  12. #include "soc/soc.h" // 引入系统级库,用于禁用掉电问题
  13. #include "soc/rtc_cntl_reg.h"  // 引入RTC控制寄存器库,用于禁用掉电问题
  14. #include "esp_http_server.h" // 引入HTTP服务器库
  15. // 替换为你的Wi-Fi网络凭据
  16. const char* ssid = "zhz3";
  17. const char* password = "z156721";
  18. #define PART_BOUNDARY "123456789000000000000987654321" // 定义边界字符串
  19. // 测试过的摄像头模型
  20. #define CAMERA_MODEL_AI_THINKER
  21. //#define CAMERA_MODEL_M5STACK_PSRAM
  22. //#define CAMERA_MODEL_M5STACK_WITHOUT_PSRAM
  23. // 未测试的摄像头模型
  24. //#define CAMERA_MODEL_WROVER_KIT
  25. #if defined(CAMERA_MODEL_WROVER_KIT)
  26.   #define PWDN_GPIO_NUM    -1
  27.   #define RESET_GPIO_NUM   -1
  28.   #define XCLK_GPIO_NUM    21
  29.   #define SIOD_GPIO_NUM    26
  30.   #define SIOC_GPIO_NUM    27
  31.   
  32.   #define Y9_GPIO_NUM      35
  33.   #define Y8_GPIO_NUM      34
  34.   #define Y7_GPIO_NUM      39
  35.   #define Y6_GPIO_NUM      36
  36.   #define Y5_GPIO_NUM      19
  37.   #define Y4_GPIO_NUM      18
  38.   #define Y3_GPIO_NUM       5
  39.   #define Y2_GPIO_NUM       4
  40.   #define VSYNC_GPIO_NUM   25
  41.   #define HREF_GPIO_NUM    23
  42.   #define PCLK_GPIO_NUM    22
  43. #elif defined(CAMERA_MODEL_M5STACK_PSRAM)
  44.   #define PWDN_GPIO_NUM     -1
  45.   #define RESET_GPIO_NUM    15
  46.   #define XCLK_GPIO_NUM     27
  47.   #define SIOD_GPIO_NUM     25
  48.   #define SIOC_GPIO_NUM     23
  49.   
  50.   #define Y9_GPIO_NUM       19
  51.   #define Y8_GPIO_NUM       36
  52.   #define Y7_GPIO_NUM       18
  53.   #define Y6_GPIO_NUM       39
  54.   #define Y5_GPIO_NUM        5
  55.   #define Y4_GPIO_NUM       34
  56.   #define Y3_GPIO_NUM       35
  57.   #define Y2_GPIO_NUM       32
  58.   #define VSYNC_GPIO_NUM    22
  59.   #define HREF_GPIO_NUM     26
  60.   #define PCLK_GPIO_NUM     21
  61. #elif defined(CAMERA_MODEL_M5STACK_WITHOUT_PSRAM)
  62.   #define PWDN_GPIO_NUM     -1
  63.   #define RESET_GPIO_NUM    15
  64.   #define XCLK_GPIO_NUM     27
  65.   #define SIOD_GPIO_NUM     25
  66.   #define SIOC_GPIO_NUM     23
  67.   
  68.   #define Y9_GPIO_NUM       19
  69.   #define Y8_GPIO_NUM       36
  70.   #define Y7_GPIO_NUM       18
  71.   #define Y6_GPIO_NUM       39
  72.   #define Y5_GPIO_NUM        5
  73.   #define Y4_GPIO_NUM       34
  74.   #define Y3_GPIO_NUM       35
  75.   #define Y2_GPIO_NUM       17
  76.   #define VSYNC_GPIO_NUM    22
  77.   #define HREF_GPIO_NUM     26
  78.   #define PCLK_GPIO_NUM     21
  79. #elif defined(CAMERA_MODEL_AI_THINKER)
  80.   #define PWDN_GPIO_NUM     32
  81.   #define RESET_GPIO_NUM    -1
  82.   #define XCLK_GPIO_NUM      0
  83.   #define SIOD_GPIO_NUM     26
  84.   #define SIOC_GPIO_NUM     27
  85.   
  86.   #define Y9_GPIO_NUM       35
  87.   #define Y8_GPIO_NUM       34
  88.   #define Y7_GPIO_NUM       39
  89.   #define Y6_GPIO_NUM       36
  90.   #define Y5_GPIO_NUM       21
  91.   #define Y4_GPIO_NUM       19
  92.   #define Y3_GPIO_NUM       18
  93.   #define Y2_GPIO_NUM        5
  94.   #define VSYNC_GPIO_NUM    25
  95.   #define HREF_GPIO_NUM     23
  96.   #define PCLK_GPIO_NUM     22
  97. #else
  98.   #error "Camera model not selected"
  99. #endif
  100. static const char* _STREAM_CONTENT_TYPE = "multipart/x-mixed-replace;boundary=" PART_BOUNDARY;
  101. static const char* _STREAM_BOUNDARY = "\r\n--" PART_BOUNDARY "\r\n";
  102. static const char* _STREAM_PART = "Content-Type: image/jpeg\r\nContent-Length: %u\r\n\r\n";
  103. httpd_handle_t stream_httpd = NULL;
  104. static esp_err_t stream_handler(httpd_req_t *req){
  105.   camera_fb_t * fb = NULL;
  106.   esp_err_t res = ESP_OK;
  107.   size_t _jpg_buf_len = 0;
  108.   uint8_t * _jpg_buf = NULL;
  109.   char * part_buf[64];
  110.   res = httpd_resp_set_type(req, _STREAM_CONTENT_TYPE);
  111.   if(res != ESP_OK){
  112.     return res;
  113.   }
  114.   while(true){
  115.     fb = esp_camera_fb_get();
  116.     if (!fb) {
  117.       Serial.println("Camera capture failed");
  118.       res = ESP_FAIL;
  119.     } else {
  120.       if(fb->width > 400){
  121.         if(fb->format != PIXFORMAT_JPEG){
  122.           bool jpeg_converted = frame2jpg(fb, 80, &_jpg_buf, &_jpg_buf_len);
  123.           esp_camera_fb_return(fb);
  124.           fb = NULL;
  125.           if(!jpeg_converted){
  126.             Serial.println("JPEG compression failed");
  127.             res = ESP_FAIL;
  128.           }
  129.         } else {
  130.           _jpg_buf_len = fb->len;
  131.           _jpg_buf = fb->buf;
  132.         }
  133.       }
  134.     }
  135.     if(res == ESP_OK){
  136.       size_t hlen = snprintf((char *)part_buf, 64, _STREAM_PART, _jpg_buf_len);
  137.       res = httpd_resp_send_chunk(req, (const char *)part_buf, hlen);
  138.     }
  139.     if(res == ESP_OK){
  140.       res = httpd_resp_send_chunk(req, (const char *)_jpg_buf, _jpg_buf_len);
  141.     }
  142.     if(res == ESP_OK){
  143.       res = httpd_resp_send_chunk(req, _STREAM_BOUNDARY, strlen(_STREAM_BOUNDARY));
  144.     }
  145.     if(fb){
  146.       esp_camera_fb_return(fb);
  147.       fb = NULL;
  148.       _jpg_buf = NULL;
  149.     } else if(_jpg_buf){
  150.       free(_jpg_buf);
  151.       _jpg_buf = NULL;
  152.     }
  153.     if(res != ESP_OK){
  154.       break;
  155.     }
  156.     //Serial.printf("MJPG: %uB\n",(uint32_t)(_jpg_buf_len));
  157.   }
  158.   return res;
  159. }
  160. void startCameraServer(){
  161.   httpd_config_t config = HTTPD_DEFAULT_CONFIG();
  162.   config.server_port = 80;
  163.   httpd_uri_t index_uri = {
  164.     .uri       = "/",
  165.     .method    = HTTP_GET,
  166.     .handler   = stream_handler,
  167.     .user_ctx  = NULL
  168.   };
  169.   
  170.   //Serial.printf("Starting web server on port: '%d'\n", config.server_port);
  171.   if (httpd_start(&stream_httpd, &config) == ESP_OK) {
  172.     httpd_register_uri_handler(stream_httpd, &index_uri);
  173.   }
  174. }
  175. void setup() {
  176.   WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); //disable brownout detector
  177.   Serial.begin(115200);
  178.   Serial.setDebugOutput(false);
  179.   
  180.   camera_config_t config;
  181.   config.ledc_channel = LEDC_CHANNEL_0;
  182.   config.ledc_timer = LEDC_TIMER_0;
  183.   config.pin_d0 = Y2_GPIO_NUM;
  184.   config.pin_d1 = Y3_GPIO_NUM;
  185.   config.pin_d2 = Y4_GPIO_NUM;
  186.   config.pin_d3 = Y5_GPIO_NUM;
  187.   config.pin_d4 = Y6_GPIO_NUM;
  188.   config.pin_d5 = Y7_GPIO_NUM;
  189.   config.pin_d6 = Y8_GPIO_NUM;
  190.   config.pin_d7 = Y9_GPIO_NUM;
  191.   config.pin_xclk = XCLK_GPIO_NUM;
  192.   config.pin_pclk = PCLK_GPIO_NUM;
  193.   config.pin_vsync = VSYNC_GPIO_NUM;
  194.   config.pin_href = HREF_GPIO_NUM;
  195.   config.pin_sscb_sda = SIOD_GPIO_NUM;
  196.   config.pin_sscb_scl = SIOC_GPIO_NUM;
  197.   config.pin_pwdn = PWDN_GPIO_NUM;
  198.   config.pin_reset = RESET_GPIO_NUM;
  199.   config.xclk_freq_hz = 20000000;
  200.   config.pixel_format = PIXFORMAT_JPEG;
  201.   
  202.   if(psramFound()){
  203.     config.frame_size = FRAMESIZE_UXGA;
  204.     config.jpeg_quality = 10;
  205.     config.fb_count = 2;
  206.   } else {
  207.     config.frame_size = FRAMESIZE_SVGA;
  208.     config.jpeg_quality = 12;
  209.     config.fb_count = 1;
  210.   }
  211.   
  212.   // Camera init
  213.   esp_err_t err = esp_camera_init(&config);
  214.   if (err != ESP_OK) {
  215.     Serial.printf("Camera init failed with error 0x%x", err);
  216.     return;
  217.   }
  218.   // Wi-Fi connection
  219.   WiFi.begin(ssid, password);
  220.   while (WiFi.status() != WL_CONNECTED) {
  221.     delay(500);
  222.     Serial.print(".");
  223.   }
  224.   Serial.println("");
  225.   Serial.println("WiFi connected");
  226.   
  227.   Serial.print("Camera Stream Ready! Go to: http://");
  228.   Serial.print(WiFi.localIP());
  229.   
  230.   // Start streaming web server
  231.   startCameraServer();
  232. }
  233. void loop() {
  234.   delay(1);
  235. }
复制代码



回复

使用道具 举报

驴友花雕  中级技神
 楼主|

发表于 2024-9-12 18:18:46

【花雕学编程】Arduino动手做(230)---IP 视频流 Web 服务器

实验串口返回情况

【花雕学编程】Arduino动手做(230)---IP 视频流 Web 服务器图1
回复

使用道具 举报

驴友花雕  中级技神
 楼主|

发表于 2024-9-12 18:22:40

【花雕学编程】Arduino动手做(230)---IP 视频流 Web 服务器

PC端和手机端视频流截图

【花雕学编程】Arduino动手做(230)---IP 视频流 Web 服务器图1
回复

使用道具 举报

驴友花雕  中级技神
 楼主|

发表于 2024-9-12 18:25:00

【花雕学编程】Arduino动手做(230)---IP 视频流 Web 服务器

【花雕学编程】Arduino动手做(230)---IP 视频流 Web 服务器图2

【花雕学编程】Arduino动手做(230)---IP 视频流 Web 服务器图1
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4

© 2013-2024 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail