OV7670 with both arduino uno and now mega

Have you been told by someone or I that you an external ram of some sort such as a FIFO or SPI ram. I previously thought external RAM was needed but that is not true.

Here is the code that uses only a non-FIFO OV7670 module GitHub - ComputerNerd/ov7670-no-ram-arduino-uno: Allows you to use a non fifo ov7670 on the arudino uno without external spi ram like other examples. Sends the data to UART.
Accompanied by the Arudino code is a frame grabber GitHub - ComputerNerd/simpleFrameGrabber: Uses SDL to display frames sent via serial. POSIX systems only.
It requires only the ov7670 without FIFO and a way to lower the 5V digital outputs to 3.3V. No other parts such as SPI ram or an AL422 are needed.

Also for those who may have been having trouble with the camera module note that PWDN should be plugged into ground and RESET# to 3.3v.

The initial post is always a work in progress. I appreciate suggestions on how to improve this post. We can avoid redundant questions with a high quality initial post.

When creating this post on the 2013-04-09 I would have never imagined that there would be so much interest in the ov7670.

I am happy that I have enabled so many people to explore the world of image processing introducing people to a valuable and fun concept.

What is the OV7670?

The OV7670 is an image sensor manufactured by OmniVision.
This image sensor is quite old by image sensor standards. According to OmniVision they started mass production of the sensor in February of 2006.
The image sensor has a resolution of 640x480 and is an Soc meaning it has built in image processing capabilities.
Why the OV7670?
The OV7670 is the lowest cost camera module that I am able to find.

There are other easy to use camera modules available that are higher quality for only a few dollars more.
What can I do with the OV7670?
The reality is you are limited not only by the sensor but by the processor you are using.
This thread focuses primarily on Arduino boards and interfacing the ov7670 to microcontrollers featured on an Arduino board. The Arduinos that I have used are both based on 8bit AVRs running at 16mhz so that is quite the limitation. I do however welcome discussion of any microcontroller. Do not expect something ridiculous such as 30fps 640x480 on an Arduino Uno.

The original reason that I wanted to use the OV7670 was time lapse purposes.
I could live with the slow speed as all I need was an image every few seconds. However using a faster microcontroller can mean reading pixels faster but remember un-optimized code on a fast microcontroller can be slower than well optimized code on a slower device.

So with all that said: What can I actually do with this sensor? The answer is pretty much anything that does not involve subjecting the sensor to unreasonable conditions or expecting something unreasonable from it such as 1000fps full resolution. What attracts me to the idea of a camera module vs just buying a webcam is the fact that I have more control over it. You are able to program it to do various tasks that suite your needs and the automatic functionality on the OV7670 (such as auto white balance, auto gain and auto exposure) can be overridden if needed.
How can I get started?
Read the documentation and check out code that I have written. Also check the code to figure out some aspects of wiring. I have already explained many aspects of wiring. Just read the thread.
Where can I get documentation?
http://www.electronicaestudio.com/docs/sht001.pdf

I would like to expand this list. If you have ANYTHING from Omnivsion that would help me understand undocumented stuff in regards to the OV7670 I will take it. If you cannot or do not want it to be posted on the internet I will respect that wish fully. I will take anything regarding the OV7670 even a newer version of what I have already. In fact I would take unrelated documentation that comes from Omnivsion. It is nice to have. Seemly unrelated documentation may prove to be relevant in non obvious ways until examined.
Where do you keep up to date code?
Here GitHub - ComputerNerd/ov7670-simple: This is a simple sample code of the ov7670 on the arduino uno sends data over serial. and here GitHub - ComputerNerd/arduino-camera-tft: Arduino Mega 2560 code that uses either an OV7670 or an MT9D111 to display an image on a TFT LCD screen with SD card support. also if you don't have any other parts besides the ov7670 check out GitHub - ComputerNerd/ov7670-no-ram-arduino-uno: Allows you to use a non fifo ov7670 on the arudino uno without external spi ram like other examples. Sends the data to UART. it also contains how to enable PWM to get 8mhz.
I also made a data converter that allows you to convert raw data from the camera into a PNG file
GitHub - ComputerNerd/RawCamera-data-converter: This program was made to convert raw data from the ov7670 to a png file. It may also work with other cameras.
For windows users here is a binary.
RawCamera-data-converter/convert.exe.7z at master · ComputerNerd/RawCamera-data-converter · GitHub
I also posted some pastebin links that is old code but it covers some stuff that the code above does not
How I can I help the author?
Responding to you all guys does not happen magically. There are some things you can do to help ensure that I will continue to help you.

  1. Give back: Know something that I don't know regarding the OV7670? Post it.
  2. Avoid asking repeat questions.
  3. Write stuff. Maybe you can explain something better than I can. If that is the case please do such. I am always open to suggestions on how I can improving my writing.

Hello, I would like to see your connection in detail. I want the camera to be used in image processing by arduino.

Thanks for answer and sorry for my English. Nice job.

As I cannot have a post over 9000 characters I had to move down the first and second version of this post:

Second revision:
Edit: I now recommend the fifo version over the non-fifo version. However if you have the regular version without the fifo you can still get an image using external spi ram.
If you have the fifo version lots of this is still relevant all except the external ram part and reading pixels.
The reason for using the fifo version is because of faster readout and you can capture a 640x480 images without breaking it up into pieces however to do such you must use raw bayer data.
Also I have since figured out how to generate an 8mhz clock using PWM
Using PWM to generate XCLK has several advantages including:
You don't need a special programmer to set the fuse bits.
You can change the output clock speed the fastest it goes is F_CPU/2 which results in 8mhz in the case of the arduino. However it is best to set it as max speed and use the divider that the ov7670 has.
Also a good way to keep filesize down thus improving transfer speed is to use raw bayer data.
Raw bayer appears to be about the same or better quality as yuv422 but takes half the speed thus doubling transfer speed.
I would recommend you use it instead of yuv422 I have posted new versions that use raw bayer data.
Here is an FAQ of some questions that may come up:
Q: Some arduino outputs a 5v clock but the OV7670 will only accept 3.3v what should I do
A: use a buffer of some sort it just needs to be fast enough to pass the 8mhz signal.
Q: Will the ov7670 accept twi/sccb/i2c (same thing different names) commands without XCLK?
A: No
Q: Will I need to buffer any other pins besides the XCLK?
A: No but be sure you have the i2c/twi/sccb lines pulled up to 3.3v instead of 5v or you risk damage to the ov7670
Also don't set any of the pins that go to the ov7670 as output.
Q: where can I get current registers and useful functions for the ov7670?
A: On my github page GitHub - ComputerNerd/arduino-camera-tft: Arduino Mega 2560 code that uses either an OV7670 or an MT9D111 to display an image on a TFT LCD screen with SD card support.
More specifically here is some stat-up registers here arduino-camera-tft/ov7670_regs.h at master · ComputerNerd/arduino-camera-tft · GitHub
And here are some useful functions here arduino-camera-tft/twicam.c at master · ComputerNerd/arduino-camera-tft · GitHub also don't forget the header file arduino-camera-tft/twicam.h at master · ComputerNerd/arduino-camera-tft · GitHub
And you will notice that I have vga qvga rgb565 yuv422 defined somewhere else that is here arduino-camera-tft/config.h at master · ComputerNerd/arduino-camera-tft · GitHub
Q: the code you posted runs on the arduino mega but I have an arduino uno what can I do?
A; The functions that setup the camera will also work on the arduino uno and I have posted some code for the arduino uno see the pastebin links below or my github page ov7670-simple (link below)
Q: The code you posted (above) is complex give me something more simple
A: For a while I had this code available I just thought I would make it more obvious that it exists. GitHub - ComputerNerd/ov7670-simple: This is a simple sample code of the ov7670 on the arduino uno sends data over serial.
Q: The FAQ does not answer my question what should I do
A: try reading through this topic your question might be answered if not post a reply I'd rather that you not send a pm because someone else may have the same question that you do later on.

First revision:

I have recently been working with the ov7670 unfortunately I made the mistake of cheeping out and buying the cheaper one without the fifo. At first I though it would be a challenge to get this to work but it turns out not to be that hard at all. The problems: the arudino does not have enough ram and is slow additionally it runs on 5v when both the ov7670 and the sd card need 3.3v. The solutions. Break the image into smaller pieces and transfer the smaller pieces into spi ram in this case I have the 23LC1024 128kb of ram that means if I want a vga image 6404802 bytes per pixel. I must divide it into 5 equal parts. So I transfer part of the image and save that part into the sd card and do this for a total of 5 times each time skipping different regions and saving others. The sensor can output both rgb565 or yuv422 I found that yuv422 is better quality so I made a converter for that and you can get the source code here GitHub - ComputerNerd/RawCamera-data-converter: This program was made to convert raw data from the ov7670 to a png file. It may also work with other cameras.. Here is code for the capture program. ov7670 arduino uno example code - Pastebin.com I used sdfatlib to write and based my code off of his fastlogger code. Note that by defining useLed using #define useLed will assume you have an led on pin 0 and a button on pin 1 to stop the capture hold down the button and wait for the led to blink very fast make sure that the button sinks the pin to ground. If you do not define useLed then it uses serial to start stop image send one letter to the arduino and it will save 1 image you can send more for more images. Also Note that I found some registers online somewhere and I could not find documentation on those registers. The only ov7670 datasheet that I could find online does not explain all the registers it gives the name but the description is blank. If someone could explain with a reply or PM what these:

    wrReg(AWBC7,0x88);
    wrReg(AWBC8,0x88);
    wrReg(AWBC9,0x44);
    wrReg(AWBC10,0x67);
    wrReg(AWBC11,0x49);
    wrReg(AWBC12,0x0e);
	wrReg(REG_GFIX,0x00);
	//wrReg(GGAIN,0x40);
    wrReg(AWBCTR3,0x0a);
    wrReg(AWBCTR2,0x55);
    wrReg(AWBCTR1,0x11);
    wrReg(AWBCTR0,0x9f);
	wrReg(0xb0,0x84);//not sure what this does

registers do that would be awesome.
To solve the 5v issue I use a buffer. To solve the fact that the arduino is slow I set the divider to 9 also I am getting the clock with the CLKOUT pin you will have to change your fuse settings for that. Also for twi communication the ov7670 is picky about what pullup resistor values you use I found 4.7k and 10k to work. I tried 1k and 2.2k and those do NOT work. You will need twi to write to the registers the image out is parallel. Here are some images taken with the ov7670.


Here is the arduino uno itself. Image is very large click here to view http://imageshack.com/a/img849/4632/zuvj.jpg

Below here lies my response (the original aspect of the post).

The connections are simple. Start by plugging in SIO_C to A5 and SIO_D to A4 since this is i2c/twi you must have a 4k7 resistor 10k also works. Make sure you have the resistor to pull up 3.3v not 5v. Also edit twi.c in the arduino ide folder/libraries/Wire/utility search for these lines and comment them out or remove them

 // activate internal pullups for twi.
  digitalWrite(SDA, 1);
  digitalWrite(SCL, 1);

This is to remove the internel pullup resistor by not removing these 2 lines you could cause damage to the sensor. Then plug d7 to digital pin 7 d6 to 6 d5 to 5 d4 to 4 d3 to A3 d2 to A2 d1 to A1 and d0 to A0 now plug in VSYNC to digital pin 3 and PCLK to pin 2. Now change the fuse bits to be exactly the same except enable the CLKOUT pin. This will output a clock run this through a buffer or level shifter to 3.3v if you do not get the 5v signal down to 3.3v it could damage the sensor. The sd card and spi ram is just standard spi wiring nothing special.

Thanks for the answer, I will try. :slight_smile: :slight_smile:

I wish you the best of luck if anything does not work right just reply and I will help you.

Could you post a photo of your device sometime ? I got one of these and the connections were so tiny that
I could not see then with a magnifying glass and certainly not actually connect anything to them.

Hi,
I'm working on a project at university about computer vision and Arduino.
I'm trying to capture an image using Arduino Uno and OV7670 camera without FIFO. Other components like SD card, LCD, additional RAM, shields, etc. are unfortunately not available at this time (I've read some tutorials about this, but they were using special shields or some stuff I don't have or camera with FIFO...).
Is it possible to directly communicate with camera from Arduino and get some images? It doesn't have to be fast, the point is to get some results.

Since I'm just a beginner with Arduino, I'm a little bit confused about how to connect my camera to it, when I don't use RAM that was mentioned above. I really don't want to damage it...
Could you please describe it or provide some connection schema for a case like mine? Could you please also give me some advice how to change the code for the capture program?

Any help is appreciated.

michinyon I bought an ov7670 camera module that means some of the pins are routed to a 2.54mm pitch header I think you have bought just the sensor. I am busy right now I will take a picture soon.
Saren it is possible I will have to get back with you on this one though. I am busy right now and don't have any code written right now for using no ram. I do however have a program that is compiled with avr-gcc that sends the image to a frame grabber program that I wrote.
Here is the sender program it is in 3 files main.c ov7670.h ov7670.c
main.c:

I will warn you that I made some changes to the code but forgot to change the comments like the captureImg function says it missed a byte but now it does not I posted it to paste bin before realising this.
ov7670.h

ov7670.c

Here is the frame grabber source code

This one is only one file. If on Gnu/Linux you will need to install the development package of SDL or if gentoo just emerge sdl. If on windows get the development library from Simple DirectMedia Layer - SDL version 1.2.15 (historic)
Also I made an update to my program that captures an image to the sd card it nows saves raw bayer data.
ov7670 raw bayer capture arduino uno - Pastebin.com
The link is different than the previous code that I posted.
Here is a program to debayer/demosaic the data it is still in very beta needs work
It will also convert yuv422 to rgb (the old image to sd card program saved data in that format)

//to compile type gcc -Wall -Wextra -lm -lpng -o yuv main.c
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <png.h>
#include <zlib.h>
#include <sys/stat.h>
#define img_w 640
#define img_w_2 1280
#define img_h 480
#define CLIP(X) ( (X) > 255 ? 255 : (X) < 0 ? 0 : X)
#define C(Y) ( (Y) - 16  )
#define D(U) ( (U) - 128 )
#define E(V) ( (V) - 128 )
#define YUV2R(Y, U, V) CLIP(( 298 * C(Y)              + 409 * E(V) + 128) >> 8)
#define YUV2G(Y, U, V) CLIP(( 298 * C(Y) - 100 * D(U) - 208 * E(V) + 128) >> 8)
#define YUV2B(Y, U, V) CLIP(( 298 * C(Y) + 516 * D(U)              + 128) >> 8)
char buf[1024];
void showHelp()
{
	puts("Yuv422 raw image data to png");
	puts("-n x replace x with the image number you want to convert");
	puts("-h shows this help file");
	puts("-o x replace x with a real integer between 0 and 7 this sets the offset");
}
int savePNG(char * fileName,uint32_t width,uint32_t height,void * ptr)
{
	//saves a 24bit png with rgb byte order
	png_byte * dat=ptr;//convert to uint8_t
	//png_byte **row_pointers = malloc(height*sizeof(png_byte));
	//if (row_pointers==0)
	//	return 1;
	FILE * fp=fopen(fileName,"wb");
	if (fp==0)
		return 1;
	png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (png_voidp)0,0,0);
	if (!png_ptr)
		return 1;
	png_infop info_ptr = png_create_info_struct(png_ptr);
	if (!info_ptr)
	{
		png_destroy_write_struct(&png_ptr,(png_infopp)NULL);
		return 1;
	}
	if (setjmp(png_jmpbuf(png_ptr)))
	{
		png_destroy_write_struct(&png_ptr, &info_ptr);
		fclose(fp);
		return 1;
	}
	png_init_io(png_ptr, fp);
	png_set_IHDR(png_ptr, info_ptr, width, height,8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);//must be called before other png_set_*() functions
	//png_set_compression_level(png_ptr,Z_BEST_COMPRESSION);//since we are doing timelapses we may be dealing with many files it is good to keep disk space usage down
	uint32_t y;
	//for (y=0;y<height;y++)
	//	row_pointers[y]=&dat[(y*width*3)];//the rows are contiguous
	png_set_user_limits(png_ptr, width, height);
	png_write_info(png_ptr, info_ptr);
	//puts("saving data 2");
	//png_write_image(png_ptr, row_pointers);
	for (y=0;y<height;y++)
		png_write_row(png_ptr, &dat[(y*width*3)]);
	//png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
	png_write_end(png_ptr, info_ptr);
	png_destroy_write_struct(&png_ptr, &info_ptr);
	//free(row_pointers);
	fclose(fp);//done with file
	return 0;//will return 0 on success non-zero in error
}
void yuv2rgb(uint8_t * yuvDat,uint8_t * out)
{
	uint64_t xy;
	for (xy=0;xy<(img_w/2)*img_h;xy++)
	{
		*out++=YUV2R(yuvDat[0],yuvDat[1],yuvDat[3]);
		*out++=YUV2G(yuvDat[0],yuvDat[1],yuvDat[3]);
		*out++=YUV2B(yuvDat[0],yuvDat[1],yuvDat[3]);
		*out++=YUV2R(yuvDat[2],yuvDat[1],yuvDat[3]);
		*out++=YUV2G(yuvDat[2],yuvDat[1],yuvDat[3]);
		*out++=YUV2B(yuvDat[2],yuvDat[1],yuvDat[3]);
		yuvDat+=4;
	}
}
void deBayerN(uint8_t * in,uint8_t * out)
{
	uint32_t x,y;
	for (y=0;y<img_h;y+=2)
	{
		for (x=0;x<img_w;x+=2)
		{
			//this will do a 2x2 pixel rectangle
			/*R G
			  G B*/
			out[(x*3)]=in[x];//copy red 
			out[(x*3)+1]=in[x+1];//green
			out[(x*3)+2]=in[x+1+img_w];//blue
			
			out[(x*3)+3]=in[x];//red
			out[(x*3)+4]=in[x+1];//green		
			out[(x*3)+5]=in[x+1+img_w];//blue

			out[((x+img_w)*3)]=in[x];//red
			out[((x+img_w)*3)+1]=in[x+img_w];//green
			out[((x+img_w)*3)+2]=in[x+1+img_w];//blue

			out[((x+img_w)*3)+3]=in[x];//red
			out[((x+img_w)*3)+4]=in[x+img_w];//green
			out[((x+img_w)*3)+5]=in[x+img_w+1];//blue
		}
		out+=img_w*6;
		in+=img_w*2;
	}
}
void deBayerL (uint8_t * in,uint8_t * out)
{//this is an implementation of http://www.ipol.im/pub/art/2011/g_mhcd/
	uint32_t x,y;
	for (y=0;y<img_h;y+=2)
	{
		for (x=0;x<img_w;x+=2)
		{
			//this will do a 2x2 pixel rectangle
			/* B Gb
			   Gr R
			*/
			/*R G THIS IS WRONG BUT STANDARD The rows are reversed on omnivision sensors keep this in mind later just get alg working for now
			  G B*/
			//if (x>=2 && x<=img_w-2 && y>=2 && y<=img_h-2)//see if we are able to grab pixels from neighboors
			//{
				//printf("X %d Y %d x-img_w %d\n",x,y,x-img_w);
				out[x*3]=in[x];//red just needs to be copied
				//out[(x*3)+1]=((in[x]*4)+(in[x-1]*2)+(in[x+1]*2)+(*(in+x-img_w)*2)+(in[x+img_w]*2)-(in[x-2])-(in[x+2])-(*(in+x-img_w_2))-in[x+img_w_2])/8;//green at red locations
				//out[(x*3)+2]=((in[x]*6)+(*(in+x-1-img_w)*2)+(*(in+x+1-img_w)*2)+(*(in+x-1+img_w)*2)+(in[x+1+img_w]*2)-(in[x-2]/3*2)-(in[x+2]/3*2)-(*(in+x-img_w_2)/3*2)-(in[x+img_w_2]/3*2))/8;//Blue at red
				
				//out[(x*3)+4]=
				out[(x*3)+4]=in[x+1];//copy green

				out[((img_w+x)*3)+1]=in[x+img_w];//copy green

				out[((img_w+x)*3)+5]=in[x+img_w+1];//copy blue
			/*}
			else//we are on the edge defualt to edge safe algorthim
			{
				out[(x*3)]=in[x];//copy red 
				out[(x*3)+1]=in[x+1];//green
				out[(x*3)+2]=in[x+1+img_w];//blue
			
				out[(x*3)+3]=in[x];//red
				out[(x*3)+4]=in[x+1];//green		
				out[(x*3)+5]=in[x+1+img_w];//blue

				out[((x+img_w)*3)]=in[x];//red
				out[((x+img_w)*3)+1]=in[x+img_w];//green
				out[((x+img_w)*3)+2]=in[x+1+img_w];//blue

				out[((x+img_w)*3)+3]=in[x];//red
				out[((x+img_w)*3)+4]=in[x+img_w];//green
				out[((x+img_w)*3)+5]=in[x+img_w+1];//blue
			}*/
		}
		out+=img_w*6;
		in+=img_w*2;
	}
}
uint8_t readImg(uint32_t num,uint8_t * dat)
{
	sprintf(buf,"F%d.YUV",num);
	FILE * myfile = fopen(buf,"rb");
	if (myfile==0)
	{
		printf("Cannot open file %s\n",buf);
		return 1;
	}
	fread(dat,2,img_w*img_h,myfile);
	fclose(myfile);
	return 0;
}
uint8_t processImg(uint8_t * in,uint8_t * out,uint32_t num,uint8_t alg,uint16_t offset)
{
	if (readImg(num,in))
		return 1;
	uint32_t w,h;
	switch (alg)
	{
	case 2:
		deBayerL(in+offset,out);//linear
	break;
	case 1:
		deBayerN(in+offset,out);//nearest neighboor low quality try to avoid using
	break;
	case 0:
		yuv2rgb(in+offset,out);
	break;
	default:
		puts("You must pick an algorithm to save the image as");
		return 1;
	}
	sprintf(buf,"frame %d.png",num);
	if (savePNG(buf,img_w,img_h,out))
	{
		return 1;
		puts("Error while saving PNG");
	}
	return 0;
}
int main(int argc,char ** argv)
{
	uint8_t useNum=0;
	uint32_t useImg;
	uint16_t offset=0;
	uint8_t debayer=1;
	if (argc>1)
	{
		//handle arguments
		int arg;
		for (arg=0;arg<argc;arg++)
		{
			if (strcmp(argv[arg],"-n") == 0)
			{
				arg++;
				useImg=atoi(argv[arg]);
				useNum=1;
				continue;
			}
			if (strcmp(argv[arg],"-o") == 0)
			{
				arg++;
				offset=atoi(argv[arg]);
				if (offset>img_w)
				{
					printf("you must specify a number between 0 and %d for argument -o\n",img_w);
					showHelp();
					return 1;
				}
				continue;
			}
			if (strcmp(argv[arg],"-h") == 0)
			{
				showHelp();
				continue;
			}
		}
	}
	uint8_t * Dat;//in case some of the file was not saved we use calloc instead of malloc to garentte that the unsaved pixels are set to 0
	if (debayer!=0)
		Dat = calloc(img_w*img_h+img_w,1);
	else
		Dat = calloc(img_w*img_h+img_w,2);
	uint8_t * outImg = malloc(img_w*img_h*3);//all bytes in the array will be overwritten no need for calloc
	if (useNum)
	{
		processImg(Dat,outImg,useImg,debayer,offset);
	}
	else
	{
		uint32_t imgC;
		for (;;imgC++)
		{
			printf("Saving image %d\n",imgC);
			if (processImg(Dat,outImg,imgC,debayer,offset))
				return 1;
		}
	}
	free(Dat);
	free(outImg);
	return 0;
}

I forget that. I bought the camera ov7670 fifo.
Sorry and thank you so much.

nonzung:
I forget that. I bought the camera ov7670 fifo.
Sorry and thank you so much.

Smart choice the one with the fifo is much better I wish I would have bought it but I bought the one without the fifo.

Mr_arduino: I didn't have much time lately, but now I'm going to try it. I have some questions about connection:

  1. You mentioned that it's necessary to get the 5V signal down to 3.3V. Is it possible to do this without level shifter/buffer or do I have to get this stuff?
  2. Are connections the same (as in one of your posts) even in my case (without RAM, etc)?

Thanks for your effort to help. I really appreciate it :slight_smile:

The connections will be mostly the same but it could be abit different as I do not own the one with the fifo I am not sure but I think instead of PCLK you use RCLK and and RCLK is output you strobe that to get data. Check you this for more info about the fifo version http://wiki.beyondlogic.org/index.php/OV7670_Camera_Module_with_AL422_FIFO_Theory_of_Operation Also you could try a resistor divider but I have heard that they are too slow you may need a buffer/level-shiftier. Also this would not require the ram as you have the fifo.

A recent discovery that I made is you can get an F_CPU/2 (8mhz in the arduino's case) clock output with pwm this removes the need to edit fuse bits. Note that this is for the arduino mega 2560 I switched to from the uno to the mega recently. This will work with the arduino uno also just change the timer number.

 DDRL|=8;
 ASSR &= ~(_BV(EXCLK) | _BV(AS2));
 //generate 8mhz clock
TCCR5A =67;
TCCR5B=17;

Also change DDRL to proper port and pin or be lazy and replace with pinMode();

There's a good page on generating clock signals at Introduction to timers [tutorial part 6] | HeKilledMyWire

I too have the question about level shifting; what sort of buffers are needed, would a 74HC245 do?

I think the 74HC245 would work just fine also a unidirectional one would work too. Pretty much any buffer that is fast enough to handle a 16mhz signal and can accept 3.3v as a supply voltage which the 74HC245 can. You do not need to shift the d7-d0 as those are always output from the sensor and never input. Only the clock signal needs to go though the buffer as that is an input and the sd card if you are using it. From twi just disable internal pullup resistors and have them to 3.3v instead of 5v. Also I think I may have forgot to mention that RESET needs to be tided to 3.3v and PWDN to ground or you could use more GPIO pins if you need to use the PWDN and RESET features although a reset can also be triggered by writing to a register so driving that pin with the arduino has little purpose.

Thanks, that's very helpful. I'd thought that the D0..D7 signals would need shifting and so lots of converters would be needed, but that's simplified things a lot. Still waiting for my camera to turn up.

Mr_arduino:
The connections will be mostly the same but it could be abit different as I do not own the one with the fifo I am not sure but I think instead of PCLK you use RCLK and and RCLK is output you strobe that to get data. Check you this for more info about the fifo version OV7670 Camera Module with AL422 FIFO Theory of Operation - BeyondLogic Also you could try a resistor divider but I have heard that they are too slow you may need a buffer/level-shiftier. Also this would not require the ram as you have the fifo.

I think there has been a misunderstanding. My camera is without fifo...

Saren:
I think there has been a misunderstanding. My camera is without fifo...

So is mine so will need the same connections as I use and the external sram. Also the reason d0-d7 not need shifting is the arduino will never drive those pins so it is up to you to make sure that those pins are always set to input on the arduino.

Hi, i have the ov7670 camera, an arduino uno rev 3 and ST M27C512-12F1 Eprom. Is it possible to take pictures with these components? and if so, how do i connect them together. i have seen that you used the spi ram, can i replace that with the eprom??
Please assist me on how to connect the arduino, camera and the eprom together to give me a picture.

This is the old school eprom with UV erase. There are several reason why this would not work. First of all how are you going to erase it in a reasonable time. Even if you had a UV led driven by the arduino it would still take awhile to erase and UV is bad for your eyes so you would need to cover it with something. Also you would not have enough pins are the eprom is parallel. Also how fast are the write speed will it even accept data fast enough. Another problem is that you would wear it out fast. Eproms only have a certain amount of writes (They do have unlimited reads though). Also this Eprom has only 64kb of memory you would have to break the frame up even more which would reduce performance even more. In short the Eprom would not work for this purpose save it for repairing a bios or make your own NES cartridge or do something fun with it but not in a camera. Just buy or sample the 23LC1024 it is kinda cheap at $2.59 if you only order one at digi-key and you will not regret it. It is even in dip package. The dip package one is called 23LC1024-I/P by the way