Capture time issue on Arducam OV5642 MINI 5MP Plus SPI camera modules

Hi, I have Arducam ov5652 Mini-5mp units.
I am preparing a demonstration of transferring images using wireless communication(Our product). But there are some problems.

Issues :

  1. ov5642 single captrue time take too long (320x240 in average about 230 ms). I want to send 10 single capture images per second. Is it possible to solve it?
    If I change from ov5642 to ov2640, can I improve the speed?
  2. I used FIFO_BURST, but sometimes I don’t get CAP_DONE_MASK and keep waiting.

code sample attached
void arducam_start_single_capture(void)
{
uint32_t start, end;
if(camera_left_bytes == 0) {
rtc_set_compare(RTC_ID_0, RTC_CCID_0, 32768 * 2 );
rtc_clr_count(RTC_ID_0);

arducam_flush_fifo();
arducam_clear_fifo_flag();

//Start capture
arducam_start_capture();
while(!arducam_get_bit(ARDUCHIP_TRIG, CAP_DONE_MASK))

camera_left_bytes = arducam_read_fifo_length();//
arducam_cs_low();
arducam_set_fifo_burst();
} else {
log_info(“arducam module busy\n”);
}
}

void arducam_init_cam(void)
{
sensor_model = OV5642;
sensor_addr = 0x78;

switch (sensor_model)
{
case OV5642:
{
arducam_wr_i2c_reg16_data8(0x3008, 0x80);
if (m_fmt == RAW) {
//Init and set 640x480;
arducam_wr_i2c_regs16_data8(OV5642_1280x960_RAW);
arducam_wr_i2c_regs16_data8(OV5642_640x480_RAW);
} else {
arducam_wr_i2c_regs16_data8(OV5642_QVGA_Preview);
SystemDelay(100);
if (m_fmt == JPEG)
{
SystemDelay(100);
arducam_wr_i2c_regs16_data8(OV5642_JPEG_Capture_QSXGA);
arducam_wr_i2c_regs16_data8(ov5642_320x240);
SystemDelay(100);
arducam_wr_i2c_reg16_data8(0x3818, 0xa8);
arducam_wr_i2c_reg16_data8(0x3621, 0x10);
arducam_wr_i2c_reg16_data8(0x4407, 0x0C);
arducam_wr_i2c_reg16_data8(0x5888, 0x00);
} else {
uint8_t reg_val;
arducam_wr_i2c_reg16_data8(0x4740, 0x21);
arducam_wr_i2c_reg16_data8(0x501e, 0x2a);
arducam_wr_i2c_reg16_data8(0x5002, 0xf8);
arducam_wr_i2c_reg16_data8(0x501f, 0x01);
arducam_wr_i2c_reg16_data8(0x4300, 0x61);
arducam_rd_i2c_reg16_data8(0x3818, &reg_val);
arducam_wr_i2c_reg16_data8(0x3818, (reg_val | 0x60) & 0xff);
arducam_rd_i2c_reg16_data8(0x3621, &reg_val);
arducam_wr_i2c_reg16_data8(0x3621, reg_val & 0xdf);
}
}
break;
}
}
}

void arducam_open(void)
{
// put your setup code here, to run once:
uint8_t vid, pid;
uint8_t temp = 0xFF;

// peri init
arducam_init_peri();

SystemDelay(1000);
log_info(“ARDUCAM Camera Start\n”);
// arducam_write_reg(0x07, 0x80);
// SystemDelay(100);
// arducam_write_reg(0x07, 0x00);
// SystemDelay(100);

// Check if the ArduCAM SPI bus is OK
arducam_write_reg(ARDUCHIP_TEST1, 0x55);
temp = arducam_read_reg(ARDUCHIP_TEST1);
if (temp != 0x55) {
log_info(“SPI interface non responsive\n”);
while(1);
}

#if (ARDUCAM_OV5642_MINI_5MP)
//Check if the camera module type is OV5642
arducam_wr_i2c_reg16_data8(0xff, 0x01);
arducam_rd_i2c_reg16_data8(OV5642_CHIPID_HIGH, &vid);
arducam_rd_i2c_reg16_data8(OV5642_CHIPID_LOW, &pid);
if ((vid != 0x56) || (pid != 0x42)) {
log_info(“i2c interface non responsive\n”);
} else {
log_info(“arducam module detected\n”);
}

#elif (ARDUCAM_OV2640_MINI_2MP)
//Check if the camera module type is OV2640
arducam_wr_i2c_reg8_data8(0xff, 0x01);
arducam_rd_i2c_reg8_data8(OV2640_CHIPID_HIGH, &vid);
arducam_rd_i2c_reg8_data8(OV2640_CHIPID_LOW, &pid);
if ((vid != 0x26) || (pid != 0x42)) {
log_info(“i2c interface non responsive\n”);
} else {
log_info(“arducam module detected\n”);
}
#endif

arducam_set_format(JPEG);
arducam_init_cam();
#if (ARDUCAM_OV5642_MINI_5MP)
arducam_write_reg(ARDUCHIP_TIM, VSYNC_LEVEL_MASK);
#endif
}

Please reply Thank you!

Hi,

The spi camera fetching images is affected by the spi speed. At present, OV5642 fetch images cannot reach 10 frames per second. OV2640 can barely reach 10 frames per second at the minimum resolution.

 

 

Thank you for the reply.

issue 2.

i haven’t resolved it yet. sometimes i don’t get capture_done_mask.

So I restarted the camera module and it works fine, but it not recv capture_done_mask after a while.

 

 

 

 

 

Hi,

Usually, you cannot get CAP_DONE MASK because the CPLD or the camera is not initialized properly.

Please use our example to test first. If there is no issue 2, then problem may be your code. In addition, we looked at your code, because it is incomplete, so we are not sure if there is a problem with your calling process. Hope you can give us feedback after testing your code in detail.

Our code was made by referring to ardcam.cpp. The only difference is that the i2c command function name has been modified.

arducam_wr_i2c_reg16_data8 and wrSensorReg16_8 perform the same function.

void ArduCAM::InitCAM()
{

switch (sensor_model)
{
case OV7660:
{
#if defined OV7660_CAM
wrSensorReg8_8(0x12, 0x80);
delay(100);
wrSensorRegs8_8(OV7660_QVGA);
#endif
break;
}
case OV7725:
{
#if defined OV7725_CAM
byte reg_val;
wrSensorReg8_8(0x12, 0x80);
delay(100);
wrSensorRegs8_8(OV7725_QVGA);
rdSensorReg8_8(0x15, &reg_val);
wrSensorReg8_8(0x15, (reg_val | 0x02));
#endif
break;
}
case OV7670:
{
#if defined OV7670_CAM
wrSensorReg8_8(0x12, 0x80);
delay(100);
wrSensorRegs8_8(OV7670_QVGA);
#endif
break;
}
case OV7675:
{
#if defined OV7675_CAM
wrSensorReg8_8(0x12, 0x80);
delay(100);
wrSensorRegs8_8(OV7675_QVGA);
#endif
break;
}
case MT9D111_A:
{
#if defined MT9D111A_CAM
wrSensorRegs8_16(MT9D111_QVGA_30fps);
delay(1000);
wrSensorReg8_16(0x97, 0x0020);
wrSensorReg8_16(0xf0, 0x00);
wrSensorReg8_16(0x21, 0x8403); //Mirror Column
wrSensorReg8_16(0xC6, 0xA103);//SEQ_CMD
wrSensorReg8_16(0xC8, 0x0005); //SEQ_CMD
#endif
break;
}
case MT9D111_B:
{
#if defined MT9D111B_CAM
wrSensorRegs8_16(MT9D111_QVGA_30fps);
delay(1000);
wrSensorReg8_16(0x97, 0x0020);
wrSensorReg8_16(0xf0, 0x00);
wrSensorReg8_16(0x21, 0x8403); //Mirror Column
wrSensorReg8_16(0xC6, 0xA103);//SEQ_CMD
wrSensorReg8_16(0xC8, 0x0005); //SEQ_CMD
#endif
break;
}
case OV5642:
{
#if ( defined(OV5642_CAM) || defined(OV5642_MINI_5MP) || defined(OV5642_MINI_5MP_BIT_ROTATION_FIXED) || defined(OV5642_MINI_5MP_PLUS) )
wrSensorReg16_8(0x3008, 0x80);
if (m_fmt == RAW){
//Init and set 640x480;
wrSensorRegs16_8(OV5642_1280x960_RAW);
wrSensorRegs16_8(OV5642_640x480_RAW);
}else{
wrSensorRegs16_8(OV5642_QVGA_Preview);
#if defined (RASPBERRY_PI)
arducam_delay_ms(100);
#else
delay(100);
#endif
if (m_fmt == JPEG)
{
#if defined (RASPBERRY_PI)
arducam_delay_ms(100);
#else
delay(100);
#endif
wrSensorRegs16_8(OV5642_JPEG_Capture_QSXGA);
wrSensorRegs16_8(ov5642_320x240);
#if defined (RASPBERRY_PI)
arducam_delay_ms(100);
#else
delay(100);
#endif
wrSensorReg16_8(0x3818, 0xa8);
wrSensorReg16_8(0x3621, 0x10);
wrSensorReg16_8(0x3801, 0xb0);
#if (defined(OV5642_MINI_5MP_PLUS) || (defined ARDUCAM_SHIELD_V2))
wrSensorReg16_8(0x4407, 0x04);
#else
wrSensorReg16_8(0x4407, 0x0C);
#endif
wrSensorReg16_8(0x5888, 0x00);
}
else
{

byte reg_val;
wrSensorReg16_8(0x4740, 0x21);
wrSensorReg16_8(0x501e, 0x2a);
wrSensorReg16_8(0x5002, 0xf8);
wrSensorReg16_8(0x501f, 0x01);
wrSensorReg16_8(0x4300, 0x61);
rdSensorReg16_8(0x3818, &reg_val);
wrSensorReg16_8(0x3818, (reg_val | 0x60) & 0xff);
rdSensorReg16_8(0x3621, &reg_val);
wrSensorReg16_8(0x3621, reg_val & 0xdf);
}
}
#endif
break;
}
case OV5640:
{
#if ( defined(OV5640_CAM) || defined(OV5640_MINI_5MP_PLUS) )
delay(100);
if (m_fmt == JPEG)
{
wrSensorReg16_8(0x3103, 0x11);
wrSensorReg16_8(0x3008, 0x82);
delay(100);
wrSensorRegs16_8(OV5640YUV_Sensor_Dvp_Init);
delay(500);
wrSensorRegs16_8(OV5640_JPEG_QSXGA);
wrSensorRegs16_8(OV5640_QSXGA2QVGA);
#if (defined(OV5640_MINI_5MP_PLUS) || (defined ARDUCAM_SHIELD_V2))
wrSensorReg16_8(0x4407, 0x04);
#else
wrSensorReg16_8(0x4407, 0x0C);
#endif
}
else
{
wrSensorReg16_8(0x3103, 0x11);
wrSensorReg16_8(0x3008, 0x82);
delay(500);
wrSensorRegs16_8(OV5640YUV_Sensor_Dvp_Init);
wrSensorRegs16_8(OV5640_RGB_QVGA);
}
#endif
break;
}
case OV3640:
{
#if defined OV3640_CAM
wrSensorRegs16_8(OV3640_QVGA);
#endif
break;
}
case OV2640:
{
#if (defined(OV2640_CAM) || defined(OV2640_MINI_2MP) || defined(OV2640_MINI_2MP_PLUS))
wrSensorReg8_8(0xff, 0x01);
wrSensorReg8_8(0x12, 0x80);
delay(100);
if (m_fmt == JPEG)
{
wrSensorRegs8_8(OV2640_JPEG_INIT);
wrSensorRegs8_8(OV2640_YUV422);
wrSensorRegs8_8(OV2640_JPEG);
wrSensorReg8_8(0xff, 0x01);
wrSensorReg8_8(0x15, 0x00);
wrSensorRegs8_8(OV2640_320x240_JPEG);
//wrSensorReg8_8(0xff, 0x00);
//wrSensorReg8_8(0x44, 0x32);
}
else
{
wrSensorRegs8_8(OV2640_QVGA);
}
#endif
break;
}
case OV9655:
{
break;
}
case MT9M112:
{
#if defined MT9M112_CAM
wrSensorRegs8_16(MT9M112_QVGA);
#endif
break;
}

case MT9M034:
{
#if defined MT9M034_CAM
wrSensorRegs16_16(MT9M034_RAW);
#endif
break;
}

case MT9V111:
{
#if defined MT9V111_CAM
//Reset sensor core
wrSensorReg8_16(0x01, 0x04);
wrSensorReg8_16(0x0D, 0x01);
wrSensorReg8_16(0x0D, 0x00);
//Reset IFP
wrSensorReg8_16(0x01, 0x01);
wrSensorReg8_16(0x07, 0x01);
wrSensorReg8_16(0x07, 0x00);
delay(100);
wrSensorRegs8_16(MT9V111_QVGA);
//delay(1000);
wrSensorReg8_16(0x97, 0x0020);
wrSensorReg8_16(0xf0, 0x00);
wrSensorReg8_16(0x21, 0x8403); //Mirror Column
wrSensorReg8_16(0xC6, 0xA103);//SEQ_CMD
wrSensorReg8_16(0xC8, 0x0005); //SEQ_CMD
#endif
break;
}
case MT9M001:
{
#if defined MT9M001_CAM
wrSensorRegs8_16(MT9M001_QVGA_30fps);
#endif
break;
}
case MT9T112:
{
#if defined MT9T112_CAM
wrSensorReg16_16(0x001a , 0x0219 );
wrSensorReg16_16(0x001a , 0x0018 );
//reset camera
wrSensorReg16_16(0x0014 , 0x2425 );
wrSensorReg16_16(0x0014 , 0x2145 );
wrSensorReg16_16(0x0010 , 0x0110 );
wrSensorReg16_16(0x0012 , 0x00f0 );
wrSensorReg16_16(0x002a , 0x7f77 );
wrSensorReg16_16(0x0014 , 0x2545 );
wrSensorReg16_16(0x0014 , 0x2547 );
wrSensorReg16_16(0x0014 , 0x3447 );
wrSensorReg16_16(0x0014 , 0x3047 );
delay(10);
wrSensorReg16_16(0x0014 , 0x3046 );
wrSensorReg16_16(0x0022 , 0x01f4 );
wrSensorReg16_16(0x001e , 0x0707 );
wrSensorReg16_16(0x3b84 , 0x01f4 );
wrSensorReg16_16(0x002e , 0x0500 );
wrSensorReg16_16(0x0018 , 0x402b );
wrSensorReg16_16(0x3b82 , 0x0004 );
wrSensorReg16_16(0x0018 , 0x402f );
wrSensorReg16_16(0x0018 , 0x402e );
delay(50);
wrSensorReg16_16(0x0614 , 0x0001 );
delay(1);
wrSensorReg16_16(0x0614 , 0x0001 );
delay(1);
wrSensorReg16_16(0x0614 , 0x0001 );
delay(1);
wrSensorReg16_16(0x0614 , 0x0001 );
delay(1);
wrSensorReg16_16(0x0614 , 0x0001 );
delay(1);
wrSensorReg16_16(0x0614 , 0x0001 );
delay(1);
delay(10);
//init pll
wrSensorReg16_16(0x098e , 0x6800 );
wrSensorReg16_16(0x0990 , 0x0140 );
wrSensorReg16_16(0x098e , 0x6802 );
wrSensorReg16_16(0x0990 , 0x00f0 );
wrSensorReg16_16(0x098e , 0x68a0 );
wrSensorReg16_16(0x098e , 0x68a0 );
wrSensorReg16_16(0x0990 , 0x082d );
wrSensorReg16_16(0x098e , 0x4802 );
wrSensorReg16_16(0x0990 , 0x0000 );
wrSensorReg16_16(0x098e , 0x4804 );
wrSensorReg16_16(0x0990 , 0x0000 );
wrSensorReg16_16(0x098e , 0x4806 );
wrSensorReg16_16(0x0990 , 0x060d );
wrSensorReg16_16(0x098e , 0x4808 );
wrSensorReg16_16(0x0990 , 0x080d );
wrSensorReg16_16(0x098e , 0x480c );
wrSensorReg16_16(0x0990 , 0x046c );
wrSensorReg16_16(0x098e , 0x480f );
wrSensorReg16_16(0x0990 , 0x00cc );
wrSensorReg16_16(0x098e , 0x4811 );
wrSensorReg16_16(0x0990 , 0x0381 );
wrSensorReg16_16(0x098e , 0x4813 );
wrSensorReg16_16(0x0990 , 0x024f );
wrSensorReg16_16(0x098e , 0x481d );
wrSensorReg16_16(0x0990 , 0x0436 );
wrSensorReg16_16(0x098e , 0x481f );
wrSensorReg16_16(0x0990 , 0x05d0 );
wrSensorReg16_16(0x098e , 0x4825 );
wrSensorReg16_16(0x0990 , 0x1153 );
wrSensorReg16_16(0x098e , 0x6ca0 );
wrSensorReg16_16(0x098e , 0x6ca0 );
wrSensorReg16_16(0x0990 , 0x082d );
wrSensorReg16_16(0x098e , 0x484a );
wrSensorReg16_16(0x0990 , 0x0004 );
wrSensorReg16_16(0x098e , 0x484c );
wrSensorReg16_16(0x0990 , 0x0004 );
wrSensorReg16_16(0x098e , 0x484e );
wrSensorReg16_16(0x0990 , 0x060b );
wrSensorReg16_16(0x098e , 0x4850 );
wrSensorReg16_16(0x0990 , 0x080b );
wrSensorReg16_16(0x098e , 0x4857 );
wrSensorReg16_16(0x0990 , 0x008c );
wrSensorReg16_16(0x098e , 0x4859 );
wrSensorReg16_16(0x0990 , 0x01f1 );
wrSensorReg16_16(0x098e , 0x485b );
wrSensorReg16_16(0x0990 , 0x00ff );
wrSensorReg16_16(0x098e , 0x4865 );
wrSensorReg16_16(0x0990 , 0x0668 );
wrSensorReg16_16(0x098e , 0x4867 );
wrSensorReg16_16(0x0990 , 0x0af0 );
wrSensorReg16_16(0x098e , 0x486d );
wrSensorReg16_16(0x0990 , 0x0af0 );
wrSensorReg16_16(0x098e , 0xa005 );
wrSensorReg16_16(0x0990 , 0x0001 );
wrSensorReg16_16(0x098e , 0x6c11 );
wrSensorReg16_16(0x0990 , 0x0003 );
wrSensorReg16_16(0x098e , 0x6811 );
wrSensorReg16_16(0x0990 , 0x0003 );
wrSensorReg16_16(0x098e , 0xc8a5 );
wrSensorReg16_16(0x0990 , 0x0025 );
wrSensorReg16_16(0x098e , 0xc8a6 );
wrSensorReg16_16(0x0990 , 0x0028 );
wrSensorReg16_16(0x098e , 0xc8a7 );
wrSensorReg16_16(0x0990 , 0x002c );
wrSensorReg16_16(0x098e , 0xc8a8 );
wrSensorReg16_16(0x0990 , 0x002f );
wrSensorReg16_16(0x098e , 0xc844 );
wrSensorReg16_16(0x0990 , 0x00ba );
wrSensorReg16_16(0x098e , 0xc92f );
wrSensorReg16_16(0x0990 , 0x0000 );
wrSensorReg16_16(0x098e , 0xc845 );
wrSensorReg16_16(0x0990 , 0x009b );
wrSensorReg16_16(0x098e , 0xc92d );
wrSensorReg16_16(0x0990 , 0x0000 );
wrSensorReg16_16(0x098e , 0xc88c );
wrSensorReg16_16(0x0990 , 0x0082 );
wrSensorReg16_16(0x098e , 0xc930 );
wrSensorReg16_16(0x0990 , 0x0000 );
wrSensorReg16_16(0x098e , 0xc88d );
wrSensorReg16_16(0x0990 , 0x006d );
wrSensorReg16_16(0x098e , 0xc92e );
wrSensorReg16_16(0x0990 , 0x0000 );
wrSensorReg16_16(0x098e , 0xa002 );
wrSensorReg16_16(0x0990 , 0x0010 );
wrSensorReg16_16(0x098e , 0xa009 );
wrSensorReg16_16(0x0990 , 0x0002 );
wrSensorReg16_16(0x098e , 0xa00a );
wrSensorReg16_16(0x0990 , 0x0003 );
wrSensorReg16_16(0x098e , 0xa00c );
wrSensorReg16_16(0x0990 , 0x000a );
wrSensorReg16_16(0x098e , 0x4846 );
wrSensorReg16_16(0x0990 , 0x0014 );
wrSensorReg16_16(0x098e , 0x488e );
wrSensorReg16_16(0x0990 , 0x0014 );
wrSensorReg16_16(0x098e , 0xc844 );
wrSensorReg16_16(0x0990 , 0x0085 );
wrSensorReg16_16(0x098e , 0xc845 );
wrSensorReg16_16(0x0990 , 0x006e );
wrSensorReg16_16(0x098e , 0xc88c );
wrSensorReg16_16(0x0990 , 0x0082 );
wrSensorReg16_16(0x098e , 0xc88d );
wrSensorReg16_16(0x0990 , 0x006c );
wrSensorReg16_16(0x098e , 0xc8a5 );
wrSensorReg16_16(0x0990 , 0x001b );
wrSensorReg16_16(0x098e , 0xc8a6 );
wrSensorReg16_16(0x0990 , 0x001e );
wrSensorReg16_16(0x098e , 0xc8a7 );
wrSensorReg16_16(0x0990 , 0x0020 );
wrSensorReg16_16(0x098e , 0xc8a8 );
wrSensorReg16_16(0x0990 , 0x0023 );
//init setting
wrSensorReg16_16(0x0018 , 0x002a );
wrSensorReg16_16(0x3084 , 0x2409 );
wrSensorReg16_16(0x3092 , 0x0a49 );
wrSensorReg16_16(0x3094 , 0x4949 );
wrSensorReg16_16(0x3096 , 0x4950 );
wrSensorReg16_16(0x098e , 0x68a0 );
wrSensorReg16_16(0x0990 , 0x0a2e );
wrSensorReg16_16(0x098e , 0x6ca0 );
wrSensorReg16_16(0x0990 , 0x0a2e );
wrSensorReg16_16(0x098e , 0x6c90 );
wrSensorReg16_16(0x0990 , 0x0cb4 );
wrSensorReg16_16(0x098e , 0x6807 );
wrSensorReg16_16(0x0990 , 0x0004 );
wrSensorReg16_16(0x098e , 0xe88e );
wrSensorReg16_16(0x0990 , 0x0000 );
wrSensorReg16_16(0x316c , 0x350f );
wrSensorReg16_16(0x001e , 0x0777 );
wrSensorReg16_16(0x098e , 0x8400 );
wrSensorReg16_16(0x0990 , 0x0001 );
delay(100);
wrSensorReg16_16(0x098e , 0x8400 );
wrSensorReg16_16(0x0990 , 0x0006 );
//Serial.println(“MT9T112 init done”);
#endif
break;
}
case MT9D112:
{
#if defined MT9D112_CAM
wrSensorReg16_16(0x301a , 0x0acc );
wrSensorReg16_16(0x3202 , 0x0008 );
delay(100 );
wrSensorReg16_16(0x341e , 0x8f09 );
wrSensorReg16_16(0x341c , 0x020c );
delay(100 );
wrSensorRegs16_16(MT9D112_default_setting);
wrSensorReg16_16(0x338c , 0xa103 );
wrSensorReg16_16(0x3390 , 0x0006 );
delay(100 );
wrSensorReg16_16(0x338c , 0xa103 );
wrSensorReg16_16(0x3390 , 0x0005 );
delay(100 );
wrSensorRegs16_16(MT9D112_soc_init);
delay(200);
wrSensorReg16_16(0x332E, 0x0020); //RGB565
#endif
}
default:
break;
}
}

Even if we add ‘wrSensorReg16_8(0x3801, 0xb0);’ to our code, the symptoms are the same.

 

 

 

Hello,

Did you use our test examples for testing? Please use our example to test first to make sure the camera can work stably.

In addition, if you paste the code to us, please paste the call flow of all functions, not just the function definition.

Hi

It was identified as a problem with our chip.

Now solved and by replacing the module with ov2640, the performance was improved to 10fps.

Thank you

 

 

 

Hi,

Great to hear you have solved your problems.

Let me know if you need more help.