From 70a68f04c5aed2e9179c6228833177050743683c Mon Sep 17 00:00:00 2001 From: Christopher Nadler <147471517+cnadler86@users.noreply.github.com> Date: Thu, 22 May 2025 06:53:33 +0200 Subject: [PATCH 1/9] general-issue.md aktualisieren --- .github/ISSUE_TEMPLATE/general-issue.md | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/ISSUE_TEMPLATE/general-issue.md b/.github/ISSUE_TEMPLATE/general-issue.md index 5460346..3e6d63d 100644 --- a/.github/ISSUE_TEMPLATE/general-issue.md +++ b/.github/ISSUE_TEMPLATE/general-issue.md @@ -8,3 +8,4 @@ assignees: '' --- PLEASE, read the documentation, search [previous issues](https://github.com/cnadler86/micropython-camera-API/issues?q=is%3Aissue) and/or ask ChatGPT before! +Also disconnect any peripherals to the board and try without them before raising an issue. From 91af395f9ca061bdd390e36e886dff762057f4d6 Mon Sep 17 00:00:00 2001 From: Christopher Nadler <147471517+cnadler86@users.noreply.github.com> Date: Thu, 22 May 2025 06:54:55 +0200 Subject: [PATCH 2/9] bug_report.md aktualisieren --- .github/ISSUE_TEMPLATE/bug_report.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index d612a9d..cf131bf 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -22,3 +22,5 @@ A clear and concise description of what you expected to happen. **Additional context** Add any other context about the problem here. + +Note: Also disconnect any peripherals to the board and try without them before raising a bug. \ No newline at end of file From 9ac3ad9f1134cd2ccd8c6cdb0be551adbd565d9d Mon Sep 17 00:00:00 2001 From: Christopher Nadler Date: Fri, 4 Jul 2025 15:51:22 +0200 Subject: [PATCH 3/9] Add M5STACK_ATOM_S3R Pin definitions --- .github/workflows/ESP32.yml | 1 + src/camera_pins.h | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/.github/workflows/ESP32.yml b/.github/workflows/ESP32.yml index ad39378..ae1332d 100644 --- a/.github/workflows/ESP32.yml +++ b/.github/workflows/ESP32.yml @@ -113,6 +113,7 @@ jobs: - ESP32_GENERIC-SPIRAM@M5STACK_WIDE - ESP32_GENERIC-SPIRAM@M5STACK_ESP32CAM - ESP32_GENERIC-SPIRAM@M5STACK_UNITCAM + - MICROPY_CAMERA_MODEL_M5STACK_ATOM_S3R - ESP32_GENERIC-SPIRAM@AI_THINKER - ESP32_GENERIC-SPIRAM@TTGO_T_JOURNAL - ESP32_GENERIC-SPIRAM@TTGO_T_CAMERA_PLUS diff --git a/src/camera_pins.h b/src/camera_pins.h index 203f7f1..fd0f911 100644 --- a/src/camera_pins.h +++ b/src/camera_pins.h @@ -116,6 +116,25 @@ #define MICROPY_CAMERA_PIN_HREF 18 #define MICROPY_CAMERA_PIN_PCLK 12 +#elif defined(MICROPY_CAMERA_MODEL_M5STACK_ATOM_S3R) +#define MICROPY_CAMERA_PIN_PWDN 18 +#define MICROPY_CAMERA_PIN_RESET -1 +#define MICROPY_CAMERA_PIN_XCLK 21 +#define MICROPY_CAMERA_PIN_SIOD 12 +#define MICROPY_CAMERA_PIN_SIOC 9 + +#define MICROPY_CAMERA_PIN_D7 13 +#define MICROPY_CAMERA_PIN_D6 11 +#define MICROPY_CAMERA_PIN_D5 17 +#define MICROPY_CAMERA_PIN_D4 4 +#define MICROPY_CAMERA_PIN_D3 48 +#define MICROPY_CAMERA_PIN_D2 46 +#define MICROPY_CAMERA_PIN_D1 42 +#define MICROPY_CAMERA_PIN_D0 3 +#define MICROPY_CAMERA_PIN_VSYNC 10 +#define MICROPY_CAMERA_PIN_HREF 14 +#define MICROPY_CAMERA_PIN_PCLK 40 + #elif defined(MICROPY_CAMERA_MODEL_AI_THINKER) #define MICROPY_CAMERA_PIN_PWDN 32 #define MICROPY_CAMERA_PIN_RESET -1 From 720a195bf03086d2a03de264d88920d6235248cf Mon Sep 17 00:00:00 2001 From: Christopher Nadler Date: Fri, 4 Jul 2025 15:53:20 +0200 Subject: [PATCH 4/9] Update readme --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index c46598e..5dc3976 100644 --- a/README.md +++ b/README.md @@ -252,6 +252,7 @@ Below is a list of supported `MICROPY_CAMERA_MODEL_xxx` definitions: - MICROPY_CAMERA_MODEL_M5STACK_WIDE - [M5Stack Wide](https://shop.m5stack.com/collections/m5-cameras) - MICROPY_CAMERA_MODEL_M5STACK_ESP32CAM - [M5Stack ESP32CAM](https://shop.m5stack.com/collections/m5-cameras) - MICROPY_CAMERA_MODEL_M5STACK_CAMS3_UNIT - [M5Stack CAMS3 Unit](https://shop.m5stack.com/collections/m5-cameras) +- MICROPY_CAMERA_MODEL_M5STACK_ATOM_S3R - [M5Stack Atom S3R](https://shop.m5stack.com/products/atoms3r-camera-kit-m12-version-ov3660) - MICROPY_CAMERA_MODEL_AI_THINKER - [AI-Thinker ESP32-CAM] - MICROPY_CAMERA_MODEL_XIAO_ESP32S3 - [XIAO ESP32S3](https://www.seeedstudio.com/xiao-series-page) - MICROPY_CAMERA_MODEL_ESP32_MP_CAMERA_BOARD - [ESP32 MP Camera Board] From bd668701d630532889c604852a17b445ec653074 Mon Sep 17 00:00:00 2001 From: Christopher Nadler Date: Fri, 4 Jul 2025 16:47:31 +0200 Subject: [PATCH 5/9] update pipeline --- .github/workflows/ESP32.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ESP32.yml b/.github/workflows/ESP32.yml index ae1332d..fc58d07 100644 --- a/.github/workflows/ESP32.yml +++ b/.github/workflows/ESP32.yml @@ -113,11 +113,11 @@ jobs: - ESP32_GENERIC-SPIRAM@M5STACK_WIDE - ESP32_GENERIC-SPIRAM@M5STACK_ESP32CAM - ESP32_GENERIC-SPIRAM@M5STACK_UNITCAM - - MICROPY_CAMERA_MODEL_M5STACK_ATOM_S3R - ESP32_GENERIC-SPIRAM@AI_THINKER - ESP32_GENERIC-SPIRAM@TTGO_T_JOURNAL - ESP32_GENERIC-SPIRAM@TTGO_T_CAMERA_PLUS - ESP32_GENERIC_S3-SPIRAM_OCT@M5STACK_CAMS3_UNIT + - ESP32_GENERIC_S3-SPIRAM_OCT@M5STACK_ATOM_S3R - ESP32_GENERIC_S3-SPIRAM_OCT@XIAO_ESP32S3 - ESP32_GENERIC_S3-SPIRAM_OCT@ESP32S3_CAM_LCD - ESP32_GENERIC_S3-SPIRAM_OCT@ESP32S3_EYE From 192095a355eba0e8c645c5525eab6a69a9666a00 Mon Sep 17 00:00:00 2001 From: Christopher Nadler Date: Tue, 29 Jul 2025 21:41:33 +0200 Subject: [PATCH 6/9] update M5 stack atom s3 --- README.md | 2 +- src/camera_pins.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5dc3976..3768354 100644 --- a/README.md +++ b/README.md @@ -252,7 +252,7 @@ Below is a list of supported `MICROPY_CAMERA_MODEL_xxx` definitions: - MICROPY_CAMERA_MODEL_M5STACK_WIDE - [M5Stack Wide](https://shop.m5stack.com/collections/m5-cameras) - MICROPY_CAMERA_MODEL_M5STACK_ESP32CAM - [M5Stack ESP32CAM](https://shop.m5stack.com/collections/m5-cameras) - MICROPY_CAMERA_MODEL_M5STACK_CAMS3_UNIT - [M5Stack CAMS3 Unit](https://shop.m5stack.com/collections/m5-cameras) -- MICROPY_CAMERA_MODEL_M5STACK_ATOM_S3R - [M5Stack Atom S3R](https://shop.m5stack.com/products/atoms3r-camera-kit-m12-version-ov3660) +- MICROPY_CAMERA_MODEL_M5STACK_ATOM_S3R - [M5Stack Atom S3R](https://docs.m5stack.com/en/core/AtomS3R-M12) - MICROPY_CAMERA_MODEL_AI_THINKER - [AI-Thinker ESP32-CAM] - MICROPY_CAMERA_MODEL_XIAO_ESP32S3 - [XIAO ESP32S3](https://www.seeedstudio.com/xiao-series-page) - MICROPY_CAMERA_MODEL_ESP32_MP_CAMERA_BOARD - [ESP32 MP Camera Board] diff --git a/src/camera_pins.h b/src/camera_pins.h index fd0f911..6041cae 100644 --- a/src/camera_pins.h +++ b/src/camera_pins.h @@ -117,7 +117,7 @@ #define MICROPY_CAMERA_PIN_PCLK 12 #elif defined(MICROPY_CAMERA_MODEL_M5STACK_ATOM_S3R) -#define MICROPY_CAMERA_PIN_PWDN 18 +#define MICROPY_CAMERA_PIN_PWDN -1 //needs to be low to run #define MICROPY_CAMERA_PIN_RESET -1 #define MICROPY_CAMERA_PIN_XCLK 21 #define MICROPY_CAMERA_PIN_SIOD 12 From febc944870bae8e437abf2470047758ab67e2b17 Mon Sep 17 00:00:00 2001 From: Christopher Nadler Date: Sat, 2 Aug 2025 14:44:02 +0200 Subject: [PATCH 7/9] add typing stub --- typings/acamera.pyi | 9 ++ typings/camera.pyi | 348 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 357 insertions(+) create mode 100644 typings/acamera.pyi create mode 100644 typings/camera.pyi diff --git a/typings/acamera.pyi b/typings/acamera.pyi new file mode 100644 index 0000000..88ede9f --- /dev/null +++ b/typings/acamera.pyi @@ -0,0 +1,9 @@ +from camera import Camera as _Camera + +class Camera(_Camera): + async def acapture(self) -> memoryview: + """Asynchronously capture a frame and return it as a memoryview. + + Yields control back to the event loop while waiting for a frame to become available. + """ + ... \ No newline at end of file diff --git a/typings/camera.pyi b/typings/camera.pyi new file mode 100644 index 0000000..679d9be --- /dev/null +++ b/typings/camera.pyi @@ -0,0 +1,348 @@ +from __future__ import annotations +from typing import Final + +class GainCeiling(): + X2: Final[int] = 0 # 2X gain + X4: Final[int] = 1 # 4X gain + X8: Final[int] = 2 # 8X gain + X16: Final[int] = 3 # 16X gain + X32: Final[int] = 4 # 32X gain + X64: Final[int] = 5 # 64X gain + X128: Final[int] = 6 # 128X gain + def __init__(self, *argv, **kwargs) -> None: + ... + + +class GrabMode(): + WHEN_EMPTY: Final[int] = 0 + LATEST: Final[int] = 1 + def __init__(self, *argv, **kwargs) -> None: + ... + + +class PixelFormat(): + RGB555: Final[int] = 8 + RGB565: Final[int] = 0 + RGB888: Final[int] = 5 + YUV420: Final[int] = 2 + YUV422: Final[int] = 1 + RGB444: Final[int] = 7 + GRAYSCALE: Final[int] = 3 + JPEG: Final[int] = 4 + RAW: Final[int] = 6 + def __init__(self, *argv, **kwargs) -> None: + ... + + +class FrameSize(): + R240X240: Final[int] = 5 + XGA: Final[int] = 12 + R320X320: Final[int] = 7 + QVGA: Final[int] = 6 + R128x128: int = 2 + QXGA: Final[int] = 19 + VGA: Final[int] = 10 + R96X96: Final[int] = 0 + WQXGA: Final[int] = 21 + SVGA: Final[int] = 11 + UXGA: Final[int] = 15 + SXGA: Final[int] = 14 + HQVGA: Final[int] = 4 + QSXGA: Final[int] = 23 + HVGA: Final[int] = 9 + CIF: Final[int] = 8 + HD: Final[int] = 13 + FHD: Final[int] = 16 + QHD: Final[int] = 20 + P_3MP: Final[int] = 18 + QQVGA: Final[int] = 1 + P_FHD: Final[int] = 22 + QCIF: Final[int] = 3 + P_HD: Final[int] = 17 + def __init__(self, *argv, **kwargs) -> None: + ... + + +class Camera(): + def __init__(self, *, + data_pins: list[int] | None = None, + pclk_pin: int | None = None, + vsync_pin: int | None = None, + href_pin: int | None = None, + sda_pin: int | None = None, + scl_pin: int | None = None, + xclk_pin: int | None = None, + xclk_freq: int = 20000000, + powerdown_pin: int = -1, + reset_pin: int = -1, + pixel_format: int = PixelFormat.RGB565, + frame_size: int = FrameSize.QVGA, + jpeg_quality: int = 85, + fb_count: int = 1, + grab_mode: int = GrabMode.WHEN_EMPTY, + init: bool = True) -> None: + ... + + def get_special_effect(self) -> int: + """Get the current special effect setting.""" + ... + + def set_special_effect(self, value: int) -> None: + """Set the special effect.""" + ... + + def set_awb_gain(self, value: bool) -> None: + """Enable/disable Auto White Balance Gain.""" + ... + + def get_awb_gain(self) -> bool: + """Get Auto White Balance Gain state.""" + ... + + def set_agc_gain(self, value: int) -> None: + """Set the Auto Gain Control gain value.""" + ... + + def get_agc_gain(self) -> int: + """Get the Auto Gain Control gain value.""" + ... + + def set_aec_value(self, value: int) -> None: + """Set the Auto Exposure Control value.""" + ... + + def get_aec_value(self) -> int: + """Get the Auto Exposure Control value.""" + ... + + def set_bpc(self, value: bool) -> None: + """Enable/disable Bad Pixel Correction.""" + ... + + def get_bpc(self) -> bool: + """Get Bad Pixel Correction state.""" + ... + + def set_contrast(self, value: int) -> None: + """Set the contrast level (-2 to 2).""" + ... + + def get_contrast(self) -> int: + """Get the contrast level.""" + ... + + def set_colorbar(self, value: bool) -> None: + """Enable/disable color bar test pattern.""" + ... + + def get_colorbar(self) -> bool: + """Get color bar test pattern state.""" + ... + + def set_brightness(self, value: int) -> None: + """Set the brightness level (-2 to 2).""" + ... + + def get_brightness(self) -> int: + """Get the brightness level.""" + ... + + def set_aec2(self, value: bool) -> None: + """Enable/disable AEC DSP.""" + ... + + def get_aec2(self) -> bool: + """Get AEC DSP state.""" + ... + + def set_whitebal(self, value: bool) -> None: + """Enable/disable white balance.""" + ... + + def get_whitebal(self) -> bool: + """Get white balance state.""" + ... + + def set_wb_mode(self, value: int) -> None: + """Set white balance mode.""" + ... + + def get_wb_mode(self) -> int: + """Get white balance mode.""" + ... + + def set_vflip(self, value: bool) -> None: + """Enable/disable vertical flip.""" + ... + + def get_vflip(self) -> bool: + """Get vertical flip state.""" + ... + + def set_wpc(self, value: bool) -> None: + """Enable/disable White Pixel Correction.""" + ... + + def get_wpc(self) -> bool: + """Get White Pixel Correction state.""" + ... + + def set_ae_level(self, value: int) -> None: + """Set Auto Exposure level (-2 to 2).""" + ... + + def get_ae_level(self) -> int: + """Get Auto Exposure level.""" + ... + + def reconfigure(self, *, frame_size: int | None = None, + pixel_format: int | None = None, + grab_mode: int | None = None, + fb_count: int | None = None) -> None: + """Reconfigure camera with new settings.""" + ... + + def init(self) -> None: + """Initialize the camera.""" + ... + + def deinit(self) -> None: + """Deinitialize the camera.""" + ... + + def set_dcw(self, value: bool) -> None: + """Enable/disable DCW (Downsize EN).""" + ... + + def get_dcw(self) -> bool: + """Get DCW (Downsize EN) state.""" + ... + + def set_sharpness(self, value: int) -> None: + """Set the sharpness level (-2 to 2).""" + ... + + def get_sharpness(self) -> int: + """Get the sharpness level.""" + ... + + def set_saturation(self, value: int) -> None: + """Set the saturation level (-2 to 2).""" + ... + + def get_saturation(self) -> int: + """Get the saturation level.""" + ... + + def set_raw_gma(self, value: bool) -> None: + """Enable/disable GMA (Gamma) Correction.""" + ... + + def get_raw_gma(self) -> bool: + """Get GMA (Gamma) Correction state.""" + ... + + def set_quality(self, value: int) -> None: + """Set JPEG quality (0-63).""" + ... + + def get_quality(self) -> int: + """Get JPEG quality.""" + ... + + def set_frame_size(self, value: int) -> None: + """Set frame size.""" + ... + + def get_frame_size(self) -> int: + """Get frame size.""" + ... + + def set_exposure_ctrl(self, value: bool) -> None: + """Enable/disable Auto Exposure Control.""" + ... + + def get_exposure_ctrl(self) -> bool: + """Get Auto Exposure Control state.""" + ... + + def set_denoise(self, value: int) -> None: + """Set denoise level.""" + ... + + def get_denoise(self) -> int: + """Get denoise level.""" + ... + + def set_gain_ctrl(self, value: bool) -> None: + """Enable/disable Auto Gain Control.""" + ... + + def get_gain_ctrl(self) -> bool: + """Get Auto Gain Control state.""" + ... + + def set_lenc(self, value: bool) -> None: + """Enable/disable Lens Correction.""" + ... + + def get_lenc(self) -> bool: + """Get Lens Correction state.""" + ... + + def set_hmirror(self, value: bool) -> None: + """Enable/disable horizontal mirror.""" + ... + + def get_hmirror(self) -> bool: + """Get horizontal mirror state.""" + ... + + def set_gainceiling(self, value: int) -> None: + """Set gain ceiling.""" + ... + + def get_gainceiling(self) -> int: + """Get gain ceiling.""" + ... + + def frame_available(self) -> bool: + """Check if a frame is available.""" + ... + + def capture(self) -> memoryview: + """Capture a frame and return it as a memoryview.""" + ... + + def free_buffer(self) -> None: + """Free the frame buffer.""" + ... + + def get_pixel_width(self) -> int: + """Get frame width in pixels.""" + ... + + def get_pixel_height(self) -> int: + """Get frame height in pixels.""" + ... + + def get_pixel_format(self) -> int: + """Get current pixel format.""" + ... + + def get_sensor_name(self) -> str: + """Get camera sensor name.""" + ... + + def get_max_frame_size(self) -> int: + """Get maximum supported frame size.""" + ... + + def get_fb_count(self) -> int: + """Get frame buffer count.""" + ... + + def get_grab_mode(self) -> int: + """Get current grab mode.""" + ... + From e2e800a4addf0fbcf34444bac3d65fd96f29d09f Mon Sep 17 00:00:00 2001 From: Christopher Nadler Date: Thu, 14 Aug 2025 12:41:01 +0200 Subject: [PATCH 8/9] Add MICROPY_ROM_TEXT_COMPRESSION as target compile definition and coorect pipeline to include mp_jpeg --- .github/workflows/ESP32.yml | 6 +++--- src/micropython.cmake | 5 +++++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ESP32.yml b/.github/workflows/ESP32.yml index fc58d07..eeeaa0c 100644 --- a/.github/workflows/ESP32.yml +++ b/.github/workflows/ESP32.yml @@ -105,7 +105,6 @@ jobs: - ESP32_GENERIC_S2 - ESP32_GENERIC_S3 - ESP32_GENERIC_S3-SPIRAM_OCT - - ESP32_GENERIC_S3-FLASH_4M - ESP32_GENERIC-SPIRAM@WROVER_KIT - ESP32_GENERIC-SPIRAM@ESP_EYE - ESP32_GENERIC-SPIRAM@M5STACK_PSRAM @@ -158,6 +157,7 @@ jobs: - name: Build MicroPython run: | cd ${{ github.workspace }} + cd .. git clone https://github.com/cnadler86/mp_jpeg.git cd ~/esp-idf/components/esp32-camera CAM_DRIVER=$(git describe --tags --always --dirty) @@ -169,9 +169,9 @@ jobs: IFS='-' read -r BOARD_NAME BOARD_VARIANT <<< "${BUILD_TARGET}" if [ -n "${BOARD_VARIANT}" ]; then - IDF_CMD="idf.py -D MICROPY_BOARD=$BOARD_NAME -D USER_C_MODULES=${{ github.workspace }}/src/micropython.cmake -D MICROPY_BOARD_VARIANT=$BOARD_VARIANT -B build-$BUILD_TARGET -D MP_CAMERA_DRIVER_VERSION=$CAM_DRIVER -D MP_JPEG_DIR=${{ github.workspace }}/mp_jpeg" + IDF_CMD="idf.py -D MICROPY_BOARD=$BOARD_NAME -D USER_C_MODULES=${{ github.workspace }}/src/micropython.cmake -D MICROPY_BOARD_VARIANT=$BOARD_VARIANT -B build-$BUILD_TARGET -D MP_CAMERA_DRIVER_VERSION=$CAM_DRIVER" else - IDF_CMD="idf.py -D MICROPY_BOARD=$BOARD_NAME -D USER_C_MODULES=${{ github.workspace }}/src/micropython.cmake -B build-$BUILD_TARGET -D MP_CAMERA_DRIVER_VERSION=$CAM_DRIVER -D MP_JPEG_DIR=${{ github.workspace }}/mp_jpeg" + IDF_CMD="idf.py -D MICROPY_BOARD=$BOARD_NAME -D USER_C_MODULES=${{ github.workspace }}/src/micropython.cmake -B build-$BUILD_TARGET -D MP_CAMERA_DRIVER_VERSION=$CAM_DRIVER" fi if [ -n "${CAMERA_MODEL}" ]; then echo "FW_NAME=${CAMERA_MODEL}" >> $GITHUB_ENV diff --git a/src/micropython.cmake b/src/micropython.cmake index d08205b..178d39f 100644 --- a/src/micropython.cmake +++ b/src/micropython.cmake @@ -81,6 +81,11 @@ if (MP_CAMERA_DRIVER_VERSION) ) endif() +# Camera module strings are not suitable for compression and cause size increase +target_compile_definitions(usermod_mp_camera INTERFACE + MICROPY_ROM_TEXT_COMPRESSION=0 +) + # Link the camera module with the main usermod target target_link_libraries(usermod INTERFACE usermod_mp_camera) From ab114facc4d674b675c5a44e3a010ef987a51afa Mon Sep 17 00:00:00 2001 From: Christopher Nadler <147471517+cnadler86@users.noreply.github.com> Date: Thu, 14 Aug 2025 21:22:27 +0200 Subject: [PATCH 9/9] ESP32.yml aktualisieren --- .github/workflows/ESP32.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ESP32.yml b/.github/workflows/ESP32.yml index eeeaa0c..3ad8407 100644 --- a/.github/workflows/ESP32.yml +++ b/.github/workflows/ESP32.yml @@ -59,7 +59,7 @@ jobs: if: steps.cache_esp_idf.outputs.cache-hit != 'true' run: | cd ~ - git clone --depth 1 --branch v5.4 https://github.com/espressif/esp-idf.git + git clone --depth 1 --branch v5.4.2 https://github.com/espressif/esp-idf.git # git clone --depth 1 --branch ${{ env.IDF_VER }} https://github.com/espressif/esp-idf.git git -C esp-idf submodule update --init --recursive --filter=tree:0 cd esp-idf