diff --git a/dispositivos/esp32-cam/ESP32-CAM Pinout.jpg b/dispositivos/esp32-cam/ESP32-CAM Pinout.jpg new file mode 100644 index 0000000..82b3a2d Binary files /dev/null and b/dispositivos/esp32-cam/ESP32-CAM Pinout.jpg differ diff --git a/dispositivos/esp32-cam/OV2640.pdf b/dispositivos/esp32-cam/OV2640.pdf new file mode 100644 index 0000000..a81d1ce Binary files /dev/null and b/dispositivos/esp32-cam/OV2640.pdf differ diff --git a/dispositivos/esp32-cam/README.md b/dispositivos/esp32-cam/README.md new file mode 100644 index 0000000..8b5db16 --- /dev/null +++ b/dispositivos/esp32-cam/README.md @@ -0,0 +1,12 @@ +esptool.py --chip esp32 --port /dev/ttyUSB0 erase_flash + +esptool.py --chip esp32 --port /dev/ttyUSB0 write_flash -z 0x1000 micropython_camera_feeeb5ea3_esp32_idf4_4.bin + +https://github.com/lemariva/micropython-camera-driver + +https://www.profetolocka.com.ar/2022/04/18/aprende-a-programar-la-esp32-cam-en-micropython-parte-1/ + +https://www.profetolocka.com.ar/2022/04/25/aprende-a-programar-la-esp32-cam-en-micropython-parte-2/ + +https://www.arducam.com/esp32-machine-vision-learning-guide/ + diff --git a/dispositivos/esp32-cam/capture.py b/dispositivos/esp32-cam/capture.py new file mode 100644 index 0000000..b154c08 --- /dev/null +++ b/dispositivos/esp32-cam/capture.py @@ -0,0 +1,21 @@ +# Código para Capturar una Imagen + +import esp +import machine +import time +import camera + +# Inicializar la cámara +camera.init(0, format=camera.JPEG, fb_location=camera.PSRAM) + +# Capturar una imagen +buf = camera.capture() + +# Guardar la imagen en un archivo +with open("/sd/captura.jpg", "wb") as f: + f.write(buf) + +print("Imagen guardada como captura.jpg") + +# Finalizar la cámara +camera.deinit() diff --git a/dispositivos/esp32-cam/micropython-camera-driver/.gitignore b/dispositivos/esp32-cam/micropython-camera-driver/.gitignore new file mode 100644 index 0000000..61c3ba8 --- /dev/null +++ b/dispositivos/esp32-cam/micropython-camera-driver/.gitignore @@ -0,0 +1,59 @@ +# Prerequisites +*.d + +# Object files +*.o +*.ko +*.obj +*.elf + +# Linker output +*.ilk +*.map +*.exp + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su +*.idb +*.pdb + +# Kernel Module Compile Results +*.mod* +*.cmd +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf + +# emacs backup +*~ +# tarball +*.tgz +*.txz + diff --git a/dispositivos/esp32-cam/micropython-camera-driver/LICENSE b/dispositivos/esp32-cam/micropython-camera-driver/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/dispositivos/esp32-cam/micropython-camera-driver/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/dispositivos/esp32-cam/micropython-camera-driver/README.md b/dispositivos/esp32-cam/micropython-camera-driver/README.md new file mode 100644 index 0000000..6acdd10 --- /dev/null +++ b/dispositivos/esp32-cam/micropython-camera-driver/README.md @@ -0,0 +1,154 @@ +# micropython-camera-driver + +This repository adds camera (OV2640) support to MicroPython for the ESP32 family. + +**NEW**: The camera uses now the PSRAM. Thus, you are able to take photos with more resolution. The standard mode is without PSRAM you can activate that using the argument `fb_location=camera.PSRAM`. Thanks @mocleiri for the [info and the MicroPython PR](https://github.com/lemariva/micropython-camera-driver/issues/32#issuecomment-1027613157). + +I follow the advice of [#32](https://github.com/lemariva/micropython-camera-driver/issues/32) and modify the repository to fit to those requirements. + +For more information about installing MicroPython visit this tutorial: https://lemariva.com/blog/2022/01/micropython-upgraded-support-cameras-m5camera-esp32-cam-etc + +The MicroPython example codes are included here: +* [Webserver](https://github.com/lemariva/upyCam) +* [Timelapse Camera](https://github.com/lemariva/upyCam/tree/timelapse-camera) + + +## Example +```python +import camera + +## ESP32-CAM (default configuration) - https://bit.ly/2Ndn8tN +camera.init(0, format=camera.JPEG, fb_location=camera.PSRAM) + +## M5Camera (Version B) - https://bit.ly/317Xb74 +camera.init(0, d0=32, d1=35, d2=34, d3=5, d4=39, d5=18, d6=36, d7=19, + format=camera.JPEG, framesize=camera.FRAME_VGA, xclk_freq=camera.XCLK_10MHz, + href=26, vsync=25, reset=15, sioc=23, siod=22, xclk=27, pclk=21, fb_location=camera.PSRAM) #M5CAMERA + +## T-Camera Mini (green PCB) - https://bit.ly/31H1aaF +import axp202 # source https://github.com/lewisxhe/AXP202_PythonLibrary +# USB current limit must be disabled (otherwise init fails) +axp=axp202.PMU( scl=22, sda=21, address=axp202.AXP192_SLAVE_ADDRESS ) +limiting=axp.read_byte( axp202.AXP202_IPS_SET ) +limiting &= 0xfc +axp.write_byte( axp202.AXP202_IPS_SET, limiting ) + +camera.init(0, d0=5, d1=14, d2=4, d3=15, d4=18, d5=23, d6=36, d7=39, + format=camera.JPEG, framesize=camera.FRAME_VGA, + xclk_freq=camera.XCLK_20MHz, + href=25, vsync=27, reset=-1, pwdn=-1, + sioc=12, siod=13, xclk=32, pclk=19) + +# The parameters: format=camera.JPEG, xclk_freq=camera.XCLK_10MHz are standard for all 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. + +## Other settings: +# flip up side down +camera.flip(1) +# left / right +camera.mirror(1) + +# framesize +camera.framesize(camera.FRAME_240x240) +# The options are the following: +# FRAME_96X96 FRAME_QQVGA FRAME_QCIF FRAME_HQVGA FRAME_240X240 +# FRAME_QVGA FRAME_CIF FRAME_HVGA FRAME_VGA FRAME_SVGA +# FRAME_XGA FRAME_HD FRAME_SXGA FRAME_UXGA FRAME_FHD +# FRAME_P_HD FRAME_P_3MP FRAME_QXGA FRAME_QHD FRAME_WQXGA +# FRAME_P_FHD FRAME_QSXGA +# Check this link for more information: https://bit.ly/2YOzizz + +# special effects +camera.speffect(camera.EFFECT_NONE) +# The options are the following: +# EFFECT_NONE (default) EFFECT_NEG EFFECT_BW EFFECT_RED EFFECT_GREEN EFFECT_BLUE EFFECT_RETRO + +# white balance +camera.whitebalance(camera.WB_NONE) +# The options are the following: +# WB_NONE (default) WB_SUNNY WB_CLOUDY WB_OFFICE WB_HOME + +# saturation +camera.saturation(0) +# -2,2 (default 0). -2 grayscale + +# brightness +camera.brightness(0) +# -2,2 (default 0). 2 brightness + +# contrast +camera.contrast(0) +#-2,2 (default 0). 2 highcontrast + +# quality +camera.quality(10) +# 10-63 lower number means higher quality + +buf = camera.capture() + +``` + +### Important +* 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 due that 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 I got almost every time out of memory, trying to capture an image in a different format than JPEG. +* The firmware was compiled without BLE support. Otherwise I got `region 'iram0_0_seg' overflowed by xxx bytes`. + +## Firmware + +I've included a compiled MicroPython firmware with camera (check the `firmware` folder). The firmware was compiled using following versions and hashes: + +* esp-idf v4.4.x - [`b64925c56`](https://github.com/espressif/esp-idf/commit/b64925c5673206100eaf4337d064d0fe3507eaec) +* MicroPython v1.18-63-feeeb5ea3-dirty - [`feeeb5ea3`](https://github.com/micropython/micropython/commit/feeeb5ea3afe801b381eb5d4b310e83290634c46) +* esp32-camera - [`093688e`](https://github.com/espressif/esp32-camera/commit/093688e0b3521ac982bc3d38bbf92059d97e3613) + +There is also a more current firmware based on MicroPython v1.21.0, ESP-IDF v5.0.2 and esp32-camera v2.0.5. + +To flash it to the board, you need to type the following: +```sh +esptool.py --chip esp32 --port /dev/ttyUSB0 erase_flash +esptool.py --chip esp32 --port /dev/ttyUSB0 write_flash -z 0x1000 micropython_camera_feeeb5ea3_esp32_idf4_4.bin +``` +More information is available in this [tutorial](https://lemariva.com/blog/2022/01/micropython-upgraded-support-cameras-m5camera-esp32-cam-etc). + +If you want to compile your driver from scratch follow the next section: + +## DIY + +Read this section if you want to include the camera support to MicroPython from scratch. To do that follow these steps: + +- Note 1: if you get stuck, those pages are a good help: + - https://github.com/micropython/micropython/tree/master/ports/esp32 + - https://docs.espressif.com/projects/esp-idf/en/stable/esp32/get-started/index.html#installation-step-by-step + +- Note 2: Up to micropython version 1.14, the build tool for the esp32 port is Make. Starting with this [PR](https://github.com/micropython/micropython/pull/6892), it is CMAKE. You can find more discussion in this [micropython forum blog post](https://forum.micropython.org/viewtopic.php?f=18&t=9820) + +- Note 3: The steps below now also work for MicroPython v1.21.0, ESP-IDF v5.0.2 and esp32-camera v2.0.5. + +1. Clone the MicroPython repository: + ``` + git clone --recursive https://github.com/micropython/micropython.git + ``` + Note: The MicroPython repo changes a lot, I've done this using the version with the hash mentioned above. + + :warning: If you want to directly replace the original files with the provided in this repository, be sure that you've taken the same commit hash. MicroPython changes a lot, and you'll compiling issues if you ignore this warning. + +2. Copy the files and folders inside the `boards` folder into `micropython/ports/esp32/boards`. Or use a symbolic link `ln -s [...]/micropython-camera-driver/boards/ESP32_CAM micropython/ports/esp32/boards/ESP32_CAM ` (recommended - change the `[...]` to the right path). +3. Clone the `https://github.com/espressif/esp32-camera` repository inside the `~/esp/esp-idf/components` folder. + ```sh + cd ~/esp/esp-idf/components + git clone https://github.com/espressif/esp32-camera + git checkout [CHECK-HASH-ABOVE] + ``` +4. Compile the firmware by typing following commands: + ``` + cd micropython/ports/esp32 + make USER_C_MODULES=../../../../micropython-camera-driver/src/micropython.cmake BOARD=ESP32_CAM all + ``` + Note that the folder `micropython-camera-driver` should be in the same folder level as the `micropython`. Otherwise, you'll need to change the path (`../../../../micropython-camera-driver/src/`) to the `micropython.cmake` file. +5. Deploy the firmware into the ESP32 by typing: + ``` + cd micropython/ports/esp32 + esptool.py --port /dev/ttyUSB0 erase_flash + esptool.py --chip esp32 --port /dev/ttyUSB0 write_flash -z 0x1000 build-ESP32_CAM/firmware.bin + ``` diff --git a/dispositivos/esp32-cam/micropython-camera-driver/boards/ESP32_CAM/board.json b/dispositivos/esp32-cam/micropython-camera-driver/boards/ESP32_CAM/board.json new file mode 100644 index 0000000..1b592b1 --- /dev/null +++ b/dispositivos/esp32-cam/micropython-camera-driver/boards/ESP32_CAM/board.json @@ -0,0 +1,20 @@ +{ + "deploy": [ + "../deploy.md" + ], + "docs": "", + "features": [ + "External Flash", + "WiFi" + ], + "images": [ + "esp32_devkitc.jpg" + ], + "mcu": "esp32", + "product": "ESP32 / CAM", + "thumbnail": "", + "url": "https://www.espressif.com/en/products/modules", + "variants": { + }, + "vendor": "Espressif" +} diff --git a/dispositivos/esp32-cam/micropython-camera-driver/boards/ESP32_CAM/board.md b/dispositivos/esp32-cam/micropython-camera-driver/boards/ESP32_CAM/board.md new file mode 100644 index 0000000..0b8af81 --- /dev/null +++ b/dispositivos/esp32-cam/micropython-camera-driver/boards/ESP32_CAM/board.md @@ -0,0 +1,2 @@ + +ESP32_GENERIC with SPIRAM and OV2640 camera diff --git a/dispositivos/esp32-cam/micropython-camera-driver/boards/ESP32_CAM/mpconfigboard.cmake b/dispositivos/esp32-cam/micropython-camera-driver/boards/ESP32_CAM/mpconfigboard.cmake new file mode 100644 index 0000000..07126e2 --- /dev/null +++ b/dispositivos/esp32-cam/micropython-camera-driver/boards/ESP32_CAM/mpconfigboard.cmake @@ -0,0 +1,9 @@ +set(SDKCONFIG_DEFAULTS + boards/sdkconfig.base + boards/sdkconfig.spiram + boards/ESP32_CAM/sdkconfig.esp32cam +) + +list(APPEND MICROPY_DEF_BOARD + MICROPY_HW_BOARD_NAME="ESP32 module with Camera" +) diff --git a/dispositivos/esp32-cam/micropython-camera-driver/boards/ESP32_CAM/mpconfigboard.h b/dispositivos/esp32-cam/micropython-camera-driver/boards/ESP32_CAM/mpconfigboard.h new file mode 100644 index 0000000..8ac83f7 --- /dev/null +++ b/dispositivos/esp32-cam/micropython-camera-driver/boards/ESP32_CAM/mpconfigboard.h @@ -0,0 +1,10 @@ +#ifndef MICROPY_HW_BOARD_NAME +#define MICROPY_HW_BOARD_NAME "ESP32 module with Camera" +#endif + +#define MICROPY_PY_BLUETOOTH (0) +#define MODULE_CAMERA_ENABLED (1) + +#ifndef MICROPY_HW_MCU_NAME +#define MICROPY_HW_MCU_NAME "ESP32" +#endif diff --git a/dispositivos/esp32-cam/micropython-camera-driver/boards/ESP32_CAM/sdkconfig.esp32cam b/dispositivos/esp32-cam/micropython-camera-driver/boards/ESP32_CAM/sdkconfig.esp32cam new file mode 100644 index 0000000..3a09373 --- /dev/null +++ b/dispositivos/esp32-cam/micropython-camera-driver/boards/ESP32_CAM/sdkconfig.esp32cam @@ -0,0 +1,5 @@ +# MicroPython on ESP32, ESP IDF configuration with SPIRAM support +# The following options override the defaults + +# ESP32-CAMERA +CONFIG_OV2640_SUPPORT=y diff --git a/dispositivos/esp32-cam/micropython-camera-driver/firmware/micropython_camera_feeeb5ea3_esp32_idf4_4.bin b/dispositivos/esp32-cam/micropython-camera-driver/firmware/micropython_camera_feeeb5ea3_esp32_idf4_4.bin new file mode 100644 index 0000000..7adc3bb Binary files /dev/null and b/dispositivos/esp32-cam/micropython-camera-driver/firmware/micropython_camera_feeeb5ea3_esp32_idf4_4.bin differ diff --git a/dispositivos/esp32-cam/micropython-camera-driver/firmware/micropython_cmake_9fef1c0bd_esp32_idf4.x_ble_camera.bin b/dispositivos/esp32-cam/micropython-camera-driver/firmware/micropython_cmake_9fef1c0bd_esp32_idf4.x_ble_camera.bin new file mode 100644 index 0000000..395aa7e Binary files /dev/null and b/dispositivos/esp32-cam/micropython-camera-driver/firmware/micropython_cmake_9fef1c0bd_esp32_idf4.x_ble_camera.bin differ diff --git a/dispositivos/esp32-cam/micropython-camera-driver/firmware/micropython_v1.21.0_camera_no_ble.bin b/dispositivos/esp32-cam/micropython-camera-driver/firmware/micropython_v1.21.0_camera_no_ble.bin new file mode 100644 index 0000000..d3c910f Binary files /dev/null and b/dispositivos/esp32-cam/micropython-camera-driver/firmware/micropython_v1.21.0_camera_no_ble.bin differ diff --git a/dispositivos/esp32-cam/micropython-camera-driver/src/micropython.cmake b/dispositivos/esp32-cam/micropython-camera-driver/src/micropython.cmake new file mode 100644 index 0000000..2f23e6e --- /dev/null +++ b/dispositivos/esp32-cam/micropython-camera-driver/src/micropython.cmake @@ -0,0 +1,22 @@ +# Create an INTERFACE library for our C module. +add_library(usermod_esp32camera INTERFACE) + +# Add our source files to the lib +target_sources(usermod_esp32camera INTERFACE + ${CMAKE_CURRENT_LIST_DIR}/modcamera.c +) + +# Add the current directory as an include directory. +target_include_directories(usermod_esp32camera INTERFACE + ${CMAKE_CURRENT_LIST_DIR} + ${IDF_PATH}/components/esp32-camera/driver/include + ${IDF_PATH}/components/esp32-camera/driver/private_include + ${IDF_PATH}/components/esp32-camera/conversions/include + ${IDF_PATH}/components/esp32-camera/conversions/private_include + ${IDF_PATH}/components/esp32-camera/sensors/private_include +) + +target_compile_definitions(usermod_esp32camera INTERFACE) + +# Link our INTERFACE library to the usermod target. +target_link_libraries(usermod INTERFACE usermod_esp32camera) \ No newline at end of file diff --git a/dispositivos/esp32-cam/micropython-camera-driver/src/micropython.mk b/dispositivos/esp32-cam/micropython-camera-driver/src/micropython.mk new file mode 100644 index 0000000..66ddf34 --- /dev/null +++ b/dispositivos/esp32-cam/micropython-camera-driver/src/micropython.mk @@ -0,0 +1,4 @@ +CAMERA_MOD_DIR := $(USERMOD_DIR) +SRC_USERMOD += $(addprefix $(CAMERA_MOD_DIR)/, modcamera.c) +CFLAGS_USERMOD += -I$(CAMERA_MOD_DIR) -DMODULE_CAMERA_ENABLED=1 + diff --git a/dispositivos/esp32-cam/micropython-camera-driver/src/modcamera.c b/dispositivos/esp32-cam/micropython-camera-driver/src/modcamera.c new file mode 100644 index 0000000..477edbf --- /dev/null +++ b/dispositivos/esp32-cam/micropython-camera-driver/src/modcamera.c @@ -0,0 +1,449 @@ +/* + * Copyright [2021] Mauro Riva + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "py/nlr.h" +#include "py/obj.h" +#include "modcamera.h" +#include "py/runtime.h" +#include "py/binary.h" + +#if MODULE_CAMERA_ENABLED + +#include "esp_system.h" +#include "spi_flash_mmap.h" +#include "esp_camera.h" +#include "esp_log.h" + + + +typedef struct _camera_obj_t { + int8_t id; + camera_config_t config; + bool used; +} camera_obj_t; + +//STATIC camera_obj_t camera_obj; +STATIC bool camera_init_helper(camera_obj_t *camera, size_t n_pos_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { + ARG_format, + ARG_framesize, + ARG_quality, + ARG_d0, + ARG_d1, + ARG_d2, + ARG_d3, + ARG_d4, + ARG_d5, + ARG_d6, + ARG_d7, + ARG_VSYNC, + ARG_HREF, + ARG_PCLK, + ARG_PWDN, + ARG_RESET, + ARG_XCLK, + ARG_SIOD, + ARG_SIOC, + ARG_FREQ, + ARG_FBSIZE, + ARG_FBLOC, + }; + + //{ MP_QSTR_d0, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + static const mp_arg_t allowed_args[] = { + { MP_QSTR_format, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = PIXFORMAT_JPEG} }, + { MP_QSTR_framesize, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = FRAMESIZE_VGA} }, + { MP_QSTR_quality, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 12} }, + { MP_QSTR_d0, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAM_PIN_D0} }, + { MP_QSTR_d1, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAM_PIN_D1} }, + { MP_QSTR_d2, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAM_PIN_D2} }, + { MP_QSTR_d3, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAM_PIN_D3} }, + { MP_QSTR_d4, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAM_PIN_D4} }, + { MP_QSTR_d5, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAM_PIN_D5} }, + { MP_QSTR_d6, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAM_PIN_D6} }, + { MP_QSTR_d7, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAM_PIN_D7} }, + { MP_QSTR_vsync, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAM_PIN_VSYNC} }, + { MP_QSTR_href, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAM_PIN_HREF} }, + { MP_QSTR_pclk, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAM_PIN_PCLK} }, + { MP_QSTR_pwdn, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAM_PIN_PWDN} }, + { MP_QSTR_reset, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAM_PIN_RESET} }, + { MP_QSTR_xclk, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAM_PIN_XCLK} }, + { MP_QSTR_siod, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAM_PIN_SIOD} }, + { MP_QSTR_sioc, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAM_PIN_SIOC} }, + { MP_QSTR_xclk_freq, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = XCLK_FREQ_10MHz} }, + { MP_QSTR_fb_size, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} }, + { MP_QSTR_fb_location, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAMERA_FB_IN_DRAM} }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_pos_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + // TODO:---- Check validity of arguments ---- + int8_t format = args[ARG_format].u_int; + if ((format != PIXFORMAT_JPEG) && + (format != PIXFORMAT_YUV422) && + (format != PIXFORMAT_GRAYSCALE) && + (format != PIXFORMAT_RGB565)) { + mp_raise_ValueError(MP_ERROR_TEXT("Image format is not valid")); + } + + int8_t size = args[ARG_framesize].u_int; + if ((size != FRAMESIZE_96X96) && + (size != FRAMESIZE_QQVGA) && + (size != FRAMESIZE_QCIF) && + (size != FRAMESIZE_HQVGA) && + (size != FRAMESIZE_240X240) && + (size != FRAMESIZE_QVGA) && + (size != FRAMESIZE_CIF) && + (size != FRAMESIZE_HVGA) && + (size != FRAMESIZE_VGA) && + (size != FRAMESIZE_SVGA) && + (size != FRAMESIZE_XGA) && + (size != FRAMESIZE_HD) && + (size != FRAMESIZE_SXGA) && + (size != FRAMESIZE_UXGA) && + (size != FRAMESIZE_FHD) && + (size != FRAMESIZE_P_HD) && + (size != FRAMESIZE_P_3MP) && + (size != FRAMESIZE_QXGA) && + (size != FRAMESIZE_QHD) && + (size != FRAMESIZE_WQXGA) && + (size != FRAMESIZE_P_FHD) && + (size != FRAMESIZE_QSXGA)) { + mp_raise_ValueError(MP_ERROR_TEXT("Image framesize is not valid")); + } + + + int32_t xclk_freq = args[ARG_FREQ].u_int; + if ((xclk_freq != XCLK_FREQ_10MHz) && + (xclk_freq != XCLK_FREQ_20MHz)) { + mp_raise_ValueError(MP_ERROR_TEXT("xclk frequency is not valid")); + } + + // configuring camera + camera->config.pin_d0 = args[ARG_d0].u_int; + camera->config.pin_d1 = args[ARG_d1].u_int; + camera->config.pin_d2 = args[ARG_d2].u_int; + camera->config.pin_d3 = args[ARG_d3].u_int; + camera->config.pin_d4 = args[ARG_d4].u_int; + camera->config.pin_d5 = args[ARG_d5].u_int; + camera->config.pin_d6 = args[ARG_d6].u_int; + camera->config.pin_d7 = args[ARG_d7].u_int; + camera->config.pin_vsync = args[ARG_VSYNC].u_int; + camera->config.pin_href = args[ARG_HREF].u_int; + camera->config.pin_pclk = args[ARG_PCLK].u_int; + camera->config.pin_pwdn = args[ARG_PWDN].u_int; + camera->config.pin_reset = args[ARG_RESET].u_int; + camera->config.pin_xclk = args[ARG_XCLK].u_int; + camera->config.pin_sscb_sda = args[ARG_SIOD].u_int; + camera->config.pin_sscb_scl = args[ARG_SIOC].u_int; + camera->config.pixel_format = args[ARG_format].u_int; //YUV422,GRAYSCALE,RGB565,JPEG + camera->config.jpeg_quality = args[ARG_quality].u_int; //0-63 lower number means higher quality + + // defaul parameters + //XCLK 20MHz or 10MHz for OV2640 double FPS (Experimental) + camera->config.xclk_freq_hz = args[ARG_FREQ].u_int; + camera->config.ledc_timer = LEDC_TIMER_0; + camera->config.ledc_channel = LEDC_CHANNEL_0; + camera->config.frame_size = args[ARG_framesize].u_int; //QQVGA-QXGA Do not use sizes above QVGA when not JPEG + camera->config.fb_count = args[ARG_FBSIZE].u_int; //if more than one, i2s runs in continuous mode. Use only with JPEG + camera->config.fb_location = args[ARG_FBLOC].u_int; + camera->config.grab_mode = CAMERA_GRAB_WHEN_EMPTY; + + esp_err_t err = esp_camera_init(&camera->config); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Camera Init Failed"); + mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Camera Init Failed")); + return false; + } + + return true; +} + + +STATIC mp_obj_t camera_init(mp_uint_t n_pos_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + + camera_obj_t camera_obj; + + bool camera = camera_init_helper(&camera_obj, n_pos_args - 1, pos_args + 1, kw_args); + if (camera) { + return mp_const_true; + } + else + { + return mp_const_false; + } +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(camera_init_obj, 1, camera_init); + + +STATIC mp_obj_t camera_deinit(){ + esp_err_t err = esp_camera_deinit(); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Camera deinit Failed"); + return mp_const_false; + } + + return mp_const_true; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(camera_deinit_obj, camera_deinit); + + +STATIC mp_obj_t camera_capture(){ + //acquire a frame + camera_fb_t * fb = esp_camera_fb_get(); + if (!fb) { + ESP_LOGE(TAG, "Camera Capture Failed"); + return mp_const_false; + } + + mp_obj_t image = mp_obj_new_bytes(fb->buf, fb->len); + + //return the frame buffer back to the driver for reuse + esp_camera_fb_return(fb); + return image; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(camera_capture_obj, camera_capture); + +STATIC mp_obj_t camera_flip(mp_obj_t direction){ + sensor_t * s = esp_camera_sensor_get(); + if (!s) { + ESP_LOGE(TAG, "Flipping Failed"); + return mp_const_false; + } + int dir = mp_obj_get_int(direction); + s->set_vflip(s, dir); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(camera_flip_obj, camera_flip); + +STATIC mp_obj_t camera_mirror(mp_obj_t direction){ + sensor_t * s = esp_camera_sensor_get(); + if (!s) { + ESP_LOGE(TAG, "Mirroring Failed"); + return mp_const_false; + } + int dir = mp_obj_get_int(direction); + s->set_hmirror(s, dir); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(camera_mirror_obj, camera_mirror); + +STATIC mp_obj_t camera_framesize(mp_obj_t what){ + sensor_t * s = esp_camera_sensor_get(); + if (!s) { + ESP_LOGE(TAG, "Framesize Failed"); + return mp_const_false; + } + int size = mp_obj_get_int(what); + /* same as in screen.h */ + if ((size != FRAMESIZE_96X96) && + (size != FRAMESIZE_QQVGA) && + (size != FRAMESIZE_QCIF) && + (size != FRAMESIZE_HQVGA) && + (size != FRAMESIZE_240X240) && + (size != FRAMESIZE_QVGA) && + (size != FRAMESIZE_CIF) && + (size != FRAMESIZE_HVGA) && + (size != FRAMESIZE_VGA) && + (size != FRAMESIZE_SVGA) && + (size != FRAMESIZE_XGA) && + (size != FRAMESIZE_HD) && + (size != FRAMESIZE_SXGA) && + (size != FRAMESIZE_UXGA) && + (size != FRAMESIZE_FHD) && + (size != FRAMESIZE_P_HD) && + (size != FRAMESIZE_P_3MP) && + (size != FRAMESIZE_QXGA) && + (size != FRAMESIZE_QHD) && + (size != FRAMESIZE_WQXGA) && + (size != FRAMESIZE_P_FHD) && + (size != FRAMESIZE_QSXGA)) { + mp_raise_ValueError(MP_ERROR_TEXT("Image framesize is not valid")); + } + + s->set_framesize(s, size); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(camera_framesize_obj, camera_framesize); + +STATIC mp_obj_t camera_quality(mp_obj_t what){ + sensor_t * s = esp_camera_sensor_get(); + if (!s) { + ESP_LOGE(TAG, "Quality Failed"); + return mp_const_false; + } + int val = mp_obj_get_int(what); // 10-63 lower number means higher quality + s->set_quality(s, val); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(camera_quality_obj, camera_quality); + +STATIC mp_obj_t camera_contrast(mp_obj_t what){ + //acquire a frame + sensor_t * s = esp_camera_sensor_get(); + if (!s) { + ESP_LOGE(TAG, "Contrast Failed"); + return mp_const_false; + } + int val = mp_obj_get_int(what); // -2,2 (default 0). 2 highcontrast + s->set_contrast(s, val); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(camera_contrast_obj, camera_contrast); + +STATIC mp_obj_t camera_saturation(mp_obj_t what){ + //acquire a frame + sensor_t * s = esp_camera_sensor_get(); + if (!s) { + ESP_LOGE(TAG, "Saturation Failed"); + return mp_const_false; + } + int val = mp_obj_get_int(what); + s->set_saturation(s, val); // -2,2 (default 0). -2 grayscale + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(camera_saturation_obj, camera_saturation); + +STATIC mp_obj_t camera_brightness(mp_obj_t what){ + sensor_t * s = esp_camera_sensor_get(); + if (!s) { + ESP_LOGE(TAG, "Brightness Failed"); + return mp_const_false; + } + int val = mp_obj_get_int(what); + s->set_brightness(s, val); // -2,2 (default 0). 2 brightest + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(camera_brightness_obj, camera_brightness); + +STATIC mp_obj_t camera_speffect(mp_obj_t what){ + sensor_t * s = esp_camera_sensor_get(); + if (!s) { + ESP_LOGE(TAG, "Special Effect Failed"); + return mp_const_false; + } + int val = mp_obj_get_int(what); + s->set_special_effect(s, val); // 0-6 (default 0). + // 0 - no effect + // 1 - negative + // 2 - black and white + // 3 - reddish + // 4 - greenish + // 5 - blue + // 6 - retro + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(camera_speffect_obj, camera_speffect); + +STATIC mp_obj_t camera_whitebalance(mp_obj_t what){ + sensor_t * s = esp_camera_sensor_get(); + if (!s) { + ESP_LOGE(TAG, "White Balance Failed"); + return mp_const_false; + } + int val = mp_obj_get_int(what); + s->set_wb_mode(s, val); // 0-4 (default 0). + // 0 - no effect + // 1 - sunny + // 2 - cloudy + // 3 - office + // 4 - home + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(camera_whitebalance_obj, camera_whitebalance); + +STATIC const mp_rom_map_elem_t camera_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_camera) }, + + { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&camera_init_obj) }, + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&camera_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR_capture), MP_ROM_PTR(&camera_capture_obj) }, + { MP_ROM_QSTR(MP_QSTR_flip), MP_ROM_PTR(&camera_flip_obj) }, + { MP_ROM_QSTR(MP_QSTR_mirror), MP_ROM_PTR(&camera_mirror_obj) }, + { MP_ROM_QSTR(MP_QSTR_framesize), MP_ROM_PTR(&camera_framesize_obj) }, + { MP_ROM_QSTR(MP_QSTR_quality), MP_ROM_PTR(&camera_quality_obj) }, + { MP_ROM_QSTR(MP_QSTR_contrast), MP_ROM_PTR(&camera_contrast_obj) }, + { MP_ROM_QSTR(MP_QSTR_saturation), MP_ROM_PTR(&camera_saturation_obj) }, + { MP_ROM_QSTR(MP_QSTR_brightness), MP_ROM_PTR(&camera_brightness_obj) }, + { MP_ROM_QSTR(MP_QSTR_speffect), MP_ROM_PTR(&camera_speffect_obj) }, + { MP_ROM_QSTR(MP_QSTR_whitebalance), MP_ROM_PTR(&camera_whitebalance_obj) }, + + // Constants + { MP_ROM_QSTR(MP_QSTR_JPEG), MP_ROM_INT(PIXFORMAT_JPEG) }, + { MP_ROM_QSTR(MP_QSTR_YUV422), MP_ROM_INT(PIXFORMAT_YUV422) }, + { MP_ROM_QSTR(MP_QSTR_GRAYSCALE), MP_ROM_INT(PIXFORMAT_GRAYSCALE) }, + { MP_ROM_QSTR(MP_QSTR_RGB565), MP_ROM_INT(PIXFORMAT_RGB565) }, + + { MP_ROM_QSTR(MP_QSTR_FRAME_96X96), MP_ROM_INT(FRAMESIZE_96X96) }, + { MP_ROM_QSTR(MP_QSTR_FRAME_QQVGA), MP_ROM_INT(FRAMESIZE_QQVGA) }, + { MP_ROM_QSTR(MP_QSTR_FRAME_QCIF), MP_ROM_INT(FRAMESIZE_QCIF) }, + { MP_ROM_QSTR(MP_QSTR_FRAME_HQVGA), MP_ROM_INT(FRAMESIZE_HQVGA) }, + { MP_ROM_QSTR(MP_QSTR_FRAME_240X240), MP_ROM_INT(FRAMESIZE_240X240) }, + { MP_ROM_QSTR(MP_QSTR_FRAME_QVGA), MP_ROM_INT(FRAMESIZE_QVGA) }, + { MP_ROM_QSTR(MP_QSTR_FRAME_CIF), MP_ROM_INT(FRAMESIZE_CIF) }, + { MP_ROM_QSTR(MP_QSTR_FRAME_HVGA), MP_ROM_INT(FRAMESIZE_HVGA) }, + { MP_ROM_QSTR(MP_QSTR_FRAME_VGA), MP_ROM_INT(FRAMESIZE_VGA) }, + { MP_ROM_QSTR(MP_QSTR_FRAME_SVGA), MP_ROM_INT(FRAMESIZE_SVGA) }, + { MP_ROM_QSTR(MP_QSTR_FRAME_XGA), MP_ROM_INT(FRAMESIZE_XGA) }, + { MP_ROM_QSTR(MP_QSTR_FRAME_HD), MP_ROM_INT(FRAMESIZE_HD) }, + { MP_ROM_QSTR(MP_QSTR_FRAME_SXGA), MP_ROM_INT(FRAMESIZE_SXGA) }, + { MP_ROM_QSTR(MP_QSTR_FRAME_UXGA), MP_ROM_INT(FRAMESIZE_UXGA) }, + { MP_ROM_QSTR(MP_QSTR_FRAME_FHD), MP_ROM_INT(FRAMESIZE_FHD) }, + { MP_ROM_QSTR(MP_QSTR_FRAME_P_HD), MP_ROM_INT(FRAMESIZE_P_HD) }, + { MP_ROM_QSTR(MP_QSTR_FRAME_P_3MP), MP_ROM_INT(FRAMESIZE_P_3MP) }, + { MP_ROM_QSTR(MP_QSTR_FRAME_QXGA), MP_ROM_INT(FRAMESIZE_QXGA) }, + { MP_ROM_QSTR(MP_QSTR_FRAME_QHD), MP_ROM_INT(FRAMESIZE_QHD) }, + { MP_ROM_QSTR(MP_QSTR_FRAME_WQXGA), MP_ROM_INT(FRAMESIZE_WQXGA) }, + { MP_ROM_QSTR(MP_QSTR_FRAME_P_FHD), MP_ROM_INT(FRAMESIZE_P_FHD) }, + { MP_ROM_QSTR(MP_QSTR_FRAME_QSXGA), MP_ROM_INT(FRAMESIZE_QSXGA) }, + { MP_ROM_QSTR(MP_QSTR_FRAME_QSXGA), MP_ROM_INT(FRAMESIZE_QSXGA) }, + + { MP_ROM_QSTR(MP_QSTR_WB_NONE), MP_ROM_INT(WB_NONE) }, + { MP_ROM_QSTR(MP_QSTR_WB_SUNNY), MP_ROM_INT(WB_SUNNY) }, + { MP_ROM_QSTR(MP_QSTR_WB_CLOUDY), MP_ROM_INT(WB_CLOUDY) }, + { MP_ROM_QSTR(MP_QSTR_WB_OFFICE), MP_ROM_INT(WB_OFFICE) }, + { MP_ROM_QSTR(MP_QSTR_WB_HOME), MP_ROM_INT(WB_HOME) }, + + { MP_ROM_QSTR(MP_QSTR_EFFECT_NONE), MP_ROM_INT(EFFECT_NONE) }, + { MP_ROM_QSTR(MP_QSTR_EFFECT_NEG), MP_ROM_INT(EFFECT_NEG) }, + { MP_ROM_QSTR(MP_QSTR_EFFECT_BW), MP_ROM_INT(EFFECT_BW) }, + { MP_ROM_QSTR(MP_QSTR_EFFECT_RED), MP_ROM_INT(EFFECT_RED) }, + { MP_ROM_QSTR(MP_QSTR_EFFECT_GREEN), MP_ROM_INT(EFFECT_GREEN) }, + { MP_ROM_QSTR(MP_QSTR_EFFECT_BLUE), MP_ROM_INT(EFFECT_BLUE) }, + { MP_ROM_QSTR(MP_QSTR_EFFECT_RETRO), MP_ROM_INT(EFFECT_RETRO) }, + + { MP_ROM_QSTR(MP_QSTR_XCLK_10MHz), MP_ROM_INT(XCLK_FREQ_10MHz) }, + { MP_ROM_QSTR(MP_QSTR_XCLK_20MHz), MP_ROM_INT(XCLK_FREQ_20MHz) }, + + { MP_ROM_QSTR(MP_QSTR_DRAM), MP_ROM_INT(CAMERA_FB_IN_DRAM) }, + { MP_ROM_QSTR(MP_QSTR_PSRAM), MP_ROM_INT(CAMERA_FB_IN_PSRAM) }, + +}; + +STATIC MP_DEFINE_CONST_DICT(camera_module_globals, camera_module_globals_table); + +const mp_obj_module_t mp_module_camera_system = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&camera_module_globals, +}; + +MP_REGISTER_MODULE(MP_QSTR_camera, mp_module_camera_system); + + +#endif \ No newline at end of file diff --git a/dispositivos/esp32-cam/micropython-camera-driver/src/modcamera.h b/dispositivos/esp32-cam/micropython-camera-driver/src/modcamera.h new file mode 100644 index 0000000..ce9c22b --- /dev/null +++ b/dispositivos/esp32-cam/micropython-camera-driver/src/modcamera.h @@ -0,0 +1,62 @@ +/* + * Copyright [2021] Mauro Riva + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MICROPY_INCLUDED_ESP32_MODCAMERA_H +#define MICROPY_INCLUDED_ESP32_MODCAMERA_H + +enum { OV2640, OV7725}; + +#define TAG "camera" + +//WROVER-KIT PIN Map +#define CAM_PIN_PWDN 32 //power down is not used +#define CAM_PIN_RESET -1 //software reset will be performed +#define CAM_PIN_XCLK 0 +#define CAM_PIN_SIOD 26 // SDA +#define CAM_PIN_SIOC 27 // SCL + +#define CAM_PIN_D7 35 +#define CAM_PIN_D6 34 +#define CAM_PIN_D5 39 +#define CAM_PIN_D4 36 +#define CAM_PIN_D3 21 +#define CAM_PIN_D2 19 +#define CAM_PIN_D1 18 +#define CAM_PIN_D0 5 +#define CAM_PIN_VSYNC 25 +#define CAM_PIN_HREF 23 +#define CAM_PIN_PCLK 22 +#define XCLK_FREQ_10MHz 10000000 +#define XCLK_FREQ_20MHz 20000000 + +//White Balance +#define WB_NONE 0 +#define WB_SUNNY 1 +#define WB_CLOUDY 2 +#define WB_OFFICE 3 +#define WB_HOME 4 + +//Special Effect +#define EFFECT_NONE 0 +#define EFFECT_NEG 1 +#define EFFECT_BW 2 +#define EFFECT_RED 3 +#define EFFECT_GREEN 4 +#define EFFECT_BLUE 5 +#define EFFECT_RETRO 6 + + +#endif diff --git a/dispositivos/esp32-cam/process.py b/dispositivos/esp32-cam/process.py new file mode 100644 index 0000000..4c0470f --- /dev/null +++ b/dispositivos/esp32-cam/process.py @@ -0,0 +1,45 @@ +# Detección de Colores con MicroPython +# +# Para realizar la detección de colores, puedes usar técnicas básicas de procesamiento +# de imágenes. Aquí hay un ejemplo simple para detectar un color específico en la imagen. +# Capturar y Procesar la Imagen: + +import esp +import machine +import time +import camera +import ustruct +import gc + +# Inicializar la cámara +camera.init(0, format=camera.GRAYSCALE, fb_location=camera.PSRAM) + +# Capturar una imagen +buf = camera.capture() + +# Procesar la imagen +def detect_color(image, threshold): + width = 320 # Asumiendo una resolución de 320x240 + height = 240 + count = 0 + + for y in range(height): + for x in range(width): + # Obtener el índice del píxel + index = y * width + x + pixel = image[index] + + # Verificar si el píxel está dentro del umbral de color + if pixel > threshold: + count += 1 + + return count + +# Configurar un umbral para la detección de color +color_threshold = 200 +detected_pixels = detect_color(buf, color_threshold) + +print("Número de píxeles detectados:", detected_pixels) + +# Finalizar la cámara +camera.deinit()