I don't really have the proper gear to test and verify my modifications to an USB cable with type C connectors. Flying blind, I knew there was a good chance I would fry something. I dug through my pile of electronics for the cheapest thing I have with an USB-C socket, which turned out to be a M5Stack ESP32 Camera.

I got this particular module as an add-on to the conference badge for Layer One 2019 as documented on Hackaday. It's been gathering dust ever since, waiting for a project that needed a little camera driven by an ESP32. For conference badge purposes it ran code from this repository, which also pointed to resources that helped me find the M5Stack ESP32Cam product documentation page.

The camera module is an OV2640, which is a very popular for electronics hobbyists and found in various boards like this one from ArduCam. If I want to do more work with ESP32+OV2640 I can find variations on this concept for less than $10 each. But M5Stack is at least a relatively name-brand item here, enough for this module to be explicitly described in ESPHome documentation. (Along with a warning about insufficient cooling in this design!)

Two notes about this ESP32Cam module that might not be present on other ESP32+OV2640 modules:

  1. There is a battery power management IC (IP5306) on board, making this an interesting candidate for projects if I want to run on a single lithium-ion battery cell and if I don't want to tear apart another USB power bank. I think it handles both charge safety and boost conversion for higher voltage. I don't know for sure because the only datasheets I've found so far are in Simplified Chinese and my reading comprehension isn't great.
  2. The circuit board included footprints for a few other optional IC components. (BMP280 temperature/pressure/humidity environmental sensor, MPU6050 3-axis accelerometer + 3-axis gyroscope, SPQ2410 microphone.) They are all absent from my particular module, but worth considering if they are ICs that would be useful for a particular project.
  3. There is a red LED next to the camera connected to pin 16. I used it as an ESPHome status light.

status_led:
  pin:
    number: 16

My first attempt to put ESPHome on this module was to compile a *.bin file for installation via https://web.esphome.io. Unfortunately, it doesn't seem to properly set up the flash memory for booting as the module gets stuck in an endless loop repeating this error:

rst:0x10 (RTCWDT_RTC_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
flash read err, 1000
ets_main.c 371 
ets Jun  8 2016 00:22:57

To work around this problem, I fired up an Ubuntu laptop and ran ESPHome docker container to access a hardware USB port for flashing. This method flashed successfully and the ESP32 was able to get online where I could make future updates over wireless.

A web search indicates an OV2640 has a native sensor resolution of 1632x1232. But the ESPHome camera component running on this module could only handle a maximum of 800x600 resolution. The picture quality was acceptable, but only about 2-3 frames per second gets pushed to Home Assistant. As expected, it is possible to trade resolution for framerate. The lowest resolution of 160x120 is very blurry but at least motion is smooth. If I try resolutions higher than 800x600, at bootup time I would see this error message in debug log:

[E][esp32_camera:095]:   Setup Failed: ESP_ERR_NO_MEM

This isn't great. But considering its price point of roughly ten bucks for a WiFi-enabled camera module, it's not terrible. This experiment was a fun detour before I return to my project of automated charging for a Pixel 3a phone.