前言

之前我将爱智官网的代码移植到了 arduino 上,具体可见arduino 天下第一(暴论) -- 智能猫眼与 SDDC 连接器移植到 arduino 上
在这过程中我踩了一些坑,在这里和大家分享一下。


arduino 操作接口

arduino 官网提供demo曾经封装很好了,只用调用一个函数就能实现拍摄上传等一系列操作,然而如果这个接口不合乎咱们的需要,就只能本人同时改改了。

通过上面的连贯能够看到 ESP32-CAM 底层的货色一些接口

https://github.com/espressif/...

或者你曾经装置了 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 等函数这么平安,所以无奈应用官网代码中那种通过判断工夫距离管制拍照的办法,只能在利用端管制拍摄频率

总结

这玩意当初只能说勉强能用,因为这玩意很容易过热,继续拍摄一段时间后,信号会逐步不稳固,直到彻底掉线。