简单试用安信可ESP32-CAM摄像头开发板
本文旨在试用ESP32-CAM模块,并没有搞开发。有时候有的需求需要涉及到使用摄像头,当然你可以用专业的摄像头,然后使用协议来控制,对于简单的应用来说成本高了不少。
说是可以连接摄像头,自己画个板子,打个样,似乎太费时间了,ESP32-CAM就是很好的选择来着,简单到我本文都没啥好写的了,全程低能。
用这个开发板,使用Arduino IDE可以很快的实现一些简单的功能。因为板载了摄像头模块,micro SD卡座,LED补光灯(闪光灯),几个基本的联动功能很容易实现。比如有人经过,通过人体传感器触发,就自动拍照保存到内存卡,或者上传到服务器。并且就东西本身来说,集成度越高,价格就越便宜。
安装步骤人家已经写了,我就不怎么写了:项目(二) esp32-cam 网页图像人脸
如果使用过ESP8266,使用这个模块几乎就没啥不同。下面是官方文档里面介绍的一些特性,我当然是赞同的,因为基于ESP32的,那当然有ESP32的所有优点了。
- 采用低功耗双核32位CPU,可作应用处理器
- 主频高达240MHz,运算能力高达 600 DMIPS
- 内置 520 KB SRAM,外置8MB PSRAM
- 支持UART/SPI/I2C/PWM/ADC/DAC等接口
- 支持OV2640和OV7670摄像头,内置闪光灯
- 支持图片WiFI上传
- 支持TF卡
- 支持多种休眠模式。
- 内嵌Lwip和FreeRTOS
- 支持 STA/AP/STA+AP 工作模式
- 支持 Smart Config/AirKiss 一键配网
- 支持二次开发
在本文之前,我们已经玩过了多块了乐鑫的开发板,ESP8266和ESP32,有兴趣的可以看看:
基于Blinker的ESP8266+CC2541蓝牙接入以及其他
(暂未实践)分析使用ESP32将有线键盘转换为蓝牙无线键盘
ESP8266使用MQTT连接阿里云物联网平台(官方NONOS_SDK和Arduino_IDE )
使用ESP8266自制廉价Gokit SOC方案
完整的官方介绍页:
ESP32-CAM是安信可最新发布小尺寸的摄像头模组。该模块可以作为最小系统独立工作,尺寸仅为2740.54.5mm,深度睡眠电流最低达到6mA。 ESP32-CAM可广泛应用于各种物联网场合,适用于家庭智能设备、工业无线控制、无线监控、QR无线识别,无线定位系统信号以及其它物联网应用,是物联网应用的理想解决方案。
ESP32-CAM采用DIP封装,直接插上底板即可使用,实现产品的快速生产,为客户提供高可靠性的连接方式,方便应用于各种物联网硬件终端场合。
体积超小的802.11b/g/n Wi-Fi + BT/BLE SoC模块
引脚定义
最小系统图
功耗:
我自己测试也是得到的这个数据。
- 关闭闪光灯:180mA@5V
- 开启闪光灯并且亮度调到最大:310mA@5V
- Deep-sleep:最低功耗可以达到 6mA@5V
- Moderm-sleep:最低可达到 20mA@5V
- Light-sleep:最低可达到 6.7mA@5V
实物图:
烧录
当然要加入ESP32的官方源,并在开发板中找到安信可的ESP32-CAM。
使用例程CameraWebServer,就是官方自带的相机例子,也带有人脸识别功能。
在写入模块以前,要把宏定义修改一下,切换为ai-thinker,也就是安信可的那一项,不然会提示不支持。
同时修改要连接的Wi-Fi网络。
const char* ssid = "*********";
const char* password = "*********";
就这样就算是配置完成了。在烧录的时候要注意,要将开发板中的GPIO0连接到GND,烧录完毕后去掉连接。其他的RX,TX连接就不多说了。
测试
前面的操作一切正常以后,就可以开始试用了。串口会输出连接到的局域网IP地址,你也可以查看路由器分配的多少。
进入网页就是下面的样子。
当然可以更改视频的尺寸。
在串口端会有如下输出。
拍照并保存到内存卡
上面的Arduino自带的例子,对于视频流的暂停,只是网页上的暂停,也不能保存到内存卡,所以要实现摄像头的内容保存到内存卡,还需要自己捣鼓一下,下面提供了一个现成的Demo,可以供参考。
ESP32-CAM Take Photo and Save to MicroSD Card
这个案例实现的是模块上电拍照,保存到内存卡,然后深度休眠。
我直接把代码照搬过来了。
/*********
Rui Santos
Complete project details at https://RandomNerdTutorials.com/esp32-cam-take-photo-save-microsd-card
IMPORTANT!!!
- Select Board "AI Thinker ESP32-CAM"
- GPIO 0 must be connected to GND to upload a sketch
- After connecting GPIO 0 to GND, press the ESP32-CAM on-board RESET button to put your board in flashing mode
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
*********/
#include "esp_camera.h"
#include "Arduino.h"
#include "FS.h" // SD Card ESP32
#include "SD_MMC.h" // SD Card ESP32
#include "soc/soc.h" // Disable brownour problems
#include "soc/rtc_cntl_reg.h" // Disable brownour problems
#include "driver/rtc_io.h"
#include <EEPROM.h> // read and write from flash memory
// define the number of bytes you want to access
#define EEPROM_SIZE 1
// Pin definition for 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
int pictureNumber = 0;
void setup() {
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); //disable brownout detector
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_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(psramFound()){
config.frame_size = FRAMESIZE_UXGA; // FRAMESIZE_ + QVGA|CIF|VGA|SVGA|XGA|SXGA|UXGA
config.jpeg_quality = 10;
config.fb_count = 2;
} else {
config.frame_size = FRAMESIZE_SVGA;
config.jpeg_quality = 12;
config.fb_count = 1;
}
// Init Camera
esp_err_t err = esp_camera_init(&config);
if (err != ESP_OK) {
Serial.printf("Camera init failed with error 0x%x", err);
return;
}
//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;
}
camera_fb_t * fb = NULL;
// Take Picture with Camera
fb = esp_camera_fb_get();
if(!fb) {
Serial.println("Camera capture failed");
return;
}
// initialize EEPROM with predefined size
EEPROM.begin(EEPROM_SIZE);
pictureNumber = EEPROM.read(0) + 1;
// Path where new picture will be saved in SD Card
String path = "/picture" + String(pictureNumber) +".jpg";
fs::FS &fs = SD_MMC;
Serial.printf("Picture file name: %s\n", path.c_str());
File file = fs.open(path.c_str(), FILE_WRITE);
if(!file){
Serial.println("Failed to open file in writing mode");
}
else {
file.write(fb->buf, fb->len); // payload (image), payload length
Serial.printf("Saved file to path: %s\n", path.c_str());
EEPROM.write(0, pictureNumber);
EEPROM.commit();
}
file.close();
esp_camera_fb_return(fb);
// Turns off the ESP32-CAM white on-board LED (flash) connected to GPIO 4
pinMode(4, OUTPUT);
digitalWrite(4, LOW);
rtc_gpio_hold_en(GPIO_NUM_4);
delay(2000);
Serial.println("Going to sleep now");
delay(2000);
esp_deep_sleep_start();
Serial.println("This will never be printed");
}
void loop() {
}
此处代码最后的休眠是写的esp_deep_sleep_start();
,直接休眠不再启动了,除非再次复位。如果需要GPIO唤醒,则写:
esp_sleep_enable_ext0_wakeup(GPIO_NUM_13, 0);
Serial.println("Going to sleep now");
delay(1000);
esp_deep_sleep_start();
Serial.println("This will never be printed");
使用GPIO13来唤醒(因为ESP32的IO本来就不多,又有内存卡又有摄像头已经占用了很多了),不过设置为的是低电平唤醒,那就得加个三极管处理一下。
摄像头发紫或仅显示一部分
如果拍照出来的图片是摄像头发紫或仅显示一部分,就降低画质。
代码中有判断psramFound
,存在的话,是一个设置,不存在是另外个画质。根据实际情况降低就行了。
if (psramFound()) {
Serial.println("psramFound!");
config.frame_size = FRAMESIZE_SVGA; // FRAMESIZE_ + QVGA|CIF|VGA|SVGA|XGA|SXGA|UXGA
config.jpeg_quality = 5;
config.fb_count = 2;
} else {
Serial.println("psramNotFound!");
config.frame_size = FRAMESIZE_SVGA;
config.jpeg_quality = 12;
config.fb_count = 1;
}
具体就是调节frame_size
和jpeg_quality
,适当调低就行了。
本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。
请问我运行CameraWebServer示例时报错找不到"fd_forward.h"和"fr_forward.h"文件,该怎么办呀?
报错如下
Alternatives for fd_forward.h: []app_httpd.cpp:22:24: fatal error: fd_forward.h: No such file or directory
打开这个示例的时候,会同时打开这几个头文件的,保持文件存在就行
请问这个摄像头最近拍摄距离能达到10CM吗?
我使用的是附带的这个摄像头OV2640,10厘米的距离太近基本上是模糊的。