mocleiri / tensorflow-micropython-examples

A custom micropython firmware integrating tensorflow lite for microcontrollers and ulab to implement the tensorflow micro examples.
MIT License
170 stars 79 forks source link

added esp32-cam board #64

Closed uraich closed 2 years ago

uraich commented 2 years ago

This needs the esp32-camera component to be installed: https://github.com/espressif/esp32-camera I added the micropython interface to this driver to micropython-modules and modified the micropython.cmake file to include the module. The main.c file in ports/esp32 must be modified. You find the diff file in boards/esp32/MICROLITE_ESP32-CAM/esp32_main.patch

mocleiri commented 2 years ago

Thanks for this pull request.

I'm digesting how to best integrate it. I think I will try to use as much as I can from what your request and then we can file future work to try and upstream the different customizations and then tie into the regular upstream versions.

The complexity comes from the use of either internal RAM or SPRAM by the esp-camera driver because most available memory is already pre-allocated/acquired by micropython for its heap.

The changes to micropython/ports/esp32/main.c are all about shrinking the heap size acquired by micropython to leave space to be acquired by the esp-camera code.

In the stm32 port I borrowed the xalloc functions from openmv which allow allocating memory from the micropython heap through functions very similar to malloc and free.

One approach could be to fork the esp-camera component and adjust the memory allocation calls to use xalloc.

Another could be to make a more consistent way to reduce the heap size and make it board configurable and try to get that into the upstream micropython.

esp-camera also has options to configure I2S with DMA for acquiring the framebuffer faster. I wonder what changes are needed to have machine.I2S handle the I2S DMA part of the video frame capture.

The first approach I'm going to take is to try and not make the micropython main.c changes. Since 96x96 is about the smallest resolution you can capture I want to see if it can run without the heap shrinking changes in micropython.

uraich commented 2 years ago

I fully agree with all you are saying. 96x96 is the smallest resolution you can have at least on the esp32-camera driver. In addition these are gray scale images reducing the memory size by another factor of 3 with respect to rgb images. I saw that there is a configuration option: CAMERA_FB_IN_DRAM in the esp32-camera driver, which allows to force image buffer allocation in internal RAM. This might do the trick if we stick to small images. In the TinyML book there is another example using accelerometers to detect certain gestures. I ordered a number of different accelerometers with the intention to make this example run on the ESP32.

mocleiri commented 2 years ago

Sorry for the delay in processing this. I've been trying to get an m5 timer camera to work using it. It's almost like the esp32-cam-mb except the sensor is an OV3660 and it has a usb-type C connector and can be programmed directly.

I can get the sensor to work with their test app but not using their idf example. Anyways its slowing me down to integrate your changes and I'm going to park it. I have some ov2640 sensors in the mail and then I'll also be able to debug if it doesn't work. The m5 timer camera doesn't break out pins to let me debug on chip.

I'm going to apply you changes almost exactly as filed except I'm going to try and apply a patch on upstream micropython/ports/esp32/main.c so I don't need to maintain my own fork.

I have a way to allow boards to make heap size adjustments and in this case use those special defines to half the heap size to 2MB leaving the other 2MB for the esp32-camera frame buffer.

mocleiri commented 2 years ago

I found out I misunderstood the 3 memory allocation models supported by esp32. Micropython defaults to using MMAP where it doesn't malloc anything to uses the SPRAM. For esp32-camera it needs to be able to use the idf malloc with capabilities to get ram for dma and also for the framebufffer.

I made a new way in micropython/ports/main.c to switch to allocating the micropython heap using malloc. Then we shrink its size by 512 kb and that provides enough space for the person detection example.

The upstream driver example shrinks the sp ram allocated to micropython by half but the approach I have leaves it open to other boards customizing exactly how much of the PSRAM is allocated to micropython versus other purposes.

With these changes I'm able to run your scripts to capture an example picture and also to run the person detection example.

camera.init(0,format=camera.GRAYSCALE,framesize=camera.FRAME_96X96,
                sioc=23,siod=25,xclk=27,vsync=22,href=26,pclk=21,
                d0=32,d1=35,d2=34,d3=5,d4=39,d5=18,d6=36,d7=19,
                reset=15)

I'm using the esp32-camera module from the Espressif tflm examples repo I'm working to integrate in #9 so I will plan to merge that first and then this.

uraich commented 2 years ago

In fact I also used the standard esp32-camera module from Espressif and I think I shrank the sp ram by 256kB or 512 kB only. I will try your version as soon as it is merged. In the meantime I am trying to learn more about ML in general and I want to test the audio example. It would be nice if I would manage to run this also on the esp32-cam.

mocleiri commented 2 years ago

I applied these changes as part of a feature branch on #59

Its not building using CI yet but I hope soon.