Arducam 2MP Plus Rev B slow power-up, I2C sensor register errors on ESP32

Hi everyone, running into a strange power-up timing issue with the newer Arducam 2MP Plus modules (Rev B, EtronTech chip, OV2640) and could really use some pointers.

On the older Mini 2 Plus Rev A (Winbond chip) I only need about 3ms of power-up delay before I2C comms are reliable. On the Rev B EtronTech boards I need ~30-40ms, and a couple of modules need up to 100ms before the “error writing to the sensor registers” message goes away. That is roughly 10x slower on the newer revision.

I tested 115 of the Rev B cameras: 5 of them needed up to 37ms and one needed up to 100ms. That spread is a real firmware headache because the delay isn’t consistent.

Concretely, myCAM.wrSensorReg8_8(0xff, 0x01) (select bank 1) returns an error on the Rev B modules but works fine on the earlier versions.

Two other questions while I’m here:

  1. For the Rev B board, is there a particular SPI or I2C waveform I should be scoping when debugging this?
  2. Could someone give me the command sequence / example for the “Windowing” function described on Page 3 of the OV2640 datasheet (v1.6, Feb 28 2006)? It references setting HREFST, HREFEND, REG32, VSTRT, VEND and COM1, and I’m not sure where in the library sequence that belongs.

Thanks!

Thanks for the detailed report, this lines up with a timing characteristic we’ve seen on the Rev B / EtronTech boards. Before I go too deep, can you share your full setup? Specifically the exact camera revisions, the library version, the platform/MCU, and how you’re powering the module (the power switching matters a lot here).

Sure, here’s the setup:

  • Cameras: Arducam 2MP Plus Rev B (EtronTech chip, OV2640) and Mini 2 Plus Rev A (Winbond chip, OV2640). I also have some of the earlier original Arducam MINI 2 and MINI 2 Plus boards.
  • Sensor: Omnivision OV2640 (datasheet Version 1.6, February 28, 2006)
  • Library: Arducam library v1.0.0
  • Platform: ESP32 / FreeRTOS (using vTaskDelay, xSemaphoreTake, ESP_LOGE) with Arduino Wire for I2C
  • Camera VCC is switched from a 3.3v supply using a mosfet controlled by the CAMERA_PWR pin (active low)
  • I2C address of the OV2640 is 0x60>>1
  • I2C clock speed is set by I2CCLKSPD; I’m referencing both the SPI and I2C interfaces
  • System occasionally captures an image, otherwise hardware powers-down the camera module to save power

Perfect, that helps. Can you paste the exact power-up / I2C init code you’re using, plus the block where the sensor register write fails? I want to see the ordering of Wire.begin, the dummy transmission and the delay.

Here’s the power-up / I2C init sequence:

digitalWrite(CAMERA_PWR, CAMERA_ON);  // turn on Camera module (active low)
vTaskDelay(CAMERA_PWR_UP_DELAY);  // needs to be significant, 3mS is not sufficient since Rev B EtronTech Arducam 2.0MP+

//Correct I2C arbitration loss that occurs during any power cycle
Wire.begin(SDA, SCL, I2CCLKSPD);  // start up the I2C again
Wire.beginTransmission(0x60>>1);  // the address of the OV2640
Wire.endTransmission(); // finish a dummy transmission

Thanks. And the fuller init block — the one with the semaphore and the camera init calls? I’d like to see exactly where wrSensorReg8_8(0xff, 0x01) sits relative to InitCAM() and the format setup.

Here’s the full block:

digitalWrite(CAMERA_PWR, CAMERA_ON);  // turn on Camera module (active low)
vTaskDelay(CAMERA_PWR_UP_DELAY); // allow camera i2C to settle before writing; 3mS about right

if (xSemaphoreTake(I2CGatekeeper, 100)) { // grab access to the I2C bus

//Hack to correct I2C arbitration loss that sometimes occurs after power-up
Wire.begin(SDA, SCL, I2CCLKSPD);  // start up the I2C again
Wire.beginTransmission(0x60>>1);  // the address of the OV2640
Wire.endTransmission(); // finish a dummy transmission

  //Change to JPEG capture mode and initialize the  module
  myCAM.clear_bit(ARDUCHIP_GPIO, GPIO_PWDN_MASK); //disable low power
  myCAM.set_format(JPEG);
  myCAM.InitCAM();
  myCAM.OV2640_set_JPEG_size(OV2640_640x480);
  myCAM.flush_fifo();
  myCAM.clear_fifo_flag();
  if (!myCAM.wrSensorReg8_8(0xff, 0x01)) ESP_LOGE(TAG,"Error setting camera bank1"); // set to sensor bank1 of registers <<<<< FAILs to write sensor registers here
    ...
  }

The sensor register write is what’s failing when the delay is too short.

Got it. One alternative worth testing while we sort out the delay requirement: instead of fully removing power to the module, keep the main chip powered and use the camera’s low power mode via the PWDN mask. Something like:

myCAM.set_bit(ARDUCHIP_GPIO,GPIO_PWDN_MASK);  // make camera come into low power mode
myCAM.clear_bit(ARDUCHIP_GPIO,GPIO_PWDN_MASK);  // exit low power mode

That avoids a full power cycle each time and might sidestep the arbitration/settling issue. Can you also paste the logs you’re seeing, and what you’ve tried so far with the delay?

Here’s what the logs show and what I’ve tried:

Logs:

  • ESP_LOGE(TAG,"Error setting camera bank1") fires because myCAM.wrSensorReg8_8(0xff, 0x01) fails to write sensor registers.
  • I get I2C failure messages until CAMERA_PWR_UP_DELAY is increased (up to 100ms for some modules).

Attempts:

  • Varied CAMERA_PWR_UP_DELAY until the I2C failure messages disappeared. Rev B EtronTech V2 cameras mostly need about 30-40ms, some up to 100ms, before reliably communicating over I2C.
  • Tried 3ms, also tried 10ms — no difference, still get the error writing myCAM.wrSensorReg8_8(0xff, 0x01).
  • Added the I2C dummy transmission (Wire.beginTransmission(0x60>>1) / endTransmission) to correct I2C arbitration loss / miscolouration after power-up, and re-issue Wire.begin(SDA, SCL, I2CCLKSPD).
  • Compared against the Rev A 2.0 Plus (Winbond chip) which needs only about 2-3ms for reliable I2C comms doing the same process.
  • Considered keeping the main chip powered on and using low power mode (GPIO_PWDN_MASK set/clear) as an alternative.

Note: the dummy write was removed when going from Arducam Mini 2MP to Mini 2MP Plus versions; the delay issue seems separate — Rev B EtronTech powers up roughly 10x slower than the Mini 2 Plus Winbond.

A few extra questions: (1) Are the new boards compatible with the Arducam Mini 2.0MP+? (2) Are the pinouts the same? (3) Are the SPI/I2C speeds the same or better? (4) Do I need a different version of the Arducam library or any change in the example code?

On the waveform question: please refer to our timing documentation here — Detailed Data Timing on Arducam SPI Bus - Arducam Wiki . There are two timing figures embedded in that page that illustrate the data/timing on the bus; use those as the reference for what to scope.

For context on the rest of the thread: the Rev B (EtronTech chip) Arducam 2MP Plus cameras power up slower than the Rev A (Winbond chip) version, which is exactly what causes the I2C write failures when CAMERA_PWR_UP_DELAY is too short.

On root cause — this is expected behavior for the new revision. The Rev B cameras replaced the chip and updated the firmware, and the initialization time went up accordingly. The main control chip was adjusted, so it takes a certain amount of time to load when powered on. That’s what leads to the longer power-up delay, and the delay time isn’t well controlled by the firmware on the older library.

So: Rev B (EtronTech) needs a longer CAMERA_PWR_UP_DELAY before it will reliably talk over I2C to set the camera registers — mostly ~30-40ms, some up to 100ms — versus ~2-3ms for Rev A (Winbond).

That explains the spread I was seeing. Is there any way to get this fixed in firmware rather than having to bump the delay so high? Also, could a firmware update be done locally via a suitable I2C/SPI interface, or does it require something else?

Good news — we deep-dived the firmware and updated it. After the firmware update, the delay that can be controlled is around 50ms. If a 50ms delay is acceptable for your application, we can update the firmware for you and send the package through private message so you can flash it and try.

For the SPI/I2C waveform question, use the Arducam documentation link above. For cutting/windowing the image, focus on the relevant OV2640 registers (more on that below).

50ms would be fine on my end. For the windowing — can you lay out the actual sequence? I want to make sure I put it in the right spot in the library flow.

To do the “Windowing” function (Page 3 of the Omnivision OV2640 datasheet, Version 1.6, February 28, 2006), the registers you care about are HREFST, HREFEND, REG32, VSTRT, VEND and COM1. Set those to define your crop window before you set the output size.

For the power-up path, keep the delay and the arbitration-loss correction together:

digitalWrite(CAMERA_PWR, CAMERA_ON);       // turn on Camera module (active low)
vTaskDelay(CAMERA_PWR_UP_DELAY);           // needs to be significant, 3mS is not sufficient since Rev B EtronTech Arducam 2.0MP+

Then correct the I2C arbitration loss that occurs during any power cycle:

Wire.begin(SDA, SCL, I2CCLKSPD);           // start up the I2C again
Wire.beginTransmission(0x60>>1);           // the address of the OV2640
Wire.endTransmission();                    // finish a dummy transmission

Then vary CAMERA_PWR_UP_DELAY until the I2C failure messages no longer occur.

If you’d rather avoid the full power cycle, use the low power mode by keeping the main chip powered on:

myCAM.set_bit(ARDUCHIP_GPIO, GPIO_PWDN_MASK);   // enter low power mode
myCAM.clear_bit(ARDUCHIP_GPIO, GPIO_PWDN_MASK); // exit low power mode

Your capture sequence stays the same once the bus is settled:

myCAM.clear_bit(ARDUCHIP_GPIO, GPIO_PWDN_MASK); // disable low power
myCAM.set_format(JPEG);
myCAM.InitCAM();
myCAM.OV2640_set_JPEG_size(OV2640_640x480);
myCAM.flush_fifo();
myCAM.clear_fifo_flag();
if (!myCAM.wrSensorReg8_8(0xff, 0x01)) ESP_LOGE(TAG,"Error setting camera bank1"); // set to sensor bank1 of registers

One more alternative worth a look if you need more headroom: our mega camera — https://www.arducam.com/camera-for-any-microcontroller/

Quick recap of where this landed:

  • Symptom: myCAM.wrSensorReg8_8(0xff, 0x01) (select bank 1) returns an error on Rev B (EtronTech) cameras when only 3ms/10ms of delay follows power-up. It works fine on the earlier Rev A (Winbond) versions.
  • Root cause: Rev B replaced the chip and updated the firmware, which increased the initialization/load time. It needs roughly 40-50ms before the sensor register write error goes away.
  • Firmware: our updated firmware brings the controllable delay to ~50ms. If 50ms is acceptable, flash the package I’ll send privately and retest.
  • Windowing: focus on HREFST, HREFEND, REG32, VSTRT, VEND and COM1.
  • Workaround if you want to avoid power cycling: keep the main chip powered and toggle slow power mode via GPIO_PWDN_MASK set/clear, and keep the dummy I2C transmission to clear the post-power-cycle arbitration loss.

Start by settling the bus (increase the delay / vary it until the I2C errors stop), then run the standard capture sequence. Let me know how the 50ms firmware behaves on your batch and I’ll follow up.