Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Arduino + OV7670 - Without FIFO - Reading Snapshot

I know that there is a lot in internet (http://forum.arduino.cc/index.php?topic=159557.0 for example) about OV7670 and I read a lot about it, but seems something is missing.

First of all I took a look into the way how can we read pixel by pixel from the camera to build the rectangular 600 X 480 image, and this was quite easy to understand considering HREF, VSYNCH and PCLOCK described on documentation here: http://www.voti.nl/docs/OV7670.pdf. I understand XCLOCK as an input I need to give to OV7670 as a kind of cycle controller and RESET would be something to reset it.

So at this point I thought that the functionality of such camera would be covered by wiring the following pins:

  • D0..D7 - for data (pixel) connected to arduino digital pins 0 to 7 as INPUT on arduino board
  • XCLK - for camera clock connected to arduino digital pin 8 as OUTPUT from arduino board
  • PCLK - for pixel clock connected to arduino digital pin 9 as INPUT on arduino board
  • HREF - to define when a line starts / ends connected to arduino digital pin 10 as INPUT on arduino board
  • VSYCH - to define when a frame starts / ends connected to arduino digital pin 11 as INPUT on arduino board
  • GRD - groud connected to arduino GRD
  • 3V3 - 3,3 INPUT connected to arduino 3,3v
  • RESET - connected to arduino RESET
  • PWDN - connected to arduino GRD

The implementation for such approach from my point of view would be something like: Code:

for each loop function do
   write high to XCLK

   if VSYNCH is HIGH 
      return;

   if HREF is LOW 
      return;

   if lastPCLOCK was HIGH and currentPCLOCK is LOW 
      readPixelFromDataPins();

end for

My readPixelFromDataPins() basically read just the first byte (as I'm just testing if I can even read something from the camera), and it is written as follows:

Code:

byte readPixelFromDataPins() {
  byte result = 0;
  for (int i = 0; i < 8; i++) {
    result = result << 1 | digitalRead(data_p[i]);
  }
  return result;
}

In order to check if something is being read from the camera I just print it to the Serial 9600, the byte read from data pins as a number. But currently I'm receiving only zero values. The code I'm using to retrieve an image is stored here: https://gist.github.com/franciscospaeth/8503747.

Did somebody that makes OV7670 work with Arduino already figure out what am I doing wrong? I suppose I'm using the XCLOCK wrongly right? What shall I do to get it working?

I searched a lot and I didn't found any SSCCE (http://sscce.org/) for this camera using arduino, if somebody have it please let me know.


This question is present on arduino forum (http://forum.arduino.cc/index.php?topic=211741.0) too.

like image 285
Francisco Spaeth Avatar asked Jan 19 '14 18:01

Francisco Spaeth


2 Answers

your idea is not bad but ... the xclock need to be a clock (in your program is just a transition from 0 to 1 and is freezing there) you need also to use I2C with SIOC and SIOD for configuring the camera (or you can use the default settings, but I am not sure if is the correct output format for you, 30F/s,VGA, YUV format ....)

your code execution is slower using the serial output in the same loop with reading data I will recommend you to toggle the xclock pin and to move the pixel print in a if(). Also you will be able to read Data only in a very precise time, if you want to read only one byte, than after a transition from 0 to 1 of HREF you need to wait for a new transition from 0 to 1 of PCLK (you will be able to see only one 0-1 transition of HREF after 784x2 transitions of PCLK, (640 active pixels + 144 dead time for each line) x 2 (for YUV or RGB are 2 bytes received for each pixel) )

like image 134
user3408340 Avatar answered Nov 17 '22 02:11

user3408340


Hello I am Mr_Arduino from the arduino forums. Your issue is that you are reading pixels too slow please do not use digital read to do such a thing. Also if you insist on using a separate function just to read a byte make sure the function is being inlined. You can do this by declaring your function as static inline. Also as mentioned above how are you generating the clock. You can generate the XCLK using PWM on the arduino.

I have created a working example here:

https://github.com/ComputerNerd/arduino-camera-tft/blob/master/captureimage.c

Edit: a 3rd party has copied part but not all of the code from the above link into the answer here. However, the link must remain as the code posted below requires additional files from that source to actually work. Edit 2: Removed irrelevant code. You will need to modify what you do with the data.

void capImg(void){
    cli();
    uint8_t w,ww;
    uint8_t h;
    w=160;
    h=240;
    tft_setXY(0,0);
    CS_LOW;
    RS_HIGH;
    RD_HIGH;
    DDRA=0xFF;
    //DDRC=0;
    #ifdef MT9D111
        while (PINE&32){}//wait for low
        while (!(PINE&32)){}//wait for high
    #else
        while (!(PINE&32)){}//wait for high
        while (PINE&32){}//wait for low
    #endif
    while (h--){
        ww=w;
        while (ww--){
            WR_LOW;
            while (PINE&16){}//wait for low
            PORTA=PINC;
            WR_HIGH;
            while (!(PINE&16)){}//wait for high
            WR_LOW;
            while (PINE&16){}//wait for low
            PORTA=PINC;
            WR_HIGH;
            while (!(PINE&16)){}//wait for high
            WR_LOW;
            while (PINE&16){}//wait for low
            PORTA=PINC;
            WR_HIGH;
            while (!(PINE&16)){}//wait for high
            WR_LOW;
            while (PINE&16){}//wait for low
            PORTA=PINC;
            WR_HIGH;
            while (!(PINE&16)){}//wait for high
        }

    }
    CS_HIGH;
    sei();
}

You can also find it on github.

like image 2
user3462295 Avatar answered Nov 17 '22 03:11

user3462295