작년에 충동 구매한 부품들을 뒤적이다가 카메라 모듈을 찾게 되어서, 정리차원에서 간단 사용기를 적는다.
홈서버로 사용하는 라즈베리파이에 카메라를 연결하여 사용하려고도 해봤는데, 아두이노를 이용해서도 아주 간단하게 카메라를 사용한다. 동영상까지는 얼마나 잘 작동할지 모르겠지만... WIFI카메라를 만들어보자.
아래에 설명하게 되는 카메라 모듈은 ESP32를 같이 장착하고 있는 모듈로, 전원만 공급하면 WIFI카메라 역할을 하게 된다. MicroSD카드 슬롯도 장착되어있어서, 필요한 것은 저장할 수 있는 기능도 있다.
안테나 까지 포함해서 가격이 5달러를 조금 넘을 뿐이다. 세상 정말 좋아진것 같다. 중국이 있어서 행복해요 라는 말이 헛소리는 아닌 것 같다.
한번의 광고 클릭이 저에게 도움을 줍니다. 감사합니다.
필요부품
이 모듈도 다양한 곳에서 살수 있지만, 알리 익스프레스에서 간단히 조회를 하니, 안테나까지 포함된 것으로 배송비도 없이 싸게 판매를 하고있다.
- https://www.aliexpress.com/item/33027303390.html
- 제품 스펙은 이렇다고 한다. 쇼핑몰에 안내되어있는 글을 구글번역하여 붙여넣기 하였다. 카메라는 200M화소를 지원한다.
[ESP32-CAM]
모델 : ESP32-CAM
작동 전압 : 5V
SPI 플래시 : 32Mbit
RAM : Inter 520KB +, 외부 4M PSRAM
블루투스 : BLuetooth 4.2 BR / EDR & BLE 표준
와이파이 : 802.11 / b / g / n / e / i
포트 : UART, SPI, I2C, PWM
IO 포트 : 9
직렬 포트 속도 : 115200bps
사진 형식 : JPEG (OV2640 만 지원), BMP, GRAYSCALE
스펙트럼 범위 : 2412-2484MHz
Antanna : 온보드 PCB Antanna 2dBi
보안 : WPA / WPA2 / WPA2-Enterprise / WPS
작용 온도 : -20 -85 ℃
보관 온도 : -40 -90 ℃, <90 % RH
송신 전력 :
802.11b : 17 +/- 2dBm (@ 11Mbps)
802.11g : 14 +/- 2dBm (@ 54Mbps)
802.11n : 13 +/- 2dBm (@ MSC7)
안테나 감도
CCK, 1Mbps : -90dBm
CCK, 11Mbps : -85dBm
6Mbps (1/2 BPSK) : -88dBm
54Mbps (3/4 64-QAM) : -70dBm
MCS7 (65Mbps, 72.2Mbps) : -67dBm
[ESP32-S]
메인 칩은 최대 240MHz의 주파수와 최대 600DMIPS의 컴퓨팅 성능을 가진 저전력 듀얼 코어 32 비트 CPU를 사용합니다.
기본 32Mbit SPI 플래시, 520KB SRAM
SoftAP 및 스테이션 모드 지원
초소형 802.11b / g / n Wi-Fi + BT / BLE SoC 모듈
UART / SPI / I2C / I2S / PWM / ADC / DAC 등 지원
펌웨어 업그레이드 지원 (FOTA)
안테나는 온보드 안테나 또는 IPEX 블록 출력을 지원합니다
[OV2640 카메라 모듈]
특색:
OV2640 이미지 센서는 2 메가 픽셀 (1632x1232 픽셀)
작은 크기, 낮은 작동 전압 및 단일 칩 UXGA 카메라 및 이미지 프로세서의 모든 기능을 제공합니다.
SCCB 컨트롤을 통해 전체 프레임을 출력하고 서브 샘플링을 수행하며 창을 열고 다양한 해상도 10 비트 샘플링 데이터를 얻을 수 있습니다.
제품 UXGA는 초당 최대 15 프레임을 이미지화합니다.
사용자는 이미지 품질, 데이터 형식 및 전송 모드를 완전히 제어 할 수 있습니다.
사양:
저조도 애플리케이션을위한 고감도
임베디드 애플리케이션을위한 저전압
I2C 인터페이스와 호환되는 표준 SCCB 인터페이스
RawRGB, RGB (GRB4 : 2 : 2, RGB565 / 555 / 444), YUV (4 : 2 : 2) 및 YCbCr (4 : 2 : 2) 출력 형식
UXGA, SXGA, VGA, QVGA, QQVGA, CIF, QCIF 및 최대 40x30 크기 지원
Vario Pixel 하위 샘플링 모드 지원
자동 충격 제어 기능에는 자동 노출 제어, 자동 게인 제어, 자동 화이트 밸런스, 자동 줄 제거, 블랙 레벨 자동 교정이 포함됩니다. 채도, 색조, 감마, 선명도를 포함한 이미지 품질 관리 ANTI_BLOOM
노이즈 캔슬링 및 데드 픽셀 보상 기능이있는 ISP
이미지 스케일링 지원
렌즈 손실 보정
채도 자동 조정
가장자리 향상 자동 조정
노이즈 감소 자동 조정
감지 배열 1632 x 1232
최대 형식 UXGA IO
전압 1.7V -3.3V
아날로그 전압 2.5 -3.0V (내부 LDO-전원 공급 장치 1.2V)
소비 전력 TBD 절전 <20uA
온도 작동 -30 -70 ℃
섭씨 0 ~ 50 도의 안정적인 작업
출력 형식 (8 비트)
YUV / YCbCr4 : 2 : 2 RGB565 / 555 / 444
GRB4 : 2 : 2 원시 RGB 데이터
광학 크기 1/4 "
시야각 25 °
최대 속도 15fps
SXGA 감도 1.3V / (Lux-sec)
신호 대 잡음비 40dB
다이나믹 레인지 50 dB
뷰 모드 프로그레시브 전자 노출 1 라인 ~ 1247 라인
픽셀 영역 2.2 um x 2.2 um
60 ℃에서 암전류 15mV / s
스펙에는 무엇인지 모르겠지만, 많은 것들이 적혀있다. 내가 이해를 한 것은 200M픽셀의 카메라가 설치되어있다. 15프레임을 지원한다. ESP32모듈은 BLE도 지원한다. 수준으로만 주요한 것을 뽑아봤다.
ESP32-S 모듈 PIN정보
환경설정(개발)
아두이노의 개발 환경을 설정하자. 기본적인 아두이노에는 이 보드를 지원하지 못하기 때문에, 새로운 보드 정보를 등록해야 한다. 등록 방법은 다음과 같다.
아두이노를 실행한 후, 환경설정 메뉴를 선택하여 나타난 아래 화면에서 추가적인 보드 매니저 URLs로 표시된 맨 오른쪽의 1번 아이콘을 선택한다. 내 경우에는 기존에 ESP8266 보드를 추가하여 사용하였기에, 이 주소가 추가되어있는데, 이것은 사용자에 따라서 없을 수도 있고 다르다.
그런 후에, 아래 그림과 같이 URL을 추가한다. ( https://dl.espressif.com/dl/package_esp32_index.json )
그 다음은 아두이노 메뉴(툴 -> 보드 -> 보드매니저)를 선택한 후, "esp32"로 보드를 검색하여 설치하도록 한다. 설치할 파일을 다운로드 할 때 꽤 시간이 오래 걸린다.
위의 ESP32 보드가 설치가 된 되에 아래와 같이 메뉴를 선택하면, 수많은 ESP32 보드가 설치된 것을 확인할 수 있다. 너무 많아서 놀랐다. 언젠가 이 모든 보드를 사용해볼 수 있을까... 이것을 사용해야 지만 하나? 등 다양한 생각이 든다. 엄청 많은 보드가 있나 보다. 그중에 눈에 띄는 TTGO보드가 있다. 얼마전에 알리에서 본 모양이 깔끔한 보드였던 것으로 기억한다.
보드를 ESP32 Wrover Module로 설정한다. 포트는 나중에 FTDI 모듈을 연결했을 때 COM포트 인식되면 그것을 선택한다.
예제
예제를 선택해보자. 아래와 같이 등록되어 있는 예제를 선택한다. 맥에서 설치했을 때 예제가 안보여서 아두이노를 종료했다가 재실행하니, 정상적으로 표시가 되었다.
Camera 메뉴에 있는 "Camera Web Server" 예제를 선택하였다.
#include "esp_camera.h" #include <WiFi.h> // // WARNING!!! Make sure that you have either selected ESP32 Wrover Module, // or another board which has PSRAM enabled // // Select camera model #define CAMERA_MODEL_WROVER_KIT //#define CAMERA_MODEL_ESP_EYE //#define CAMERA_MODEL_M5STACK_PSRAM //#define CAMERA_MODEL_M5STACK_WIDE //#define CAMERA_MODEL_AI_THINKER #include "camera_pins.h" const char* ssid = "*********"; // WIFI SID 이름을 입력한다. const char* password = "*********"; // WIFI 비밀번호를 입력한다. void startCameraServer(); 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_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; //init with high specs to pre-allocate larger buffers if(psramFound()){ config.frame_size = FRAMESIZE_UXGA; config.jpeg_quality = 10; config.fb_count = 2; } else { config.frame_size = FRAMESIZE_SVGA; config.jpeg_quality = 12; config.fb_count = 1; } #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 blightness just a bit s->set_saturation(s, -2);//lower the saturation } //drop down frame size for higher initial frame rate s->set_framesize(s, FRAMESIZE_QVGA); #if defined(CAMERA_MODEL_M5STACK_WIDE) s->set_vflip(s, 1); s->set_hmirror(s, 1); #endif WiFi.begin(ssid, password); 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() { // put your main code here, to run repeatedly: delay(10000); }
컴파일
보드를 "ESP32 Wrover Module"을 선택하고, 아두이노 IDE화면의 맨 왼쪽의 Check모양의 버튼인 컴파일을 해보자. 컴파일이 완료되면 이상없지만, 내 경우에는 "스케치가 너무 크다"는 메시지 "Sketch is too big" 메시지가 출력되고 컴파일 오류가 난다.
이것을 해결하기 위한 방법은 "툴 --> Partition Scheme"를 "Huge APP..."을 선택한 후 컴파일을 하면 오류없이 완료된다.
업로드
FTDI 모듈을 아래 그림과 같이 연결한다. 아래 그림과 같이 U0R은 FTDI의 TX로, U0T 는 FTDI의 RX로 연결한다.
그리고, 코드 업로드를 위해서, ESP32-S의 IO0(GPIO 0) 를 GND에 연결한다.
아두이노의 업로드 버튼을 누른다. 컴파일이 된 후에, 아래와 같이 나온 후, 업로드가 진행된다.
스케치는 프로그램 저장 공간 2100647 바이트(66%)를 사용. 최대 3145728 바이트. 전역 변수는 동적 메모리 53544바이트(16%)를 사용, 274136바이트의 지역변수가 남음. 최대는 327680 바이트. esptool.py v2.6 Serial port /dev/cu.usbserial-A700f65C Connecting........_____....._____....._____....._____....._____..
아래의 코드가 나오면서 업로드가 완료된다.
Writing at 0x0019c000... (98 %) Writing at 0x001a0000... (99 %) Writing at 0x001a4000... (100 %) Wrote 2100768 bytes (1661725 compressed) at 0x00010000 in 74.6 seconds (effective 225.3 kbit/s)... Hash of data verified. Compressed 3072 bytes to 119... Writing at 0x00008000... (100 %) Wrote 3072 bytes (119 compressed) at 0x00008000 in 0.0 seconds (effective 1555.3 kbit/s)... Hash of data verified. Leaving... Hard resetting via RTS pin...
ESP32-S의 IO0과 GND를 연결한 Jumper를 제거한다. 그 후 아두이노의 시리얼 디버깅 창을 열고 전송속도를 115200 으로 설정한 후, ESP32-S의 RESET버튼을 누른다. 다음과 같은 화면이 나오는데, 하드웨어 리셋이 된 후에 WIFI접속(AP설정한)하고 카메라가 준비되었다는 메시지가 나타난다.
이제 정상적으로 작동되는 것 같으니, 휴대폰으로 위의 카메라 주소로 접속해보자. 최초 접속한 화면에서 Resolution을 변경하고, 맨 아래에 있는 Start Steam을 선택한다.
카메라 촬영이 되고 있는 것을 보려면, 선택한 메뉴 아래에 동영상이 출력되고 있다. 또한, 위 화면의 왼쪽 상단에 있는 3선의 줄로된 메뉴를 선택해도 된다.
디버그 창에 출력되는 정보를 보니, 10프레임 이상 나오지 않는 것 같다. 그렇지만, 여기에 히스토그램을 이용하여 이미지 변화를 탐지하여 방법용으로 사용할 수 있을 것 같다. Enroll Face라는 메뉴는 무엇인지도 좀 찾아봐야 겠다.
MJPG: 87462B 327ms (3.1fps), AVG: 237ms (4.2fps), 0+0+0+0=0 0 MJPG: 87086B 150ms (6.7fps), AVG: 234ms (4.3fps), 0+0+0+0=0 0 MJPG: 87066B 322ms (3.1fps), AVG: 237ms (4.2fps), 0+0+0+0=0 0 MJPG: 87279B 133ms (7.5fps), AVG: 236ms (4.2fps), 0+0+0+0=0 0 MJPG: 87522B 337ms (3.0fps), AVG: 238ms (4.2fps), 0+0+0+0=0 0 MJPG: 87701B 155ms (6.5fps), AVG: 238ms (4.2fps), 0+0+0+0=0 0 MJPG: 87556B 159ms (6.3fps), AVG: 230ms (4.3fps), 0+0+0+0=0 0 MJPG: 87693B 226ms (4.4fps), AVG: 234ms (4.3fps), 0+0+0+0=0 0 MJPG: 87713B 154ms (6.5fps), AVG: 224ms (4.5fps), 0+0+0+0=0 0 MJPG: 87793B 339ms (2.9fps), AVG: 232ms (4.3fps), 0+0+0+0=0 0 MJPG: 87754B 159ms (6.3fps), AVG: 225ms (4.4fps), 0+0+0+0=0 0 MJPG: 87963B 297ms (3.4fps), AVG: 232ms (4.3fps), 0+0+0+0=0 0 MJPG: 87985B 203ms (4.9fps), AVG: 226ms (4.4fps), 0+0+0+0=0 0 MJPG: 87525B 443ms (2.3fps), AVG: 240ms (4.2fps), 0+0+0+0=0 0 MJPG: 86480B 165ms (6.1fps), AVG: 233ms (4.3fps), 0+0+0+0=0 0 MJPG: 87762B 323ms (3.1fps), AVG: 242ms (4.1fps), 0+0+0+0=0 0 MJPG: 87107B 194ms (5.2fps), AVG: 235ms (4.3fps), 0+0+0+0=0 0 MJPG: 87802B 228ms (4.4fps), AVG: 238ms (4.2fps), 0+0+0+0=0 0 MJPG: 87437B 216ms (4.6fps), AVG: 234ms (4.3fps), 0+0+0+0=0 0 MJPG: 88145B 275ms (3.6fps), AVG: 240ms (4.2fps), 0+0+0+0=0 0 MJPG: 88106B 190ms (5.3fps), AVG: 233ms (4.3fps), 0+0+0+0=0 0 MJPG: 87836B 302ms (3.3fps), AVG: 241ms (4.1fps), 0+0+0+0=0 0 MJPG: 87984B 170ms (5.9fps), AVG: 233ms (4.3fps), 0+0+0+0=0 0 MJPG: 87555B 292ms (3.4fps), AVG: 241ms (4.1fps), 0+0+0+0=0 0
Troubleshooting 정보는 아래의 사이트에서 찾을 수 있다.
www.randomnerdtutorials.com/esp32-cam-troubleshooting-guide/
'아두이노 > 아두이노 일반' 카테고리의 다른 글
(작성중) PMS-7003 (0) | 2020.05.18 |
---|---|
[아두이노] TMP36 으로 온도계 만들기 (0) | 2020.05.11 |
서보모터를 이용한 카메라 움직이기 (0) | 2020.05.10 |
서보모터(MG90S) 사용 (0) | 2020.05.10 |
구글 크롬 T-REX Runner 게임 자동으로 아두이노 (0) | 2020.04.10 |