3

I have working code on an Ai-Thinker ESP32-CAM board, programming over serial.

I would like to reprogram using OTA, but adding in the functionality from the BasicOTA sketch (which I have done on various other boards successfully) fails when OTA programming is attempted, the board reboots following an abort() and a stack trace is generated.

The invaluable ESP32 exception decoder shows the fault occurs from checking if memory location is safe to write.

Normally, I would choose a partition option which includes OTA, but the Ai-Thinker board doesn't have this option in the IDE

5 Answers 5

2

The boards.txt file configures what can be configured in the Arduino IDE for each board.

On my installation, this is found at C:\Users\MyUser\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.4\boards.txt

I found the section esp32cam.name=AI Thinker ESP32-CAM and changed the lines:

esp32cam.upload.maximum_size=3145728
esp32cam.build.partitions=huge_app

to

esp32cam.upload.maximum_size=1966080
esp32cam.build.partitions=min_spiffs

The various options are detailed in the same file with keys named esp32.menu.PartitionScheme., and for some boards these options are configurable be the user. To add this, remove (or comment out with a # character) the two lines found above so they look like:

# esp32cam.upload.maximum_size=3145728
# esp32cam.build.partitions=huge_app

and add the required menu selections for your application- e.g.

esp32cam.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS)
esp32cam.menu.PartitionScheme.huge_app.build.partitions=huge_app
esp32cam.menu.PartitionScheme.huge_app.upload.maximum_size=3145728
esp32cam.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (Large APPS with OTA)
esp32cam.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs
esp32cam.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080

After making any changes to boards.txt, restart the Arduino IDE for the change to take effect. Note that these changes (and any changes to the installation) may be overwritten by any future upgrades or library updates, so note your changes so they can be easily reapplied.

Alternatively, add the menu lines to boards.local.txt, introduced in Arduino 1.6.6 so they should persist during updates. In this case, no change needs to be made to boards.txt, as the boards.local.txt entries override those in boards.txt. I haven't tested this, hopefully it works across library updates and IDE upgrades.

2

You do not have to go through the hassle with editing the boards.txt if you want to have OTA only if you do not need it or you want a custom partition scheme.
That said the OTA partition is always what is left so e.g. Med Spiffs App 1.9MB, Spiffs 190KB means 1.9 MB OTA partiton.
The caveat is if you want to OTA a 1.8 MB App with 1 MB Spiffs that will NOT work. The OTA file has to be around 100kb (from experience) smaller than the availabe OTA partition. If you want to update APP and SPIFFS thats a topic on its own. So before editing your boards.txt check the following:

  • App (uncompressed) is OTA space + ~100KB
  • your OTA routine runs stable with/in small apps
  • no connection problems during upload and
  • proper OTA error handling in your code
  • for initial testing attach no hardware to the board.
  • If using the unmodified camera example or a custom on with face recognition you will fail with OTA because this is to big (~3MB APP!)
  • OTA routines (incl wifi libs) take ~800 kB for basic OTA

As I use AIThinker32cam modules in various scenarios I know what you are through ;-)
Enclosed two custom board definitions (with no OTA) as there is no predefined (ESP32 core 1.04) in C:\Users\YOUR_USERNAME\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.4\boards.txt just copy and paste into the section (search for esp32AiThinkerCam.menu.PartitionScheme :

esp32AiThinkerCam.menu.PartitionScheme.noota_3g=1MB APP/3MB SPIFFS (No OTA)
esp32AiThinkerCam.menu.PartitionScheme.noota_3g.build.partitions=noota_3g
esp32AiThinkerCam.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576
esp32AiThinkerCam.menu.PartitionScheme.no_ota=2MB APP/2MB SPIFFS (No OTA)
esp32AiThinkerCam.menu.PartitionScheme.no_ota.build.partitions=no_ota
esp32AiThinkerCam.menu.PartitionScheme.no_ota.upload.maximum_size=2097152

and the "magic unlocker" is the noota_3g.csv found in C:\Users\YOUR_USERNAME\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.4\tools\partitions,there the partition scheme isdefined. If you want to change that for custom partitions please ask a new question.
EDIT
Enclosed acomplete boards.txt part for AI-Thinker just replace the complete existing part with this amd you have a bunch of new options - all tested in production with ESP32 core 1.04. (without custom partition schemes):

##############################################################

esp32AiThinkerCam.name=ESP32 AI Thinker Cam

esp32AiThinkerCam.upload.tool=esptool_py
esp32AiThinkerCam.upload.maximum_size=1310720
esp32AiThinkerCam.upload.maximum_data_size=327680
esp32AiThinkerCam.upload.wait_for_upload_port=true

esp32AiThinkerCam.serial.disableDTR=true
esp32AiThinkerCam.serial.disableRTS=true

esp32AiThinkerCam.build.mcu=esp32
esp32AiThinkerCam.build.core=esp32
esp32AiThinkerCam.build.variant=esp32
esp32AiThinkerCam.build.board=ESP32_DEV

esp32AiThinkerCam.build.f_cpu=240000000L
esp32AiThinkerCam.build.flash_size=4MB
esp32AiThinkerCam.build.flash_freq=40m
esp32AiThinkerCam.build.flash_mode=dio
esp32AiThinkerCam.build.boot=dio

esp32AiThinkerCam.menu.CPUFreq.240=240MHz (WiFi/BT)
esp32AiThinkerCam.menu.CPUFreq.240.build.f_cpu=240000000L
esp32AiThinkerCam.menu.CPUFreq.160=160MHz (WiFi/BT)
esp32AiThinkerCam.menu.CPUFreq.160.build.f_cpu=160000000L
esp32AiThinkerCam.menu.CPUFreq.80=80MHz (WiFi/BT)
esp32AiThinkerCam.menu.CPUFreq.80.build.f_cpu=80000000L

esp32AiThinkerCam.build.partitions=default
esp32AiThinkerCam.build.defines=-DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue
esp32AiThinkerCam.menu.PartitionScheme.default=Default 1.2MB APP/1.5MB SPIFFS (OTA)
esp32AiThinkerCam.menu.PartitionScheme.default.build.partitions=default
esp32AiThinkerCam.menu.PartitionScheme.defaultffat=Default FATFS 1.2MB APP/1.5MB FATFS (OTA)
esp32AiThinkerCam.menu.PartitionScheme.defaultffat.build.partitions=default_ffat
esp32AiThinkerCam.menu.PartitionScheme.noota_3g=1MB APP/3MB SPIFFS (No OTA)
esp32AiThinkerCam.menu.PartitionScheme.noota_3g.build.partitions=noota_3g
esp32AiThinkerCam.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576
esp32AiThinkerCam.menu.PartitionScheme.no_ota=2MB APP/2MB SPIFFS (No OTA)
esp32AiThinkerCam.menu.PartitionScheme.no_ota.build.partitions=no_ota
esp32AiThinkerCam.menu.PartitionScheme.no_ota.upload.maximum_size=2097152
esp32AiThinkerCam.menu.PartitionScheme.huge_app=3MB APP/1MB SPIFFS (No OTA)
esp32AiThinkerCam.menu.PartitionScheme.huge_app.build.partitions=huge_app
esp32AiThinkerCam.menu.PartitionScheme.huge_app.upload.maximum_size=3145728
esp32AiThinkerCam.menu.PartitionScheme.noota_ffat=2MB APP/2MB FATFS (No OTA)
esp32AiThinkerCam.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat
esp32AiThinkerCam.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152
esp32AiThinkerCam.menu.PartitionScheme.noota_3gffat=1MB APP/3MB FATFS (No OTA)
esp32AiThinkerCam.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat
esp32AiThinkerCam.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576
esp32AiThinkerCam.menu.PartitionScheme.minimal=Min SPIFFS 1.3MB APP/700KB SPIFFS (OTA)
esp32AiThinkerCam.menu.PartitionScheme.minimal.build.partitions=minimal
esp32AiThinkerCam.menu.PartitionScheme.min_spiffs=Med SPIFFS 1.9MB APP/190KB SPIFFS (OTA)
esp32AiThinkerCam.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs
esp32AiThinkerCam.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080


esp32AiThinkerCam.menu.FlashMode.qio=QIO
esp32AiThinkerCam.menu.FlashMode.qio.build.flash_mode=dio
esp32AiThinkerCam.menu.FlashMode.qio.build.boot=qio
esp32AiThinkerCam.menu.FlashMode.dio=DIO
esp32AiThinkerCam.menu.FlashMode.dio.build.flash_mode=dio
esp32AiThinkerCam.menu.FlashMode.dio.build.boot=dio
esp32AiThinkerCam.menu.FlashMode.qout=QOUT
esp32AiThinkerCam.menu.FlashMode.qout.build.flash_mode=dout
esp32AiThinkerCam.menu.FlashMode.qout.build.boot=qout
esp32AiThinkerCam.menu.FlashMode.dout=DOUT
esp32AiThinkerCam.menu.FlashMode.dout.build.flash_mode=dout
esp32AiThinkerCam.menu.FlashMode.dout.build.boot=dout

esp32AiThinkerCam.menu.FlashFreq.80=80MHz
esp32AiThinkerCam.menu.FlashFreq.80.build.flash_freq=80m
esp32AiThinkerCam.menu.FlashFreq.40=40MHz
esp32AiThinkerCam.menu.FlashFreq.40.build.flash_freq=40m

esp32AiThinkerCam.menu.UploadSpeed.921600=921600
esp32AiThinkerCam.menu.UploadSpeed.921600.upload.speed=921600
esp32AiThinkerCam.menu.UploadSpeed.115200=115200
esp32AiThinkerCam.menu.UploadSpeed.115200.upload.speed=115200
esp32AiThinkerCam.menu.UploadSpeed.256000.windows=256000
esp32AiThinkerCam.menu.UploadSpeed.256000.upload.speed=256000
esp32AiThinkerCam.menu.UploadSpeed.230400.windows.upload.speed=256000
esp32AiThinkerCam.menu.UploadSpeed.230400=230400
esp32AiThinkerCam.menu.UploadSpeed.230400.upload.speed=230400
esp32AiThinkerCam.menu.UploadSpeed.460800.linux=460800
esp32AiThinkerCam.menu.UploadSpeed.460800.macosx=460800
esp32AiThinkerCam.menu.UploadSpeed.460800.upload.speed=460800
esp32AiThinkerCam.menu.UploadSpeed.512000.windows=512000
esp32AiThinkerCam.menu.UploadSpeed.512000.upload.speed=512000

esp32AiThinkerCam.menu.DebugLevel.none=None
esp32AiThinkerCam.menu.DebugLevel.none.build.code_debug=0
esp32AiThinkerCam.menu.DebugLevel.error=Error
esp32AiThinkerCam.menu.DebugLevel.error.build.code_debug=1
esp32AiThinkerCam.menu.DebugLevel.warn=Warn
esp32AiThinkerCam.menu.DebugLevel.warn.build.code_debug=2
esp32AiThinkerCam.menu.DebugLevel.info=Info
esp32AiThinkerCam.menu.DebugLevel.info.build.code_debug=3
esp32AiThinkerCam.menu.DebugLevel.debug=Debug
esp32AiThinkerCam.menu.DebugLevel.debug.build.code_debug=4
esp32AiThinkerCam.menu.DebugLevel.verbose=Verbose
esp32AiThinkerCam.menu.DebugLevel.verbose.build.code_debug=5
6
  • Thanks for the extra information, +1 for the detail. However the originally set huge_app setting for this board doesn't seem to leave any space for OTA (3MB app). I am using a small SPIFFS partition but that doesn't change the setting in boards.txt.
    – rolinger
    Apr 28, 2020 at 9:05
  • As I wrote the huge App 3MB can not be OTAed - there is nospace left toOTA you can use max 1.8MB APP or get a board with 8MB PSRAM - thats a hardware limitation not a software - try with med asgiven in y text - if your App is larger reduce it or no OTA Apr 28, 2020 at 9:17
  • huge_app is the fixed default for this board in the supplied boards.txt, which doesn't allow OTA as we both agree. It doesn't have a configurable option to choose min_spiffs, that's what I add below, maybe this is different from your installed esp32 boards.txt?
    – rolinger
    Apr 28, 2020 at 11:24
  • Sorry for the misunderstanding - choose ESP32 Wrover Module and use it for the Ai Thinker32Cam to flash, if you want to have an own menu copy the new part I posted above to your boards txt Apr 28, 2020 at 11:49
  • Thanks for clarifying, I didn't know the Wrover and Ai-Thinker boards were interchangeable for programming, so that would be an alternative workaround in this case. Note for others who may be following - camera pinouts are different between the Wrover and Ai-Thinker modules (see camera_pins.h in the CameraWebServer example).
    – rolinger
    Apr 28, 2020 at 12:19
1

As stated in the comments by @Codebreaker007 using the ESP32 Wrover Module works and if you put the pin definitions inline in the app there isn't a problem

#define CAMERA_MODEL_AI_THINKER

#if defined(CAMERA_MODEL_AI_THINKER)
  #define PWDN_GPIO_NUM     32
  #define RESET_GPIO_NUM    -1
  #define XCLK_GPIO_NUM      0
  #define SIOD_GPIO_NUM     26
  #define SIOC_GPIO_NUM     27
  
  #define Y9_GPIO_NUM       35
  #define Y8_GPIO_NUM       34
  #define Y7_GPIO_NUM       39
  #define Y6_GPIO_NUM       36
  #define Y5_GPIO_NUM       21
  #define Y4_GPIO_NUM       19
  #define Y3_GPIO_NUM       18
  #define Y2_GPIO_NUM        5
  #define VSYNC_GPIO_NUM    25
  #define HREF_GPIO_NUM     23
  #define PCLK_GPIO_NUM     22
#else
  #error "Camera model not selected"
#endif
0

Here.

Download this working ESP32-CAM sketch zip file with working OTA uploading: "Working_ESP32_CameraWebServer_V2_with_OTA"

at

https://github.com/wjsanek/wjsanek.git

Make sure you read the simple "READ ME FIRST" file in the zip after unzipping.

This sketch overcomes any "file to big" or other OTA sketch uploading problems with this crumby, tempremental ESP32-CAM board (the $5 ESP8266 NodeMCU is better but the Arducam camera for it costs $23).

The ESP32-CAM board does not like to transmit very far.

0

OTA Requires you to partition your ESP32 with two sets of space for your program (ota_0 and ota_1 partitions) - during the OTA process, the unused one gets updated, and will be the next one that boots up.

This means that there's no room left for the camera (most camera driver libraries store the image in SPIFFS) to store the image data (OV2640 is 1622x1200 pixels, which is 1946400 bytes) because the only available partition schemes with OTA in Arduino IDE is 1.9mb program with 0.19mb (190kb) SPIFFs, which is 10-times-not-enough space to store camera images in.

the wjsanek project in here looks interesting - they're using one of the OTA partitions as the SPIFF for the camera. Very clever.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.