Skip to content

Add support for Ai Thinker ESP32-CAM boards - #9231

Merged
tannewt merged 6 commits into
adafruit:mainfrom
gitcnd:add-board-ai-thinker-esp32-cam
May 15, 2024
Merged

Add support for Ai Thinker ESP32-CAM boards#9231
tannewt merged 6 commits into
adafruit:mainfrom
gitcnd:add-board-ai-thinker-esp32-cam

Conversation

@gitcnd

@gitcnd gitcnd commented May 9, 2024

Copy link
Copy Markdown

This adds support for the cheap-and-popular ESP32-CAM boards.

Board Feature			Circuitpython Status
=============                   ====================
Take photos with camera		Tested + Working
Mount SD card			Tested + Working
Wifi				Tested + Working
Inbuilt RED LED (back of board)	Tested + Working
Flashlight (front of board)	Tested + Working
ESP32-CAM-MB Button		Tested + Working
Bluetooth			Not tested
Others				There are no other features I know of

Here is my working sample script which tests the SD Card:

import board
import busio
import sdcardio
import storage

spi = board.SD_SPI()
cs = board.SD_CS

sdcard = sdcardio.SDCard(spi, cs)
vfs = storage.VfsFat(sdcard)
storage.mount(vfs, "/sd")

Here is my working sample script which takes a photo (and saves it to "out.jpg" in flash)

import io
import os
import board
import espcamera
import socketpool

cam = espcamera.Camera(
    data_pins=board.CAMERA_DATA,
    external_clock_pin=board.CAMERA_XCLK,
    pixel_clock_pin=board.CAMERA_PCLK,
    vsync_pin=board.CAMERA_VSYNC,
    href_pin=board.CAMERA_HREF,
    powerdown_pin=board.CAMERA_PWDN,
    reset_pin=None,
    i2c=board.I2C(),
    external_clock_frequency=20_000_000,
    pixel_format=espcamera.PixelFormat.JPEG,
    frame_size=espcamera.FrameSize.SVGA,
    # jpeg_quality=0,
    # framebuffer_count=0,
    # grab_mode=espcamera.GrabMode.WHEN_EMPTYi
    )

if True:
    frame = cam.take(1)
    fn="out.jpg"
    if isinstance(frame, memoryview):
        jpeg = frame
        print(f"Captured {len(jpeg)} bytes of jpeg data")

        if fn:
            with open(fn, 'wb') as f:
                f.write(jpeg)
            print(f"written to {fn}")
        else:
            print("not written - no filename given")

This is my first PR - if I've done anything wrong, please let me know, along with more-than-average details about what I'm supposed to do to fix it, thanks!

@RetiredWizard RetiredWizard left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It probably varies from board to board but you might consider adding aliases for the pins that are silk screened.i.e.:

    { MP_ROM_QSTR(MP_QSTR_SDIO_CLK), MP_ROM_PTR(&pin_GPIO14)},
    { MP_ROM_QSTR(MP_QSTR_IO14), MP_ROM_PTR(&pin_GPIO14)},

Comment thread ports/espressif/boards/ai-thinker-esp32-cam/pins.c
@RetiredWizard

Copy link
Copy Markdown

This may already be clear but since you said this was your first board, I just wanted to be sure... The silkscreen does show the actual GPIO names IO14, etc so a programmer can access them by those names using microcontroller.pin, although most CircuitPython users will be looking for the silk screen name in board.xxxx (board.IO14). In order to support that you would need to add a second line for each of the silk screened pins with both the logical name and the silk screened name.

    { MP_ROM_QSTR(MP_QSTR_SDIO_CLK), MP_ROM_PTR(&pin_GPIO14)},
    { MP_ROM_QSTR(MP_QSTR_IO14), MP_ROM_PTR(&pin_GPIO14)},

I'm pretty sure not all boards add this type of alias though.

@gitcnd

gitcnd commented May 9, 2024

Copy link
Copy Markdown
Author

... The silkscreen does show the actual GPIO names IO14, etc

I'm reluctant to introduce a whole pile of non-standard non-portable aliases simply to drop the leading "G" off everything (and waste memory and add confusion)... while I can see where circuitpython is going with that, I would very much prefer NOT to encourage that kind of thing. I'm working currently on the ESP32-WROVER-DEV board which (minus the SD card) is almost identical. Code written for either will run fine, unchanged, on the other... so long as people don't use silly pin names. The latter drops the "IO" prefix on its silkscreen, which will add a whole extra level of extreme confusion if I go down this route ...

  { MP_ROM_QSTR(MP_QSTR_16), MP_ROM_PTR(&pin_GPIO16) 

will resolve to an int instead of a string in those cases...

That said - I'm happy to keep you happy. This is my first time doing this stuff.

Update: You can't use numeric silkscreens:-

Adafruit CircuitPython 9.1.0-beta.1-18-g781c577745 on 2024-05-09; Espressif ESP32-WROVER-DEV with ESP32
>>> 
>>> import board
>>> dir(board)
['__class__', '__name__', '1', '3', 'BUTTON', 'CAMERA_DATA', 'CAMERA_DATA2', 'CAMERA_DATA3', 'CAMERA_DATA4', 'CAMERA_DATA5', 'CAMERA_DATA6', 'CAMERA_DATA7', 'CAMERA_DATA8', 'CAMERA_DATA9', 'CAMERA_HREF', 'CAMERA_PCLK', 'CAMERA_PWDN', 'CAMERA_SIOC', 'CAMERA_SIOD', 'CAMERA_VSYNC', 'CAMERA_XCLK', 'FLASHLIGHT', 'I2C', 'LED', 'LED_INVERTED', 'SCL', 'SDA', '__dict__', 'board_id']
>>> board.1
Traceback (most recent call last):
  File "<stdin>", line 1
SyntaxError: invalid syntax
>>> board.BUTTON
board.BUTTON
>>> 

@gitcnd

gitcnd commented May 9, 2024

Copy link
Copy Markdown
Author

Turns out a very large number of other ESP32 ports introduce IOnn aliases... so in the interests of letting those folks run their code unchanged on this port, I added the aliases.

@RetiredWizard RetiredWizard left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I loaded up the artifact from this PR and tested WiFi, SD Card, LED and Camera operations. I didn't find any issues other than the annoyingly bright "flashlight" led defaulting to on.

Comment thread ports/espressif/boards/ai-thinker-esp32-cam/board.c
@gitcnd

gitcnd commented May 10, 2024

Copy link
Copy Markdown
Author

FYI... More handy info about these boards is here: https://randomnerdtutorials.com/esp32-cam-ai-thinker-pinout/

@RetiredWizard

Copy link
Copy Markdown

I loaded up the artifact with the flashlight fix and everything seems good, no more bright light 😁

@RetiredWizard RetiredWizard left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good to me, I've done some basic testing and everything seems to work fine. I'm actually using the latest artifact in a project that allows me to snap a photo of the charge state of my solar batteries using adafruit.io. That allows me to turn on/off the inverter when I'm away from home depending on the charge state. I first tried using the Memento but ran into an issue so it was fortunate that this PR was in place 😁

@tannewt tannewt left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the testing @RetiredWizard and the PR @gitcnd

@bill88t

bill88t commented May 23, 2024

Copy link
Copy Markdown

@tannewt As a note, this board used - instead of _ for the spaces for the board name making it not a valid python identifier (Reminder, #6979 and #7267).

Is it too late to fix this one?

@tannewt

tannewt commented May 23, 2024

Copy link
Copy Markdown
Member

@tannewt As a note, this board used - instead of _ for the spaces for the board name making it not a valid python identifier (Reminder, #6979 and #7267).

Is it too late to fix this one?

I think the first step is adding a test that will fail if the board name isn't an id. Otherwise we'll continue to have this problem. After we have that, we can fix all the cases that need to be fixed.

@gitcnd

gitcnd commented May 23, 2024

Copy link
Copy Markdown
Author

Others:-

raytac_mdbt50q-db-40
raytac_mdbt50q-rx
TG-Watch
ai_thinker_esp32-c3s
ai_thinker_esp32-c3s-2m
ai-thinker-esp32-cam
beetle-esp32-c3
columbia-dsl-sensor
crcibernetica-ideaboard
lilygo_ttgo_t-01c3
lilygo_ttgo_t-oi-plus
morpheans_morphesp-240
zrichard_rp2.65-f
cp32-m4
kicksat-sprite
silicognition-m4-shim

@gitcnd

gitcnd commented May 23, 2024

Copy link
Copy Markdown
Author

@tannewt As a note, this board used - instead of _ for the spaces for the board name making it not a valid python identifier (Reminder, #6979 and #7267).

Is it too late to fix this one?

Why would it need to be a valid python identifier?

If someone wants this to be a rule and actually has a sensible reason why - all the board porting instructions need to be changed so that everyone knows this... it's actually quite confusing already - there's at least 3 names involved (a human name with spaces, some kind of identifier constructed from CIRCUITPY_CREATOR_ID and CIRCUITPY_CREATION_ID, and the folder name where the files live) - with none of this stuff being explained in the porting instructions...

Oh yeah - and there appear to be aliases for variants as well, also not explained I think.

@tannewt

tannewt commented May 24, 2024

Copy link
Copy Markdown
Member

@tannewt As a note, this board used - instead of _ for the spaces for the board name making it not a valid python identifier (Reminder, #6979 and #7267).
Is it too late to fix this one?

Why would it need to be a valid python identifier?

Some folks use the board id in a module name.

If someone wants this to be a rule and actually has a sensible reason why - all the board porting instructions need to be changed so that everyone knows this... it's actually quite confusing already - there's at least 3 names involved (a human name with spaces, some kind of identifier constructed from CIRCUITPY_CREATOR_ID and CIRCUITPY_CREATION_ID, and the folder name where the files live) - with none of this stuff being explained in the porting instructions...

Yes, agreed.

Oh yeah - and there appear to be aliases for variants as well, also not explained I think.

@gitcnd

gitcnd commented May 25, 2024

Copy link
Copy Markdown
Author

Some folks use the board id in a module name.

LOL - I was all fired up to argue against a "no hyphen" requirement because I couldn't think of any valid reason why... then you give a valid reason :-)

I'd estimate it's probably a days work to add the rule, fix the doc, and update all the boards currently using hyphens.

@dhalbert

Copy link
Copy Markdown
Collaborator

The board_id's are also used for https://circuitpython.org, so if you rename a board, you need to make that still work with both the 9.0.x and the 9.1.0 versions. There is a board_alias feature in the code for the website, but I'm not sure you can have more than one alias.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants