Overview
The Kuongshun ESP32-CAM is a compact ESP32 development board with a 2 MP OV3660 camera, an onboard high-power LED flash, a microSD slot, and exposed pins for everything else. It's the cheapest possible WiFi-enabled IP camera platform — perfect for surveillance projects, doorbell cameras, machine vision robots, and any "just stream me video over WiFi" use case.
This board is the larger Kuongshun variant — instead of the AI-Thinker's tiny PCB, it gives you a full set of breakout pins (GPIO 12, 13, 14, 15, 16) accessible from the side, an onboard USB-to-serial chip (RXD/TXD broken out), and a more reliable power circuit. The OV3660 sensor delivers up to 2048×1536 (3 MP) stills and 720p video over WiFi, with built-in JPEG encoding so you don't burn CPU on compression.
At a Glance
Specifications
| Parameter | Value |
| Microcontroller | ESP32 (Tensilica LX6 dual-core, 240 MHz) |
| Flash / PSRAM | 4 MB / 4 MB |
| Camera Sensor | OmniVision OV3660 (CMOS, 3 MP) |
| Maximum Resolution | 2048 × 1536 (3 MP) |
| Video | 720p / 480p / 240p MJPEG over WiFi |
| JPEG Encoding | Hardware-accelerated |
| Storage | microSD card (up to 32 GB FAT32 / exFAT) |
| WiFi | 802.11 b/g/n (2.4 GHz) |
| Bluetooth | Classic + BLE |
| Power | 5V via USB or Vin pin (3.3V available too) |
| Onboard LED | High-brightness white flash + status LED |
| Logic Level | 3.3V |
| Programming | Onboard CP2102 USB-to-serial (no FTDI needed) |
Pinout Diagram
Wiring Guide
Programming via USB
Unlike the bare AI-Thinker ESP32-CAM, the Kuongshun variant has an onboard CP2102 USB-to-serial chip — just plug in USB and upload. No FTDI adapter, no boot-mode jumper required.
| Connection | Detail |
|---|---|
| USB | Standard USB-C cable |
| Port (Arduino IDE) | Auto-detected as CP2102 device |
| Board (Arduino IDE) | "AI Thinker ESP32-CAM" or "ESP32 Wrover Module" |
| Upload speed | 460800 (default) |
Onboard Flash LED
The bright white flash LED is on GPIO 4. It's a high-brightness LED designed for camera flash use — but you can also use it as a generic high-power output.
| Function | GPIO |
|---|---|
| Flash LED | GPIO 4 (HIGH = on) |
| Status LED (red) | GPIO 33 (active LOW) |
Available External GPIOs
Most ESP32 GPIOs are consumed by the camera and SD card. The Kuongshun board breaks out the few that remain free:
| GPIO | Notes |
|---|---|
| GPIO 1 (TX) | Free if not using serial |
| GPIO 3 (RX) | Free if not using serial |
| GPIO 12 | Free, but boot strapping pin (must be LOW at reset) |
| GPIO 13 | Free, also SD_DATA3 if SD used |
| GPIO 14 | Free, also SD_CLK if SD used |
| GPIO 15 | Free, also SD_CMD if SD used |
| GPIO 16 | Free, useable as I2C/sensor input |
| GPIO 2 | Free, also SD_DATA0 |
Using the microSD Slot
Format your card as FAT32 (or exFAT for > 32 GB cards). The ESP32 talks to the SD card via 1-line or 4-line SDMMC. Using the SD card consumes GPIOs 2, 4, 12, 13, 14, 15.
Code Examples
Arduino — CameraWebServer Example
// Easiest way to get a live web stream:
//
// 1. Tools -> Board -> AI Thinker ESP32-CAM
// 2. File -> Examples -> ESP32 -> Camera -> CameraWebServer
// 3. Edit ssid / password near the top of the sketch
// 4. Find the line "#define CAMERA_MODEL_AI_THINKER" and leave it uncommented
// 5. Upload (hold BOOT button if upload errors)
// 6. Open Serial Monitor at 115200 baud, reset the board
// 7. It prints an IP address - open it in your browser
// 8. Click "Start Stream" - live video appears!
Arduino — Capture and Save to SD Card
// Capture a JPEG and write it to the SD card
#include "esp_camera.h"
#include "FS.h"
#include "SD_MMC.h"
// AI Thinker / Kuongshun pin map
#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
void setup() {
Serial.begin(115200);
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.pixel_format = PIXFORMAT_JPEG;
config.frame_size = FRAMESIZE_UXGA;
config.jpeg_quality = 10;
config.fb_count = 1;
esp_camera_init(&config);
SD_MMC.begin();
camera_fb_t *fb = esp_camera_fb_get();
File f = SD_MMC.open("/photo.jpg", FILE_WRITE);
f.write(fb->buf, fb->len);
f.close();
esp_camera_fb_return(fb);
Serial.println("Saved /photo.jpg");
}
void loop() {}
MicroPython — Stream WebSocket
# MicroPython on ESP32-CAM
# Flash with the camera-enabled firmware from
# https://github.com/lemariva/micropython-camera-driver
# Then run this snippet:
import camera, network, time
camera.init(0, format=camera.JPEG, framesize=camera.FRAME_HD)
wlan = network.WLAN(network.STA_IF); wlan.active(True)
wlan.connect("SSID", "PASS")
while not wlan.isconnected(): time.sleep(0.5)
print("IP:", wlan.ifconfig()[0])
while True:
buf = camera.capture()
print(f"Captured {len(buf)} bytes")
time.sleep(2)