ArduCAM / Arduino

This is ArduCAM library for Arduino boards
MIT License
469 stars 347 forks source link

Mini-5MP-Plus FPS limit #173

Open michprev opened 7 years ago

michprev commented 7 years ago

Hey, I am running ArduCAM_Mini_5MP_Plus_Video_Streaming sketch and I cannot get over 6 FPS on Arduino UNO. I have also rewritten the code for STM32 (source available here). The issue is that waiting for CAP_DONE_MASK of ARDUCHIP_TRIG takes too long (in average about 300 ms).

The solution would be to use the short video capture feature but this does not allow to stream the video in real time.

Is there any way how to get higher FPS? Thank you!

supprot commented 7 years ago

@michprev Hi, Please try to teat this demo: // ArduCAM Mini demo (C)2017 Lee // Web: http://www.ArduCAM.com. // This demo was made for ArduCAM_Mini_5MP_Plus. // It can continue shooting and store it into the SD card in AVI format // The demo sketch will do the following tasks // 1.Shoot video button, began to shoot video // 2. Set the camera to JPEG output mode. // 3. Capture a JPEG photo and buffer the image to FIFO // 4.Write AVI Header // 5.Write the video data to the SD card // 6.More updates AVI file header // 7.close the file // The file header introduction // 00-03 :RIFF // 04-07 :The size of the data // 08-0B :File identifier // 0C-0F :The first list of identification number // 10-13 :The size of the first list // 14-17 :The hdr1 of identification // 18-1B :Hdr1 contains avih piece of identification // 1C-1F :The size of the avih // 20-23 :Maintain time per frame picture // This program requires the ArduCAM V4.0.0 (or later) library and ArduCAM_Mini_5MP_Plus // and use Arduino IDE 1.6.8 compiler or above

include

include

include

include

include "memorysaver.h"

//This demo can only work on OV5640_MINI_5MP_PLUS or OV5642_MINI_5MP_PLUS platform.

if !(defined (OV5640_MINI_5MP_PLUS)||defined (OV5642_MINI_5MP_PLUS))

error Please select the hardware platform and camera module in the ../libraries/ArduCAM/memorysaver.h file

endif

define FRAMES_NUM 0x07

define rate 0x0a

define SD_CS 9

define KEY 2

define AVIOFFSET 240

// set pin 7 as the slave select for the digital pot: const int CS = 7; bool is_header = false; uint32_t total_time = 0; unsigned long movi_size = 0; unsigned long jpeg_size = 0; const char zero_buf[4] = {0x00, 0x00, 0x00, 0x00}; const int avi_header[AVIOFFSET] PROGMEM ={ 0x52, 0x49, 0x46, 0x46, 0xD8, 0x01, 0x0E, 0x00, 0x41, 0x56, 0x49, 0x20, 0x4C, 0x49, 0x53, 0x54, 0xD0, 0x00, 0x00, 0x00, 0x68, 0x64, 0x72, 0x6C, 0x61, 0x76, 0x69, 0x68, 0x38, 0x00, 0x00, 0x00, 0xA0, 0x86, 0x01, 0x00, 0x80, 0x66, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4C, 0x49, 0x53, 0x54, 0x84, 0x00, 0x00, 0x00, 0x73, 0x74, 0x72, 0x6C, 0x73, 0x74, 0x72, 0x68, 0x30, 0x00, 0x00, 0x00, 0x76, 0x69, 0x64, 0x73, 0x4D, 0x4A, 0x50, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, rate, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0x74, 0x72, 0x66, 0x28, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 0x4D, 0x4A, 0x50, 0x47, 0x00, 0x84, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4C, 0x49, 0x53, 0x54, 0x10, 0x00, 0x00, 0x00, 0x6F, 0x64, 0x6D, 0x6C, 0x64, 0x6D, 0x6C, 0x68, 0x04, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x4C, 0x49, 0x53, 0x54, 0x00, 0x01, 0x0E, 0x00, 0x6D, 0x6F, 0x76, 0x69, }; void print_quartet(unsigned long i,File fd){ fd.write(i % 0x100); i = i >> 8; //i /= 0x100; fd.write(i % 0x100); i = i >> 8; //i /= 0x100; fd.write(i % 0x100); i = i >> 8; //i /= 0x100; fd.write(i % 0x100); }

if defined (OV5640_MINI_5MP_PLUS)

ArduCAM myCAM(OV5640, CS);

else

ArduCAM myCAM(OV5642, CS);

endif

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

if defined(SAM3X8E)

Wire1.begin();

else

Wire.begin();

endif

Serial.begin(115200); Serial.println(F("ArduCAM Start!"));

// set the CS as an output: pinMode(CS, OUTPUT); pinMode(SD_CS, OUTPUT); pinMode(KEY, INPUT); // initialize SPI: SPI.begin();

while(1){ //Check if the ArduCAM SPI bus is OK myCAM.write_reg(ARDUCHIP_TEST1, 0x55); temp = myCAM.read_reg(ARDUCHIP_TEST1); if(temp != 0x55) { Serial.println(F("SPI interface Error!")); delay(1000);continue; }else{ Serial.println(F("SPI interface OK."));break; } }

if defined (OV5640_MINI_5MP_PLUS)

while(1){ //Check if the camera module type is OV5640 myCAM.rdSensorReg16_8(OV5640_CHIPID_HIGH, &vid); myCAM.rdSensorReg16_8(OV5640_CHIPID_LOW, &pid); if ((vid != 0x56) || (pid != 0x40)){ Serial.println(F("Can't find OV5640 module!")); delay(1000); continue; }else{ Serial.println(F("OV5640 detected."));break;
} }

else

while(1){ //Check if the camera module type is OV5642 myCAM.rdSensorReg16_8(OV5642_CHIPID_HIGH, &vid); myCAM.rdSensorReg16_8(OV5642_CHIPID_LOW, &pid); if ((vid != 0x56) || (pid != 0x42)){ Serial.println(F("Can't find OV5642 module!")); delay(1000);continue; }else{ Serial.println(F("OV5642 detected."));break;
} }

endif

//Initialize SD Card while(!SD.begin(SD_CS)) { Serial.println(F("SD Card Error!"));delay(1000); } Serial.println(F("SD Card detected."));

//Change to JPEG capture mode and initialize the OV5640 module myCAM.set_format(JPEG); myCAM.InitCAM(); myCAM.set_bit(ARDUCHIP_TIM, VSYNC_LEVEL_MASK);

if defined (OV5640_MINI_5MP_PLUS)

myCAM.OV5640_set_JPEG_size(OV5640_320x240);delay(1000);

else

myCAM.OV5642_set_JPEG_size(OV5642_320x240);delay(1000);

endif

myCAM.clear_fifo_flag(); myCAM.write_reg(ARDUCHIP_FRAMES, FRAMES_NUM); } boolean isCaptureFlag = false; bool keyState; uint8_t temp, temp_last; uint32_t length = 0; uint32_t flash_time = 0; void loop() { // put your main code here, to run repeatedly: keyState= digitalRead(KEY); if(!keyState) { isCaptureFlag = true; while(!digitalRead(KEY));
} if(isCaptureFlag){ myCAM.flush_fifo(); myCAM.clear_fifo_flag(); //Start capture myCAM.start_capture(); Serial.println(F("start capture.")); total_time = millis(); flash_time =millis(); while ( !myCAM.get_bit(ARDUCHIP_TRIG, CAP_DONE_MASK)); length = myCAM.read_fifo_length(); if( length < 0x3FFFFF){ myCAM.flush_fifo(); myCAM.clear_fifo_flag(); //Start capture myCAM.start_capture(); while ( !myCAM.get_bit(ARDUCHIP_TRIG, CAP_DONE_MASK)); Serial.println(F("CAM Capture Done.")); total_time = millis() - total_time; }else{ Serial.println(F("CAM Capture Done.")); total_time = millis() - total_time; } total_time = millis(); read_fifo_burst(); total_time = millis() - total_time; //Clear the capture done flag myCAM.clear_fifo_flag(); isCaptureFlag = false; } } uint8_t read_fifo_burst() {
uint8_t temp = 0, temp_last = 0; uint32_t length = 0; static int i = 0; static int k = 0; unsigned long position = 0; uint16_t frame_cnt = 0; uint8_t remnant = 0; File outFile; char str[8]; byte buf[256]; length = myCAM.read_fifo_length(); Serial.print(F("The fifo length is :")); Serial.println(length, DEC); // Serial.println("writting the data to the SD !"); if (length >= MAX_FIFO_SIZE) //8M { Serial.println(F("Over size.")); return 0; } if (length == 0 ) //0 kb { Serial.println(F("Size is 0.")); return 0; } movi_size = 0; //Create a avi file k = k + 1; itoa(k, str, 10); strcat(str, ".avi"); //Open the new file outFile = SD.open(str, O_WRITE | O_CREAT | O_TRUNC); if (! outFile) { Serial.println(F("open file failed")); while (1); } //Write AVI Header for ( i = 0; i < AVIOFFSET; i++) { char ch = pgm_read_byte(&avi_header[i]); buf[i] = ch; } outFile.write(buf, AVIOFFSET); myCAM.CS_LOW(); myCAM.set_fifo_burst();//Set fifo burst mode i = 0; while ( length-- ) { temp_last = temp; temp = SPI.transfer(0x00); //Read JPEG data from FIFO if ( (temp == 0xD9) && (temp_last == 0xFF) ) //If find the end ,break while, { buf[i++] = temp; //save the last 0XD9 //Write the remain bytes in the buffer myCAM.CS_HIGH(); outFile.write(buf, i); jpeg_size += i; remnant = (4 - (jpeg_size & 0x00000003)) & 0x00000003; jpeg_size = jpeg_size + remnant; movi_size = movi_size + jpeg_size; if (remnant > 0) outFile.write(zero_buf, remnant); position = outFile.position(); outFile.seek(position - 4 - jpeg_size); print_quartet(jpeg_size, outFile); position = outFile.position(); outFile.seek(position + 6); outFile.write("AVI1", 4); position = outFile.position(); outFile.seek(position + jpeg_size - 10); is_header = false; frame_cnt++; myCAM.CS_LOW(); myCAM.set_fifo_burst(); } if (is_header == true) { //Write image data to buffer if not full if (i < 256) buf[i++] = temp; else { //Write 256 bytes image data to file myCAM.CS_HIGH(); outFile.write(buf, 256); i = 0; buf[i++] = temp; myCAM.CS_LOW(); myCAM.set_fifo_burst(); jpeg_size += 256; }
} else if ((temp == 0xD8) && (temp_last == 0xFF)) { is_header = true; myCAM.CS_HIGH(); outFile.write("00dc"); outFile.write(zero_buf, 4); i = 0; jpeg_size = 0; myCAM.CS_LOW(); myCAM.set_fifo_burst();
buf[i++] = temp_last; buf[i++] = temp;
} } myCAM.CS_HIGH(); //Modify the MJPEG header from the beginning of the file outFile.seek(4); print_quartet(movi_size +12frame_cnt+4, outFile);//riff file size //overwrite hdrl unsigned long us_per_frame = 1000000 / rate; //(per_usec); //hdrl.avih.us_per_frame outFile.seek(0x20); print_quartet(us_per_frame, outFile); unsigned long max_bytes_per_sec = movi_size rate/ frame_cnt; //hdrl.avih.max_bytes_per_sec outFile.seek(0x24); print_quartet(max_bytes_per_sec, outFile); unsigned long tot_frames = frame_cnt; //hdrl.avih.tot_frames outFile.seek(0x30); print_quartet(tot_frames, outFile); unsigned long frames =frame_cnt;// (TOTALFRAMES); //hdrl.strl.list_odml.frames outFile.seek(0xe0); print_quartet(frames, outFile); outFile.seek(0xe8); print_quartet(movi_size, outFile);// size again //Close the file outFile.close(); is_header = false; Serial.println(F("Movie save OK")); return 1; } Let us know if you need more help. Regards, ArduCAM support team.

michprev commented 7 years ago

This does not allow to stream the video. We have to wait for about 5 minutes before it is possible to load images from the buffer. I am looking for a solution that would allow to stream the video (images) with no delay and higher FPS.

supprot commented 7 years ago

@michprev Hi, The speed of frame is related to register configuration. In this demo ,after you button down the key,it will start capture until 8M datasand then save it to SD card,We just give you a demo and the frame speed can uo to ten fps.You can adjust the relevant register to change the frame speed.

Let us know if you need more help. Regards, ArduCAM support team.

michprev commented 7 years ago

@supprot Hi, I think that I understand now - I need to tune camera registers over I2C. Are there available any schematics for Arducam Mini Plus boards (I am interested in OV5640 and OV5642 boards)? I don't know how works communication between the camera and the FIFO and I don't want to break it by setting improper value into a camera register. Is there any description of OV5640 and OV5642 registers or do I need to contact Omnivision support?

Thank you!

supprot commented 7 years ago

@michprev Hi,

Please refer to the below link: www.uctronics.com/download/OV5642_camera_module_software_application_notes_1.1.pdf www.uctronics.com/download/OV5642_CSP_DS_1.11_OVT(5M EDoF AFC).pdf

Let us know if you need more help. Regards, ArduCAM support team.

supprot commented 7 years ago

@michprev Hi, http://www.uctronics.com/download/OV5642_CSP_DS_1.11_OVT%EF%BC%885M%20EDoF%20AFC%EF%BC%89.pdf Let us know if you need more help. Regards, ArduCAM support team.

michprev commented 7 years ago

@supprot

Thank you very much!! Hope to get it working soon.

supprot commented 7 years ago

@michprev Hi,

You are welcome, please feel free to tell us if you have any problems.

Regards, ArduCAM support team.

ShilRenz commented 6 years ago

@supprot Hi, I have the same issue, I want to set up higher frame rate of my arducam OV5642, I have read www.uctronics.com/download/OV5642_camera_module_software_application_notes_1.1.pdf, but I don't know where to put this codes capture , may I know where will I put this codes? Thank you!

supprot commented 6 years ago

@ShilRenz Hi, You should put this configure to void ArduCAM::InitCAM() which is in ArduCAM.cpp file.

ShilRenz commented 6 years ago

@supprot thank you for so much for helping, hope this might help me with my project.

ShilRenz commented 6 years ago

I tried to put the code inside void ArduCAM::InitCAM() but during the compilation there was an error I encountered. capture i put the code inside case ov5642 capture1

I also have some question and this might not be something related to this topic, but I just wanted to ask if it is possible to create a real time face including the eye detection in arducam ov5642 ?

supprot commented 6 years ago

@ShilRenz Hi, Please replace 'write_i2c()' with 'wrSensorReg16_8()'.

ShilRenz commented 6 years ago

thank you @supprot it quite faster now than before.

supprot commented 6 years ago

@ShilRenz How many fps can you get?

ShilRenz commented 6 years ago

@supprot i got 2-3 fps, its still pretty slow for my project. how can i make it faster to 15 fps or more?

supprot commented 6 years ago

@ShilRenz This has a lot to do with the speed of the controller and the speed of the SPI. You can try it on STM32 controller.

ShilRenz commented 6 years ago

@supprot i don't have STM32 controller, is there any other way to change the fps in my arducam? it was directly connected to my arduino. do you have facebook account, may i contact you there? so that I can ask you easily when you are on line. I needed a lot of help.

supprot commented 6 years ago

@ShilRenz Hi, Facebook is not available for the time being.Do you have Skype? If so, you can contact us and our Skype ID is fpga4u

ShilRenz commented 6 years ago

@supprot ok sir, thank you for the reply, I don't have Skype. I'll just comment here or to the other issues if I have concerns. thank you a lot for your help. .😊

dcavone commented 2 years ago

Hello, the time between start_capture() and the flag CAP_DONE_MASK = 1 depends on only OV5642 sensor? Thank you