OV7670 with both arduino uno and now mega

Hello, lately I tried to make my OV7670 camera work with Arduino Uno and read entire 30 pages to find solution for my problem since it doesnt work. It shows nothing (camera is definately working)
http://postimg.org/image/yfnwtxz3h/
Heres is photo of camera and Arduino.
Also used this schematic


And this code from Mr_Arduino example. Also didnt forgot to include other stuff like stdint.h and others.

Any suggestions.

Mr_arduino:
Edit I had to move down the first revision of my inital post to here to work ardound a character limition below that I explained how I conntect the ov7670 to the arduino uno.
Here is the my old original post below kept for historical reasons:

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.
![](http://img812.imageshack.us/img812/696/v5w6.png)
![](http://img51.imageshack.us/img51/7659/blinds.png)
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.

(Sorry, my english is not the best)
I dont understand something, i need to put a resistor in the sioc and the sioc?

I have to connect the Arduino to the camera, but I do not know how to display images on the computer to determine the camera is working or not, I need to show a simple software to connect to the Arduino Uno. my english is bad, sorry about that

OK, I have read a lot through these pages. I believe my connections are right. But I am new to Arduino environment and couldn't figure out what is wrong with my code, because I keep getting compilation errors. I am trying to use a version of the code that Mr. Arduino presented. (code of: ov7670-no-ram-arduino-uno-master)

I am sure I imported the right libraries. How should I redeclare these functions?

And these are the errors I got:

sketch_dec01a.ino: In function 'int main()':
sketch_dec01a.ino:121:9: error: 'camInit' was not declared in this scope
sketch_dec01a.ino:123:8: error: 'vga' was not declared in this scope
sketch_dec01a.ino:123:11: error: 'setRes' was not declared in this scope
sketch_dec01a.ino:124:10: error: 'bayerRGB' was not declared in this scope
sketch_dec01a.ino:124:18: error: 'setColor' was not declared in this scope
Error compiling.

Hello everyone, I read through the whole topic, and I spent the past few hours researching a precise documentation or tutorial on how to connect OV7670 with FIFO to an Arduino UNO. Unfortunately, I am still quite confused.

All I would like to do at this stage is to capture frames from the camera and display them on a Mac app. I am quite proficient on the software side, but I am not clear on how to connect the camera module to the Arduino board.

Can anyone provide me with a Fritzing file or a clear photo of a similar setup? I mainly need to understand whether I should use a resistor between some pins. I don't want to damage the board or the camera.

Here is a photo of my OV7670_FIFO module: http://cl.ly/image/0P3B1T1w0O3V

I know that this question sounds like a repeated one, but despite all the information on this thread, it's really not clear how to use this module. I am not a complete beginner at this and I haven't been able to figure it out after hours of research. Once I get this working, I am going to put together some very precise documentation and code examples on how to use it for posterity.

Thank you for your assistance!

Wow I cannot keep up. I feel burnt out so to say. I would like to help you, taylanpince since you seem like one who would be good at creating precise documentation and hopefully others with questions can read that first.

hi all! I have a similar problem of shaileshswankhede talked about in the previous page.

I'm using arduino uno v3 with 18 pin no sram ov7670 camera module. (even without spi external ram)
wired as described in the readme found with the code I'm using (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.)
to convert pin11 from 5v to 3.3v to wire it up in xclk, I used a voltage divider with the following configuration
pin11 -> 4.7Kohm -> xclk pin -> 10Kohm -> arduino gnd
nothing else (no divider on sioc/siod)

the code hangs in
twiStart -> while (!(TWCR & (1 << TWINT)));
twiWriteByte -> while (!(TWCR & (1 << TWINT)));
twiAddr -> while ((TWCR & _BV(TWINT)) == 0);
if I comment out those lines it gets in the following if condition (fail).
if I comment out all the wrReg function it gets strange random colours (so the module isn't completely dead)

I'm sure I'm missing something stupid :slight_smile:
thank you!

I presume you solely went by the README file and did not notice on the first page that you needed pullup resistors on A5 and A4. I updated the README to fix this issue.

good! I put my wires in this order: A5 -> SIOC -> 10K -> arduino 3v3 (same for A4 pin) and now it passes the "wait for start" point in the three previous functions but I get half white pictures from the camera (attached)
I tried 4k7 and 10k resistors but I get quite same result.
I'm using 57600 baud rate (UBRR0L = 34;), realterm for capturing and your convert.exe to convert the captured terminal output (removing "RDY" string).

I used this scheme to connect my pullups resistor

what seem strange to me is the "ÿ" sequence of chars (should be 0xff) and the fact that I get a file of 24.576 bytes while 640x480 = 307.200 :astonished:

p.s. felt honored you fixed the readme for me :smiley: (just kidding). Thank you for the help!

4k7pullup.png

10kpullup.png

capture.txt (22.1 KB)

The baud rate you are using is too slow to keep up with the image rate I have the ov7670 set to output. If you want to use a slower baud rate you will need to mess with register 0x11 which is the clock divider using a larger value will make data output at a slower rate. I have found best results using a baud rate of 1Mbaud. Also your schematic is correct and it is good that you got very similar results when using both 4.7k and 10k that is what is supposed to happen. SIOC and SIOD are connections only for I2C which is used only to "configure" the camera.

this is what i get at 1M baud (attachment 1). it looks like the image is "almost" complete and the black part is the "non-written" part.

could it be by the clock "slipping" due to the voltage divider I put up on the XCLK?
could it be because I need a voltage divider AND a pullup resistor on the XCLK?

the second attachment is what I get without connecting RESET and PWDN.

1Mbaud.png

1Mbaud_noRESET_noPWDN.png

It looks like you are missing a few bytes every line. I am not sure what the cause it. I will note my code is very timing dependent. If you suspect that this is a signal integrity issue check the clock frequency with an oscilloscope.

ok I have good news!

  1. I don't have an oscilloscope yet: I'm trying to understand my requirements about it. For example, I read that if I want to analyze a 16Mhz frequency like in this case I need almost three times faster ADC sampler to have an error under 5%;
    So a 50Mhz oscilloscope would be good but the cost is over 250€ and I don't want to spend so much to discover after a couple of projects that it's not sufficent to suit my needs. I'm studying to make the right buy :slight_smile:

  2. I thought during my previous tests I burned the sensor using the wire library so I switched to a new one and I got a plausible (distorted) image. I think the voltage divider is ok for low freq but at high freq the signal has not enough time to overcome the parasite currents; I dealt with this recently when I used a voltage divider to plug the micro sd module to arduino UNO. full speed -> nada / half speed -> only partition spec / quarter speed -> full compatibility. Nevertheless on the due it gets full speed because it's directly plugged (which is why my next thing to do is to port the module on the DUE and plug it directly). I don't know if the sensor is burned but I'll check better one day.

  3. Mr_arduino I saw you used 74AHC125 buffer to step down to 3v3. It seems a nice solution... what about voltage regulator to step down? shouldn't it be faster? is there any case which a 74AHC125 would not fit to step up/down voltage levels?

  4. on the left you can see a strange band: to me it looks like the signal is "slipping" because of the voltage divider (I think/hope that's the reason also for the other artifacts)

  5. It seems like the sensor "suffer" of so called "eye adaptation": the first frames are white (highly exposed) and then it "adapts" the exposure. I made a short video of 100 frames palyed at 10fps in which you could notice that. - YouTube

  6. I made a little windows utils that split the terminal recorded file into n.RAW files. if someone is interested let me know and I'll post it with source code.

next stop: DUE!

p.s. Mr_arduino I read you started to work on the ov5642 module! it looks cool! how's doing?

p.p.s. just for the record: you are seing my chair and my electronic drum rotated by 90 deg.s :smiley: (random subject)

p.p.p.s. I changed the RDY to RDY because RDY collide causing wrong split (if based on characters) o.O (for everyone: in the captured data can happen "RDY" char sequence: it happened to me 115 times in the same capture of 100 frames XD)

frame 0.png

frame 1.png

frame 2.png

frame 3.png

I personally purchased a used oscilloscope from a university. It was cheap but that comes at the cost of one of the channels not working. I have yet to look at the issue however the other channel works very good. You don't have to pay too much depending on what you buy.
I would be sorry for you burning out your sensor except I have a warning on the first page telling you to remove two lines of code that are part of the Wire library. However I made the same mistake when I first got my ov7670 and my ov7670 still works even i2c. I do not think a voltage regulator would be faster. Voltage regulators are designed to output a stable voltage. The best way to find out would be to read the datasheet and test it. Also yes the ov7670 does auto exposure which is nice to have. If you want you can make it faster if you don't like the default speed.

Finally I got clean images at low speed ( wrReg(0x11, 63); ) so I decided to move the project to the DUE.

for the oscilloscope I think I'll go for the RIGOL DS1102E which seems to be a good oscilloscope to start with, also because suits also this case and I should be good at least until frequency at 33Mhz.
I'm going to open a thread soon asking for a couple of advices :slight_smile:

Auto exposure it's ok for me but I feel to advise other users that the first few frames taken could be over-exposed! (thought might be the issue of the user vvavepacket)

If you did output 5v and didn't burn, shouldn't I also. I think might be the light or dust on the sensor when I take out the lens to see how the sensor looks like.
I doubt it's screwed. I'll check when I'll finish the port on the DUE, speaking of which:

I wired DUE like so for now
SCL -> SIOC (10Kohm to 3v3)
SDA -> SIOD (10Kohm to 3v3)
PIN7 -> XCLK
3v3 -> 3v3
GND -> GND
and nothing more, just to see if this little devil answer.
to generate the clock on the DUE I found many techniques which involves PWM.
I liked this because it can achieve the highest possible PWM on the DUE which is a clean 84Mhz waveform,
but I didn't know if setting

uint32_t pwmPin = 7;
uint32_t maxDutyCount = 2;
uint32_t clkAFreq = 20000000ul;
uint32_t pwmFreq = 20000000ul;

was enough to get a 20 Mhz clock on pin 7 for the camera module.
So I tryied this other code which I found here ~10MHz clock generation with the Due - Arduino Due - Arduino Forum which I'm (quite) sure generate a 10.5Mhz clock;
the OV7670 say that wrReg is ok but when I try to read the registers it answer that the value is 0 (with three different methods).
I also tried the pwm01 library which is an "official" alpha library to generate a pwm on the DUE but it seems ok until 100000hz, then "Serial.print" screw up and begins to throw out random stuff.

BEWARE! only pin 6, 7, 8, 9 can be used for PWM on the DUE!

#include <Arduino.h>
#include <Wire.h>

#define camAddr_WR		0x42
#define camAddr_RD		0x43
#define REGISTERS       0x91        // Define # of Registesr on OV7076

byte wrReg(unsigned char regID, unsigned char regDat){
	Wire.beginTransmission(camAddr_WR >> 1);
	Wire.write(regID);
	Wire.write(regDat);
	if (Wire.endTransmission()){
		return 0;
		while (1);
	}
	delay(1);
	return 1;
}

void readRegisterBank()
{
	uint8_t count = 0x12;
	int address = 0x12;

	Wire.beginTransmission(camAddr_WR);
	Wire.write(address);
	Wire.endTransmission();
	Wire.requestFrom(camAddr_RD, 1);
	while (!Wire.available())
	{
	}
	int c = Wire.read();
	Serial.println(c);

	//while (count<REGISTERS)
	//{
		byte highByte = 0;
		Serial.print("\r\n Register num: ");
		Serial.print(count, HEX);
		Serial.print(" val: ");
		Wire.beginTransmission(camAddr_WR);          //Start communication with cmps03
		Wire.write(count);                        //Send the register we wish to read
		Wire.endTransmission();
		Wire.requestFrom(camAddr_RD, 1);             //Request high byte
		while (Wire.available() < 1);              //While there is a byte to receive
		highByte = Wire.read();                   //Read the byte as an integer
		Serial.print(highByte, HEX);
		delay(25);
		//count++;
	//}

	Serial.print("\r\n Register num: ");
	Serial.print(count, HEX);
	Serial.print(" val: ");
	Wire.beginTransmission(camAddr_WR);
	Wire.write(count);
	Wire.endTransmission();
	Wire.requestFrom(camAddr_RD, 2);
	byte LSB = Wire.read();
	byte MSB = Wire.read();
	uint16_t touched = ((MSB << 8) | LSB); //16bits that make up the touch states
	Serial.print(touched);

	Wire.beginTransmission((uint8_t)camAddr_WR);
	Wire.write(count);
	Wire.endTransmission(false);

	Wire.requestFrom((uint8_t)camAddr_RD, (uint8_t)1, (uint8_t)true);

	if (Wire.available() >= 1)
	{
		int result = Wire.read();
		Serial.println(result, HEX);
	}
}

void setup() {
	int32_t mask_PWM_pin = digitalPinToBitMask(7);
	REG_PMC_PCER1 = 1 << 4;               // activate clock for PWM controller
	REG_PIOC_PDR |= mask_PWM_pin;  // activate peripheral functions for pin (disables all PIO functionality)
	REG_PIOC_ABSR |= mask_PWM_pin; // choose peripheral option B    
	REG_PWM_CLK = 0;                     // choose clock rate, 0 -> full MCLK as reference 84MHz
	REG_PWM_CMR6 = 0 << 9;             // select clock and polarity for PWM channel (pin7) -> (CPOL = 0)
	REG_PWM_CPRD6 = 8;                // initialize PWM period -> T = value/84MHz (value: up to 16bit), value=8 -> 10.5MHz
	REG_PWM_CDTY6 = 4;                // initialize duty cycle, REG_PWM_CPRD6 / value = duty cycle, for 8/4 = 50%
	REG_PWM_ENA = 1 << 6;               // enable PWM on PWM channel (pin 7 = PWML6)

	Serial.begin(115200);
	Wire.begin();
	Serial.print("wrReg: "); Serial.println((wrReg(0x12, 0x80)));
	delay(1000);
	readRegisterBank();
}

void loop()
{
}

I know that the camera has already been ported on the DUE by user aturcitu but I didn't like he used
#define RCLK_SET PIOC->PIO_SODR=1<<15
#define RCLK_CLR PIOC->PIO_CODR=1<<15
because in the previous article I linked states that with this technique (slightly different) you can reach 16.8 Mhz. It looks like an hack to me. I want to use wire library (disabling internal pullups) and the SAM PWM to generate the clock to unleash the full potential of the OV7670 and then try to move to the ov5642 with an 8M sram module (hoping DUE keep up)

when I get the camera working with DUE I'm willing to make a C# program to toggle the settings of the module runtime so you don't need to recompile each time and allow you to see the register settings change in real-time.

Mr_Arduino thank you for your time and your patience which allow other user to grow their knowledge!

Mr_arduino:
Wow I cannot keep up. I feel burnt out so to say. I would like to help you, taylanpince since you seem like one who would be good at creating precise documentation and hopefully others with questions can read that first.

Hi Mr_arduino, I am sorry to hear that you feel burnt out. Hope you feel better soon!

I made some progress over the holidays. I now have the OV7670 FIFO module working with a test Mac application, rendering the color bars. Unfortunately it doesn't look completely right.

Here is the latest image I have: http://cl.ly/image/283b1V3R2B3F

And here is my current implementation: OV7670 FIFO SCCB · GitHub

I assume this is related to my current configuration settings. My current implementation is heavily influenced by Arndt Jenssen's version here: GitHub - arndtjenssen/ov7670: OV7670+fifo camera control with an AVR ATmega1284

Any help anyone can give me is much appreciated. Thanks and happy new year!

@taylanpince: I know user drkblog in the first pages got the fifo module working with uno. you could find your answer there :wink:

EvIl_DeViL:
@taylanpince: I know user drkblog in the first pages got the fifo module working with uno. you could find your answer there :wink:

Thanks! I am actually in contact with him and he has been super helpful. Unfortunately it seems like the FIFO module isn't the most useful one. I am going to try reading the data from FIFO to SRAM since I can't get it out to Serial without dropping below 1mhz.

I'll report back if I am successful. :slight_smile:

Looking at your code there are many changes that need to made not all of which relate to if you get a correct image or not but there are many choices in your code that is making reading slower.
First of all make functions used only in the same source code file static. This allows for best constant propagation and allows the compiler to do more extensive optimizations based on usage of the function.
Second of all read_one_byte is not inline so there may be function call overhead.
The third and hugest mistake is all the conversions you are doing on the arduino that should be done on the PC. That is horrible for performance. Do not do yuv422->rgb888 on the arduino. There is no advantage of doing so and it wastes many CPU cycles when they are needed. It also increases the amount of bytes you need to send which makes the transfer even slower. Your PC in contrast has plenty of extra cpu time to do yuv422->rgb888. Also you should not use floating point math on the AVR and expect high performance. The compiler will generate software floating point code which is slower than if you had an FPU to do such work which your computer does. Try fixed point math instead.
The reason you are getting a weird deformed image is due to the fact that you are not correctly doing yuv422 to rgb. To properly do yuv422 -> rgb you need to read four bytes which I shall call y1,u,v,y2 then you do (this is in pseudo code)

pixel1=yuvToRgb(y1,u,v);
pixel2=yuvToRgb(y2,u,v);

So for every four bytes you get two pixels. It would be a good idea to rewrite your capturing code to just send the data without any conversions. Also I cannot tell but it looks like you convert the pixel to ASCII. Do not do that it just waste CPU time. You will need to convert it back anyway so why not just send the byte and then read the byte on the PC.
Also I looked at your post Saving a pin with 23LCV1024 on SPI mode - Networking, Protocols, and Devices - Arduino Forum and it reveals that you may have two different solutions mixed up together. When you are using the fifo there isn't really a need for any external ram. The fifo already stores an image in it's own memory. So on the ov7670 camera module pcb do you see an IC that contains the words AL422? If so you do not need SPI ram. You can read the pixels are whatever rate needed. Even then if you just want to send pixel data on the serial port and you do not have a fifo you can still just send the pixels as they arrive. The external ram is needed if you want to save the image to an SD card and you do not have a FIFO. I hope this helps. If not post what happens when you make these changes I suggest.

Mr_arduino:
Looking at your code there are many changes that need to made not all of which relate to if you get a correct image or not but there are many choices in your code that is making reading slower.
First of all make functions used only in the same source code file static. This allows for best constant propagation and allows the compiler to do more extensive optimizations based on usage of the function.
Second of all read_one_byte is not inline so there may be function call overhead.
The third and hugest mistake is all the conversions you are doing on the arduino that should be done on the PC. That is horrible for performance. Do not do yuv422->rgb888 on the arduino. There is no advantage of doing so and it wastes many CPU cycles when they are needed. It also increases the amount of bytes you need to send which makes the transfer even slower. Your PC in contrast has plenty of extra cpu time to do yuv422->rgb888. Also you should not use floating point math on the AVR and expect high performance. The compiler will generate software floating point code which is slower than if you had an FPU to do such work which your computer does. Try fixed point math instead.
The reason you are getting a weird deformed image is due to the fact that you are not correctly doing yuv422 to rgb. To properly do yuv422 -> rgb you need to read four bytes which I shall call y1,u,v,y2 then you do (this is in pseudo code)

pixel1=yuvToRgb(y1,u,v);

pixel2=yuvToRgb(y2,u,v);



So for every four bytes you get two pixels. It would be a good idea to rewrite your capturing code to just send the data without any conversions. Also I cannot tell but it looks like you convert the pixel to ASCII. Do not do that it just waste CPU time. You will need to convert it back anyway so why not just send the byte and then read the byte on the PC.
Also I looked at your post http://forum.arduino.cc/index.php?topic=288933 and it reveals that you may have two different solutions mixed up together. When you are using the fifo there isn't really a need for any external ram. The fifo already stores an image in it's own memory. So on the ov7670 camera module pcb do you see an IC that contains the words AL422? If so you do not need SPI ram. You can read the pixels are whatever rate needed. Even then if you just want to send pixel data on the serial port and you do not have a fifo you can still just send the pixels as they arrive. The external ram is needed if you want to save the image to an SD card and you do not have a FIFO. I hope this helps. If not post what happens when you make these changes I suggest.

Mr_arduino, thank you for your detailed response. I spoke about this at length with drkblog, who had experimented with the FIFO version earlier. He specifically mentioned that I can never get the data fast enough out of FIFO to the serial. I tried everything, including transferring bytes directly and I used your direct to serial code for this. I also integrated your raw image converter into a Mac app so it's all done on the Mac side where it makes more sense. Unfortunately, none of it works with the module I have.

I'm aware that this version of the code is not even close to being optimized. However, it's also the first version that rendered color bars on my Mac app. That said drkblog thinks that this is misleading, it's still sending corrupt data.

After 2 weeks of trying to make this work with the OV7670 FIFO module with Arduino UNO, I'm giving up. I got a MEGA today and I will be pushing the data from FIFO to SRAM and reading from there. I couldn't do this on UNO since I am 1 pin short.

Between my own experiments and drkblog' comments, I'm convinced that the FIFO module is inferior to non-FIFO. I just couldn't find a way to read from AL422B fast enough out to serial.

I'll report here again when I hooefully make this work with MEGA.