ArduCAM / Arduino

This is ArduCAM library for Arduino boards
MIT License
470 stars 348 forks source link

Strange issue to get the "capture done" flag #478

Open ningdongywq opened 4 years ago

ningdongywq commented 4 years ago

Hi!

I am doing a project to use the Arducam 2MP Plus Rev A (OV2640) with Beaglebone black, using bare-metal programming. In other words, I implemented the I2C and SPI driver by myself, and try to use them to make the camera work. But after I rewrite your camera's app with my drivers, the program stuck after "Start capture!". And I check the camera's FIFO register's value, it's always 00. So, the problem is that I cannot get the capture done flag.

  1. The SPI driver works well, like your Linux version, I write 0x55 to test register and read it again, got 0x55.
  2. The I2C works well, I can read the camera's ID, 2642.
  3. I did the steps as your setup() and main() functions to capture a JPEG file, but after give the command start_capture, your code returns numbers like 0x01 until it hits 0x08 or 0x09 which has the done bit set (bit 3), mine returns always 0x00.

I see a similar problem with mine, https://github.com/ArduCAM/Arduino/issues/24. But after I test, the problem is not the same. His problem is the SPI PHL should be 0, not 1, as mentioned. But mine version the PHL value is already 0.

I find a solution by myself to add "wrSensorReg8_8(0xff,0x00)" before check the capture done flag. It changes the sensor's mode from sensor mode to DSP mode. Then everything works well and the picture is valid. But I don't know why? Since in your code, you do not need to change the sensor's mode to get the capture done. Any ideas would be appreciated.

Look forward to your reply. Thank you!

UCTRONICS commented 4 years ago

Hi, Thanks for your business. As normal , changing the register bank will not effect getting image. I advise you to ensure you have init the sensor following our demo code.

ningdongywq commented 4 years ago

Thanks for your quick reply. To init the sensor, I think you mean using i2c functions wrSensorRegs8_8 with ov2640regs.h. Actually, I do not change anything for ov2640regs.h. I attached camera's code. You can see I followed the same steps as yours.

camera_setup:

    {uint8_t vid,pid;
    uint8_t temp;
     UTFT();
    ArduCAM(OV2640);
    printf("ArduCAM Start!\n");

    // Check the ArduCAM SPI bus
    write_reg(ARDUCHIP_TEST1, 0x55);
    temp = read_reg(ARDUCHIP_TEST1);
    if(temp != 0x55)
    {
    printf("SPI interface Error!\n");
    while(1);
    }
    else
    {
       printf("SPI bus works well!\n");
    }

   //Change MCU mode
   write_reg(ARDUCHIP_MODE, 0x00);

   InitLCD();

   //Check the I2C bus and camera module type
   rdSensorReg8_8(OV2640_CHIPID_HIGH, &vid);
   //printf("vid is : %x\n",vid);
   rdSensorReg8_8(OV2640_CHIPID_LOW, &pid);
   //printf("pid is : %x\n",pid);
    if((vid != 0x26) || (pid != 0x42))
printf("Can't find OV2640 module!\n");
    else
printf("OV2640 detected\n");

   set_format(BMP);

   InitCAM();}

main:

   {BOOL isSavedFlag = FALSE;

   camera_setup();
   printf("Setup done!\n");

   uint8_t buf[2000];
   static int i = 0;
   uint8_t temp,temp_last;

   while(1)
{        
            set_format(JPEG);
    InitCAM();
    write_reg(ARDUCHIP_MODE, 0x00);
    OV2640_set_JPEG_size(OV2640_160x120);
            //rdSensorReg8_8(0xFF, &ctrlbank);
            //printf("Sensor bank 1 is : %x\n",ctrlbank);

        //Flush the FIFO
    flush_fifo();
            printf("Flush done!\n");
            //rdSensorReg8_8(0xFF, &ctrlbank);
            //printf("Sensor bank 2 is : %x\n",ctrlbank);

            //Clear the capture done flag
    clear_fifo_flag();
            printf("Clear done!\n");
            //rdSensorReg8_8(0xFF, &ctrlbank);
            //printf("Sensor bank 3 is : %x\n",ctrlbank);

            //Start capture
    capture();
            //rdSensorReg8_8(0xFF, &ctrlbank);
            //printf("Sensor bank 4 is : %x\n",ctrlbank);
    printf("Start Capture\n");

            while (isSavedFlag == FALSE) {
                    wrSensorReg8_8(0xff, 0x00);
        if(read_reg(ARDUCHIP_TRIG) & CAP_DONE_MASK){
        printf("Capture Done!\n");

                    i = 0;
                    temp = read_fifo();

                    //Write first image data to buffer
        buf[i++] = temp;
                    printf("0x%x,\n",temp);

                    //Read JPEG data from FIFO
        while( (temp != 0xD9) | (temp_last != 0xFF) )
            {
                temp_last = temp;
                temp = read_fifo();
                //Write image data to buffer if not full
                if(i < 2000)
                                     {
                    buf[i++] = temp;
                                            printf("0x%x,\n",temp);
                                     }
                else
                {
                    //Write 256 uint8_ts image data to file
                    //fwrite(buf,256,nmemb,fp);
                    printf("Picture data is more than buffer's szie\n");
                                            break;

                                            //i = 0;
                    //buf[i++] = temp;
                }
            }
                    printf("picture done\n");

        //Clear the capture done flag
        clear_fifo_flag();
        //Clear the start capture flag
                    set_format(BMP);
        InitCAM();
        isSavedFlag = TRUE;
                    }
            }
            isSavedFlag = FALSE;
            break;
    }}
ArducamSupport commented 4 years ago

Hello, Thank you for describing your problem in detail. You said you implemented I2C and SPI yourself, and I think you wrote in the last {0xff, 0xff} of the configuration when writing registers with I2C.If you look closely at our library, you'll see that {0xff,0xff} is just for the end of a batch write, not really written in. Please try again after confirmation.

ningdongywq commented 4 years ago

Thank you! Actually I just replaced the basic function for wrsensorReg, not wrsensorRegs. In other words, I also check the (0xff,0xff) to stop the process. You can see the code here,

uint8_t wrSensorReg8_8(uint8_t regID, uint8_t regDat) { uint8_t buf[1]; buf[0] = regDat; i2c_write(200, 0x30, regID, 1, buf, 1); return 1; }

int wrSensorRegs8_8(const struct sensor_reg reglist[]) { int err = 0; uint8_t reg_addr = 0; uint8_t reg_val = 0; const struct sensor_reg *next = reglist; while ((reg_addr != 0xff) | (reg_val != 0xff)) { reg_addr = pgm_read_word(&next->reg); reg_val = pgm_read_word(&next->val); err = wrSensorReg8_8(reg_addr, reg_val); //printf("address is %x\n",reg_addr);
next++; } return 1; }

The read functions are similar. Btw, the i2c address of the sensor is 0x30, rather than 0x60 mentioned on your website for OV2640. You can use i2cdetect in Linux to check the address.

ArducamSupport commented 4 years ago

Hi, 0x30 is the 7-bit address of I2C, excluding read and write bit.0x60 include the write bit.

ningdongywq commented 4 years ago

Hi, 0x30 is the 7-bit address of I2C, excluding read and write bit.0x60 include the write bit.

Thanks for your reply. I see the point for the address. This is not the problem I want to discuss.

The value 0xff,0xff is not written to the sensor. So if you have time, you can look at my code, https://github.com/ningdongywq/security_project/tree/master/Camera_APP_Hypervisor

Thank you!