esp32系列是高性价比物联网节点设备的代表,速度够快,自带WIFI又可以使用Arduino IDE编程,最近试用了一种带有OV2640摄像头的ESP32-CAM只要很简单地设置就可以做很多种工作,以下是试验记录。

        Arduino IDE要在首选项中在其他开发板管理器地址中填入https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json,再去开发板管理器界面中找到ESP32,点击安装后才能使用ESP32系列单片机。注意要联网才能安装。

  • 用作延时相机

    #include "esp_camera.h"
    #include "FS.h"                // SD Card ESP32
    #include "SD_MMC.h"            // SD Card ESP32
    #include "soc/soc.h"           // Disable brownout problems
    #include "soc/rtc_cntl_reg.h"  // Disable brownout problems
    #include "driver/rtc_io.h"
    #include <WiFi.h>
    #include "time.h"
    
    
    // REPLACE WITH YOUR NETWORK CREDENTIALS
    const char* ssid = "XXXXXX";
    const char* password = "XXXXXX";
    
    
    // REPLACE WITH YOUR TIMEZONE STRING: https://github.com/nayarsystems/posix_tz_db/blob/master/zones.csv
    String myTimezone ="CST-8";
    
    
    // Pin definition for CAMERA_MODEL_AI_THINKER
    // Change pin definition if you're using another ESP32 camera module
    #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
    
    
    // Stores the camera configuration parameters
    camera_config_t config;
    
    
    // Initializes the camera
    void configInitCamera(){
    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; //YUV422,GRAYSCALE,RGB565,JPEG
    config.grab_mode = CAMERA_GRAB_LATEST;
    
    
    // Select lower framesize if the camera doesn't support PSRAM
    if(psramFound()){
      config.frame_size = FRAMESIZE_UXGA; // FRAMESIZE_ + QVGA|CIF|VGA|SVGA|XGA|SXGA|UXGA
      config.jpeg_quality = 5; //0-63 lower number means higher quality
      config.fb_count = 1;
    } else {
      config.frame_size = FRAMESIZE_UXGA;
      config.jpeg_quality = 5;
      config.fb_count = 1;
    }
    
    // Initialize the Camera
    esp_err_t err = esp_camera_init(&config);
    if (err != ESP_OK) {
      Serial.printf("Camera init failed with error 0x%x", err);
      return;
    }
    }
    
    
    // Connect to wifi
    void  initWiFi(){
    WiFi.begin(ssid, password);
    Serial.println("Connecting Wifi");
    while (WiFi.status() != WL_CONNECTED) {
      Serial.print(".");
      delay(500);
    }
    }
    
    
    // Function to set timezone
    void setTimezone(String timezone){
    Serial.printf("  Setting Timezone to %s\n",timezone.c_str());
    setenv("TZ",timezone.c_str(),1);  //  Now adjust the TZ.  Clock settings are adjusted to show the new local time
    tzset();
    }
    
    
    // Connect to NTP server and adjust timezone
    void initTime(String timezone){
    struct tm timeinfo;
    Serial.println("Setting up time");
    configTime(0, 0, "pool.ntp.org");    // First connect to NTP server, with 0 TZ offset
    if(!getLocalTime(&timeinfo)){
      Serial.println(" Failed to obtain time");
      return;
    }
    Serial.println("Got the time from NTP");
    // Now we can set the real timezone
    setTimezone(timezone);
    }
    
    
    // Get the picture filename based on the current ime
    String getPictureFilename(){
    struct tm timeinfo;
    if(!getLocalTime(&timeinfo)){
      Serial.println("Failed to obtain time");
      return "";
    }
    char timeString[20];
    strftime(timeString, sizeof(timeString), "%Y-%m-%d_%H-%M-%S", &timeinfo);
    Serial.println(timeString);
    String filename = "/picture_" + String(timeString) +".jpg";
    return filename; 
    }
    
    
    // Initialize the micro SD card
    void initMicroSDCard(){
    // Start Micro SD card
    Serial.println("Starting SD Card");
    if(!SD_MMC.begin()){
      Serial.println("SD Card Mount Failed");
      return;
    }
    uint8_t cardType = SD_MMC.cardType();
    if(cardType == CARD_NONE){
      Serial.println("No SD Card attached");
      return;
    }
    }
    
    
    // Take photo and save to microSD card
    void takeSavePhoto(){
    // Take Picture with Camera
    camera_fb_t * fb = esp_camera_fb_get();
    
    //Uncomment the following lines if you're getting old pictures
    //esp_camera_fb_return(fb); // dispose the buffered image
    //fb = NULL; // reset to capture errors
    //fb = esp_camera_fb_get();
    
    if(!fb) {
      Serial.println("Camera capture failed");
      delay(1000);
      ESP.restart();
    }
    
    
    // Path where new picture will be saved in SD Card
    String path = getPictureFilename();
    Serial.printf("Picture file name: %s\n", path.c_str());
    
    // Save picture to microSD card
    fs::FS &fs = SD_MMC; 
    File file = fs.open(path.c_str(),FILE_WRITE);
    if(!file){
      Serial.printf("Failed to open file in writing mode");
    } 
    else {
      file.write(fb->buf, fb->len); // payload (image), payload length
      Serial.printf("Saved: %s\n", path.c_str());
    }
    file.close();
    esp_camera_fb_return(fb); 
    }
    
    
    void setup() {
    WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); // disable brownout detector
    
    
    Serial.begin(115200);
    delay(2000);
    
    
    // Initialize Wi-Fi
    initWiFi();
    // Initialize time with timezone
    initTime(myTimezone);    
    // Initialize the camera  
    Serial.print("Initializing the camera module...");
    configInitCamera();
    Serial.println("Ok!");
    // Initialize MicroSD
    Serial.print("Initializing the MicroSD card module... ");
    initMicroSDCard();
    }
    
    
    void loop() {    
    // Take and Save Photo
    takeSavePhoto();
    delay(60000);
    }

            在程序中修改SSID、PASSWORD,myTimezone设置时区字符串,在https://github.com/nayarsystems/posix_tz_db/blob/master/zones.csv中查找到属于当地的时区字符串;config.frame_size设置拍摄分辨率,config.jpeg_quality设置图像质量,0~63,数字越小图像质量越高,但有可能造成图像拍摄出现问题。loop()中delay()函数内是延时时间。
            图像质量实在差劲,最高分辨率UXGA下图像质量设置为0时所拍照片偶有撕裂现象,我一般设置为5。模块上电后按一下reset键,可以确保系统正常工作。

  • 用作网络摄影机

    #include "esp_camera.h"
    #include <WiFi.h>
    
    //
    // WARNING!!! PSRAM IC required for UXGA resolution and high JPEG quality
    //            Ensure ESP32 Wrover Module or other board with PSRAM is selected
    //            Partial images will be transmitted if image exceeds buffer size
    //
    //            You must select partition scheme from the board menu that has at least 3MB APP space.
    //            Face Recognition is DISABLED for ESP32 and ESP32-S2, because it takes up from 15 
    //            seconds to process single frame. Face Detection is ENABLED if PSRAM is enabled as well
    
    // ===================
    // Select camera model
    // ===================
    //#define CAMERA_MODEL_WROVER_KIT // Has PSRAM
    //#define CAMERA_MODEL_ESP_EYE // Has PSRAM
    //#define CAMERA_MODEL_ESP32S3_EYE // Has PSRAM
    //#define CAMERA_MODEL_M5STACK_PSRAM // Has PSRAM
    //#define CAMERA_MODEL_M5STACK_V2_PSRAM // M5Camera version B Has PSRAM
    //#define CAMERA_MODEL_M5STACK_WIDE // Has PSRAM
    //#define CAMERA_MODEL_M5STACK_ESP32CAM // No PSRAM
    //#define CAMERA_MODEL_M5STACK_UNITCAM // No PSRAM
    #define CAMERA_MODEL_AI_THINKER // Has PSRAM
    //#define CAMERA_MODEL_TTGO_T_JOURNAL // No PSRAM
    //#define CAMERA_MODEL_XIAO_ESP32S3 // Has PSRAM
    // ** Espressif Internal Boards **
    //#define CAMERA_MODEL_ESP32_CAM_BOARD
    //#define CAMERA_MODEL_ESP32S2_CAM_BOARD
    //#define CAMERA_MODEL_ESP32S3_CAM_LCD
    //#define CAMERA_MODEL_DFRobot_FireBeetle2_ESP32S3 // Has PSRAM
    //#define CAMERA_MODEL_DFRobot_Romeo_ESP32S3 // Has PSRAM
    #include "camera_pins.h"
    
    // ===========================
    // Enter your WiFi credentials
    // ===========================
    const char* ssid = "XXXXXX";
    const char* password = "XXXXXX";
    
    void startCameraServer();
    void setupLedFlash(int pin);
    
    void setup() {
    Serial.begin(115200);
    Serial.setDebugOutput(true);
    Serial.println();
    
    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_sccb_sda = SIOD_GPIO_NUM;
    config.pin_sccb_scl = SIOC_GPIO_NUM;
    config.pin_pwdn = PWDN_GPIO_NUM;
    config.pin_reset = RESET_GPIO_NUM;
    config.xclk_freq_hz = 20000000;
    config.frame_size = FRAMESIZE_UXGA;
    config.pixel_format = PIXFORMAT_JPEG; // for streaming
    //config.pixel_format = PIXFORMAT_RGB565; // for face detection/recognition
    config.grab_mode = CAMERA_GRAB_WHEN_EMPTY;
    config.fb_location = CAMERA_FB_IN_PSRAM;
    config.jpeg_quality = 5;
    config.fb_count = 1;
    
    // if PSRAM IC present, init with UXGA resolution and higher JPEG quality
    //                      for larger pre-allocated frame buffer.
    if(config.pixel_format == PIXFORMAT_JPEG){
      if(psramFound()){
        config.jpeg_quality = 5;
        config.fb_count = 2;
        config.grab_mode = CAMERA_GRAB_LATEST;
      } else {
        // Limit the frame size when PSRAM is not available
        config.frame_size = FRAMESIZE_SVGA;
        config.fb_location = CAMERA_FB_IN_DRAM;
      }
    } else {
      // Best option for face detection/recognition
      config.frame_size = FRAMESIZE_240X240;
    #if CONFIG_IDF_TARGET_ESP32S3
      config.fb_count = 2;
    #endif
    }
    
    #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
    if(config.pixel_format == PIXFORMAT_JPEG){
      s->set_framesize(s, FRAMESIZE_QVGA);
    }
    
    #if defined(CAMERA_MODEL_M5STACK_WIDE) || defined(CAMERA_MODEL_M5STACK_ESP32CAM)
    s->set_vflip(s, 1);
    s->set_hmirror(s, 1);
    #endif
    
    #if defined(CAMERA_MODEL_ESP32S3_EYE)
    s->set_vflip(s, 1);
    #endif
    
    // Setup LED FLash if LED pin is defined in camera_pins.h
    #if defined(LED_GPIO_NUM)
    setupLedFlash(LED_GPIO_NUM);
    #endif
    
    WiFi.begin(ssid, password);
    WiFi.setSleep(false);
    
    while (WiFi.status() != WL_CONNECTED) {
      delay(500);
      Serial.print(".");
    }
    Serial.println("");
    Serial.println("WiFi connected");
    
    startCameraServer();
    
    Serial.print("Camera Ready! Use 'http://");
    Serial.print(WiFi.localIP());
    Serial.println("' to connect");
    }
    
    void loop() {
    // Do nothing. Everything is done in another task by the web server
    delay(10000);
    }

            在程序中修改SSID、PASSWORD,上传后打开串口监视器,按rst键,看模块IP地址,在浏览器中输入IP地址就进入网络摄像头界面,点Start Stream开始摄像头网络直播。各种参数可以在浏览器界面进行设置。
    esp32-cam.png

  • 人脸检测和人脸识别

            上面网络摄像头界面左边栏有人脸检测和人脸识别功能,把分辨率调整到320*240时可以开启,此时可以自动识别画面中出现的人脸,还可点击enroll face键预存需要识别的人脸。

        本记录将持续更新。

标签: none

添加新评论