ESP32-CAM移植和使用經驗分享

語言: CN / TW / HK

@ TOC

前言

之前我將愛智官方的程式碼移植到了 arduino 上,詳細可見 arduino 天下第一(暴論) -- 智慧貓眼與 SDDC 聯結器移植到 arduino 上

在這過程中我踩了一些坑,在這裡和大家分享一下。

arduino 操作介面

arduino 官方提供demo已經封裝很好了,只用呼叫一個函式就能完成拍攝上傳等一系列操作,但是如果這個介面不符合我們的需求,就只能自己同時改改了。

通過下面的連線可以看到 ESP32-CAM 底層的東西一些介面

http://github.com/espressif/arduino-esp32/releases/tag/2.0.2

或者你已經安裝了 ESP32-CAM 相關庫後可以去:

C:\Users\123456\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.5\tools\sdk\include\esp32-camera

可以看到一個 esp_camera.h 檔案,裡面有一些可以用到的介面和結構體。

/**
 * @brief Data structure of camera frame buffer
 */
typedef struct {
    uint8_t * buf;              /*!< Pointer to the pixel data */       // 這就是攝像頭拍下來的資料
    size_t len;                 /*!< Length of the buffer in bytes */
    size_t width;               /*!< Width of the buffer in pixels */
    size_t height;              /*!< Height of the buffer in pixels */
    pixformat_t format;         /*!< Format of the pixel data */
    struct timeval timestamp;   /*!< Timestamp since boot of the first DMA buffer of the frame */
} camera_fb_t;

#define ESP_ERR_CAMERA_BASE 0x20000
#define ESP_ERR_CAMERA_NOT_DETECTED             (ESP_ERR_CAMERA_BASE + 1)
#define ESP_ERR_CAMERA_FAILED_TO_SET_FRAME_SIZE (ESP_ERR_CAMERA_BASE + 2)
#define ESP_ERR_CAMERA_FAILED_TO_SET_OUT_FORMAT (ESP_ERR_CAMERA_BASE + 3)
#define ESP_ERR_CAMERA_NOT_SUPPORTED            (ESP_ERR_CAMERA_BASE + 4)
/**
 * @brief Initialize the camera driver
 *
 * @note call camera_probe before calling this function
 *
 * This function detects and configures camera over I2C interface,
 * allocates framebuffer and DMA buffers,
 * initializes parallel I2S input, and sets up DMA descriptors.
 *
 * Currently this function can only be called once and there is
 * no way to de-initialize this module.
 *
 * @param config  Camera configuration parameters
 *
 * @return ESP_OK on success
 */
esp_err_t esp_camera_init(const camera_config_t* config);

/**
 * @brief Deinitialize the camera driver
 *
 * @return
 *      - ESP_OK on success
 *      - ESP_ERR_INVALID_STATE if the driver hasn't been initialized yet
 */
esp_err_t esp_camera_deinit();

/**
 * @brief Obtain pointer to a frame buffer.
 *
 * @return pointer to the frame buffer
 */
camera_fb_t* esp_camera_fb_get();

/**
 * @brief Return the frame buffer to be reused again.
 *
 * @param fb    Pointer to the frame buffer
 */
void esp_camera_fb_return(camera_fb_t * fb);

/**
 * @brief Get a pointer to the image sensor control structure
 *
 * @return pointer to the sensor
 */
sensor_t * esp_camera_sensor_get();

/**
 * @brief Save camera settings to non-volatile-storage (NVS)
 * 
 * @param key   A unique nvs key name for the camera settings 
 */
esp_err_t esp_camera_save_to_nvs(const char *key);

/**
 * @brief Load camera settings from non-volatile-storage (NVS)
 * 
 * @param key   A unique nvs key name for the camera settings 
 */
esp_err_t esp_camera_load_from_nvs(const char *key);

程式碼解析和注意事項

攝像頭拍下來的資料和影象屬性都儲存在 camera_fb_t 結構體中,其中 buf 就是影象資料,其他的都是相關屬性

uint8_t * buf;              /*!< Pointer to the pixel data */       // 這就是攝像頭拍下來的資料
    size_t len;                 /*!< Length of the buffer in bytes */
    size_t width;               /*!< Width of the buffer in pixels */
    size_t height;              /*!< Height of the buffer in pixels */
    pixformat_t format;         /*!< Format of the pixel data */
    struct timeval timestamp;   /*!< Timestamp since boot of the first DMA buffer of the frame */
} camera_fb_t;

然後通過 esp_camera_fb_get 可以拍攝一幀畫面,並且返回 camera_fb_t 結構體指標。

沒錯,這個介面不僅是註釋中描述那樣返回一個指標,他在返回之前會先拍攝一幀畫面,然後才返回指標,所以大家不用去找專門的拍攝函數了,也不用擔心直接呼叫這個函式會返回空指標。

/**
 * @brief Obtain pointer to a frame buffer.
 *
 * @return pointer to the frame buffer
 */
camera_fb_t* esp_camera_fb_get();

另外每使用完一幀畫面後一定要呼叫 esp_camera_fb_return 釋放掉不用的資料,否則沒辦法拍攝下一幀。

/**
 * @brief Return the frame buffer to be reused again.
 *
 * @param fb    Pointer to the frame buffer
 */
void esp_camera_fb_return(camera_fb_t * fb);

另外這些介面都是比較底層原始的介面,沒有 IDF 平臺封裝的 camera_run()camera_get_data_size 等函式這麼安全,所以無法使用官方程式碼中那種通過判斷時間間隔控制拍照的方法,只能在應用端控制拍攝頻率

總結

這玩意現在只能說勉強能用,因為這玩意很容易過熱,持續拍攝一段時間後,訊號會逐漸不穩定,直到徹底掉線。