{
    "key": "esp32-cam",
    "kind": "board",
    "source": "authored",
    "status": "draft",
    "harness": {
        "gpio": {
            "notes": "Almost every pin is routable to almost any peripheral through the GPIO matrix, so a driver binds to a pin number chosen at deploy time rather than to a fixed function. The strapping pins and the pins bonded to on-package flash are the exceptions and must not be used.",
            "library": "machine",
            "pin_scheme": "gpio"
        },
        "flash": {
            "baud": 115200,
            "tool": "esptool.py",
            "notes": "There is no USB connector on the board. Flashing needs an external USB to TTL adapter wired to U0R and U0T, with GPIO0 shorted to ground to enter the bootloader and the short removed before running. Powering it from a 3.3V adapter pin browns out during Wi-Fi transmit; use 5V. This is the single most common reason an ESP32-CAM appears dead.",
            "method": "usb-serial",
            "port_hint": "/dev/ttyUSB0"
        },
        "probe": {
            "commands": [
                "import sys; print(sys.implementation)",
                "import os; print(os.uname())",
                "import machine; print(machine.freq())",
                "import gc; gc.collect(); print(gc.mem_free())",
                "from machine import I2C, Pin; print(I2C(0).scan())"
            ],
            "model_file": null,
            "overlay_file": null
        },
        "runtime": {
            "python3": true,
            "os_family": null,
            "package_manager": "mip",
            "service_manager": null
        },
        "verified": {
            "by": null,
            "os": null,
            "date": null,
            "reviewed_by": null,
            "evidence_url": null
        },
        "transport": {
            "ota": true,
            "tls": true,
            "notes": "Connects to the broker directly over Wi-Fi. TLS works but the handshake is the largest memory spike in a typical device program, so size the heap around it rather than around steady state.",
            "network": [
                "wifi",
                "bluetooth"
            ],
            "mqtt_client": "umqtt.simple"
        },
        "toolchains": [
            "MicroPython",
            "ESP-IDF",
            "Arduino IDE",
            "Arduino CLI",
            "PlatformIO"
        ],
        "local_inference": {
            "llm": {
                "notes": "Kilobytes of RAM. A general language model does not run here and never will. Send the reading to something that can.",
                "viable": false,
                "runtimes": [],
                "max_params_b": null,
                "quantisation": [],
                "max_model_size_gb": null
            },
            "notes": "Most of the GPIO is consumed by the camera and the SD card. Count the free pins against the driver's requirements before committing to this board.",
            "tinyml": {
                "notes": "4MB PSRAM holds a camera frame buffer, which is what makes vision possible at all on an original ESP32.",
                "viable": true,
                "frameworks": [
                    "ESP-DL",
                    "TensorFlow Lite Micro",
                    "Edge Impulse"
                ]
            },
            "viable": true,
            "accelerator": null,
            "usable_memory_gb": null
        },
        "provisioning_model": "micropython",
        "component_attachment": "gpio-header",
        "supported_provisioning_models": [
            "micropython",
            "arduino-sketch",
            "vendor-firmware"
        ]
    },
    "platform": {
        "cpu": "Xtensa dual-core LX6 @ 240MHz",
        "ram": "520KB SRAM plus 4MB PSRAM",
        "name": "ESP32-CAM",
        "power": [
            {
                "source": "USB",
                "voltage_max": 5,
                "voltage_min": 5
            },
            {
                "source": "5V pin",
                "voltage_max": 5,
                "voltage_min": 5
            },
            {
                "source": "3V3 pin",
                "voltage_max": 3.3,
                "voltage_min": 3.3
            }
        ],
        "has_gpu": false,
        "has_npu": false,
        "has_tpu": false,
        "storage": "4MB Flash",
        "weight_g": null,
        "gpio_pins": 9,
        "board_type": "Microcontroller",
        "interfaces": [
            {
                "type": "OV2640 camera",
                "count": 1
            },
            {
                "type": "microSD",
                "count": 1
            },
            {
                "type": "2.54mm header",
                "count": 2
            }
        ],
        "description": "ESP32 with an OV2640 2MP camera and a microSD slot on a module the size of a postage stamp. Cheap, ubiquitous and awkward to flash.",
        "adc_channels": 4,
        "dac_channels": 0,
        "manufacturer": "AI-Thinker",
        "model_number": "ESP32-CAM",
        "pwm_channels": 16,
        "datasheet_url": null,
        "dimensions_mm": null,
        "serial_protocols": [
            {
                "count": 1,
                "protocol": "I2C"
            },
            {
                "count": 1,
                "protocol": "SPI"
            },
            {
                "count": 2,
                "protocol": "UART"
            }
        ],
        "operating_systems": [
            {
                "name": "ESP-IDF"
            },
            {
                "name": "Arduino Core"
            },
            {
                "name": "MicroPython"
            }
        ],
        "operating_voltage": "3.3V",
        "communication_chips": [
            {
                "protocol": "Wi-Fi",
                "standard": "802.11b/g/n",
                "chip_model": "ESP32-S"
            },
            {
                "protocol": "Bluetooth",
                "standard": "4.2 BR/EDR and BLE",
                "chip_model": "ESP32-S"
            }
        ]
    },
    "revision": 1
}