Manage cookies

We use cookies to improve our services. Read more about how we use cookies and how you can refuse them.

The necessary cookies help to make the website work properly.

Anonymous statistical cookies help to understand how visitors use the website.

  • M5Stack, MicroPython
    4 min | 23128

    #MicroPython: Support for cameras: M5CAMERA, ESP32-CAM etc.

    M5Stack, MicroPython | 4 min | 23128

    This tutorial updates the article: MicroPython: Taking photos with an ESP32-CAM, in which I described the steps to add support to the ESP32-CAM on MicroPython. In this tutorial, I've updated the driver, and more cameras/boards are now supported. I tested the driver on the ESP32-CAM and the M5CAMERA (model B). It should also work with every board that has an OV2640, and it can be extended to support the OV3660 (I didn't find any board with an ESP32 that uses this camera).

    The main difference is that now the camera pins are configurable from MicroPython. The default mode works for the ESP32-CAM. But, if you have an M5CAMERA, you can change the pins so that the ESP32 connects to the OV2640 and takes photos.

    Software and Hardware

    The following hardware and software will be used in this tutorial:

    Code Example

    You can use the camera driver as follows:

    import camera
    # ESP32-CAM (default configuration) -
    camera.init(0, format=camera.JPEG)  
    # M5Camera (Version B) -
    camera.init(0, d0=32, d1=35, d2=34, d3=5, d4=39, d5=18, d6=36, d7=19, 
                format=camera.JPEG, xclk_freq=camera.XCLK_10MHz,
                href=26, vsync=25, reset=15, sioc=23, siod=22, xclk=27, pclk=21)
    # These parameters: format=camera.JPEG, xclk_freq=camera.XCLK_10MHz are standard for both cameras.
    # You can try using a faster xclk (20MHz), this also worked with the esp32-cam and m5camera 
    # but the image was pixelated and somehow green.
    buf = camera.capture()

    More options were included in this article: MicroPython: OV2640 camera module extended (M5Camera, ESP32-CAM, etc.).

    Some important information:
    • Except when using CIF or lower resolution with JPEG, the driver requires PSRAM to be installed and activated. This is activated, but it is limited because MicroPython needs RAM.
    • Using YUV or RGB puts a lot of strain on the chip because writing to PSRAM is not particularly fast. The result is that image data might be missing. This is particularly true if WiFi is enabled. If you need RGB data, it is recommended that JPEG is captured and then turned into RGB using `fmt2rgb888 or fmt2bmp/frame2bmp`. The conversion is not supported. The formats are included, but almost every time I ran out of memory, trying to capture an image in a different format than JPEG. You can fork the repository and extend that!

    DIY (compiled firmware)

    I've included a compiled MicroPython firmware with support for camera and BLE (check the firmware folder). The firmware was compiled using esp-idf 4.x (hash 4c81978a3).

    To flash it to the board, you need to type the following: --chip esp32 --port /dev/ttyUSB0 erase_flash --chip esp32 --port /dev/ttyUSB0 --baud 460800 write_flash -z 0x1000 micropython_3a9d948_esp32_idf4.x_ble_camera.bin

    More information is available in this tutorial.

    If you want to compile your driver from scratch follow the next section:

    DIY (from Scratch)

    Read this section if you want to include the camera support to MicroPython from scratch. To do that follow these steps:

    1. Clone the MicroPython repository:

      git clone --recursive

      Note: The MicroPython repo changes a lot, I've done this using the version with the hash 3a9d948032e27f690e1fb09084c36bd47b1a75a0.

    2. Copy the files of this repository inside the folder ports/esp32. If you don't want to replace the files mpconfigport.h, main.h, and Makefile make the following modifications to the original ones:

      • mpconfigport.c

        1. add the line

          extern const struct _mp_obj_module_t mp_module_camera;

          in the code block below // extra built in modules to add to the list of known ones (approx. line 184)

        2. add the line:

          { MP_OBJ_NEW_QSTR(MP_QSTR_camera), (mp_obj_t)&mp_module_camera }, \

          in the code block below #define MICROPY_PORT_BUILTIN_MODULES \ (approx. line 194/195)

      • main.c: modify the lines inside the #if CONFIG_ESP32_SPIRAM_SUPPORT || CONFIG_SPIRAM_SUPPORT, they should look like:

            mp_task_heap_size = 2 * 1024 * 1024;
            void *mp_task_heap = malloc(mp_task_heap_size);
            ESP_LOGI("main", "Allocated %dK for micropython heap at %p", mp_task_heap_size/1024, mp_task_heap);
      • Makefile:

        1. add the lines:

          INC_ESPCOMP += -I$(ESPCOMP)/esp32-camera/driver/include
          INC_ESPCOMP += -I$(ESPCOMP)/esp32-camera/driver/private_include
          INC_ESPCOMP += -I$(ESPCOMP)/esp32-camera/conversions/include
          INC_ESPCOMP += -I$(ESPCOMP)/esp32-camera/conversions/private_include
          INC_ESPCOMP += -I$(ESPCOMP)/esp32-camera/sensors/private_include

          inside under the # Compiler and linker flags (approx. line 135)

        2. add the line:

          modcamera.c \

          inside the SRC_C = \ block (approx. line 329 - after the above insertion)

        3. add the lines:

          ESP32_CAM_O = $(patsubst %.c,%.o,\
          $(wildcard $(ESPCOMP)/esp32-camera/driver/*.c) \
          $(wildcard $(ESPCOMP)/esp32-camera/sensors/*.c) \
          $(wildcard $(ESPCOMP)/esp32-camera/conversions/*.c) \

          above the line OBJ_ESPIDF = (approx. line 615 - after the above insertions)

        4. add the line:

          $(eval $(call gen_espidf_lib_rule,esp32_cam,$(ESP32_CAM_O)))

          in the block above ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) (approx. line 655 - after the above insertions)

    3. Clone the repository inside the ~/esp/esp-idf/components folder.

          cd ~/esp/esp-idf/components
          git clone
    4. Compile and deploy MicroPython following the instructions from this tutorial. But, use the following compiling options:

      make BOARD=GENERIC_CAM PYTHON=python3 MICROPY_PY_BTREE=0 -j deploy


    This tutorial explains how to extend the MicroPython firmware to support the OV2640 camera. Different ESP32 board has this camera: ESP32-EYE, ESP32-CAM, and M5Camera. Stay tuned for an example application!


    Francesco 06.26.2020

    Hi, great job. I would like to compile micropython with PPP support, is it possible?

    Mauricio Martinez 10.13.2020

    Hello, Great job! I'm using the firmware of this tutorial and until now everything is working well. I have a question, what if I want to configure the camera as a "manual mode" for example: time exposure or shuter speed, ISO, etc. Thank you

    Mathias 12.22.2020

    Hello, thank you for this great tutorial. I've followed the tutorial and was able to create the firmware.bin. Once I program the board it keeps rebooting with a Guru Meditation Error: Core 0 panic'ed (StoreProhibited) error (from what I've understand its is trying to access an invalid memory. I make sure I was using the proper hash for the IDF package as the one in the Micropython/ports/esp32/Makefile. all compilation are successful without errors. Did I miss something? Thank you.

    Cef 06.10.2021

    Hi, how do you add support for ov3660

    Himakar Bavikaty 08.27.2021

    Thanks for the tutorial, I cloned git repository. I am unable to update Makefile because it contains 53 lines of code. You advised to update code at 135,329,615 lines. Can you please advice how to proceed further.

    Harry Martin 10.15.2021

    In case you didn't realize, the word "lastest" on your site is spelled incorrectly. I had similar issues on my website which hurt my credibility until someone pointed it out and I discovered some of the services like or which help with these type of issues.

    Erkman 01.13.2022

    Hi, I'm using your micropython version (latest), everything seems to be working, but... after approx 100-150 picture, camera.deint() runs on error: cannot deint camera. What helps: only cold reset the device (pull usb cable or make a deepsleep for 1 sec)

    Do you have a fix for this? it seems to do with the driver...