OV7670 with both arduino uno and now mega

I'm trying to stay within the Arduino because I have already solved other requirements with it. And it would be a lot of work migrating other stuff to Raspberry Pi, for example. I want to keep this as simple as possible, also. Raspberry Pi is awesome but it's a complexity level above Arduino, you have a whole operating system there, as far as I know. And that leads to some side effects.
So, for this project I'm trying to stay in this platform, even knowing that Raspberry would solve the camera issue with ease. Anyway, I would like to know whatever comes out of your testing. You never know when you will have to implement the Plan B. :slight_smile:

The problem with the raspberry pi is interrupts the arduino has nothing going other than what the program does. Also the arduino takes less power and does not get hot. For MT9D11 that I am working on I have tried getting it to work but I keep missing pixels. I will have to write a linux driver that way I can disable interrupts while taking the picture but I still have a whiles away to go before doing that. Also what I meant by my previous post is that I do not have the fifo version as I already have enough sensors to play with though I am still willing to help with the fifo version. But I think your goal of 5-8fps is possible. Using sdfatlib you get write to the sd card really fast if you create a contiguous file first then using the writeData() function that saves 512 bytes at a time.

Yes. I read the program you wrote, which creates the contiguous block first, the writes down the information. I don't even have to worry about the format, as I will have to write the software which is going to read the SD on the PC for downloading information from my device. That will save me some overhead that could have if I were to write an AVI or MPEG file.
I will post here as soon as I start testing the FIFO version. By the way, where are you from?

I am from the USA. Why do you ask is it related to my posting abilities? I did just notice a mistake in my previous post that made it not make sense. Also speaking of contiguous files actually creating the contiguous file is slow so try creating a big file then re-sizing it.

haha no, I just asked out of curiosity. Don't worry I didn't see any non-sense in your posts. And, in the end, It's a forum. We aren't writing a book here :slight_smile:

Besides, knowing the place you are from, I have an idea how easy is to access technology for you. For example, here in Argentina it is hard to get some components. I had to buy the RAM 23LC1024 at Mouser in USA and send it to a friend who was vacationing in Boston. So he brought it back here. Otherwise I would have paid 100USD shipping for an order of 20 bucks, which is senseless.
Fortunately, we have a several big shops here were you can find a lot of stuff. Even some rare pieces. But there is some stuff we have to buy in USA, Hong Kong, China. Specially for testing purposes.

International shipping can be expensive It is annoying when shipping cost make up a high percentage of the order. Lots of chinese ebay sellers offer free shipping is that you mean by buying from Hong Kong? I do that alot for modules also they have much better deals on zif sockets.

I'm new to all this electronics stuff and finally coming to terms with my inner nerd. Lol, I've fallen in love with the idea of creating things that anyone can use . I bought an ov7670 on ebay a few weeks back and after reading this thread, I'm completely in the dark. So, I was hoping you could shed some light on some things for me?

Obviously, you're using C to code all this, but do you know of any tutorials that will help me learn about registers? I get that you call them with hex, though hex and bin math are way over my head, I kinda sorta follow it.

Im absorbing as much as i can through google/wikipedia as often as i can and picking up any book i can find on arduino and coding it. I understand the basics of it and it feels very comfortable, so switching over to C right now would be a bit much.

I've only been doing the whole electronics thing for about a month, so I really don't understand a lot of the components, so bare with me.

You mentioned early on that you added the ram to speed up the data transfer. How long did it take to write to the SD card without the memory? Breaking it up into 5 blocks was still faster? How can that be?

Thanks in advance for the help and patience. So many people I've seen online said it was impossible to use this camera, but then I found one Guy who shared a link, but it was in Russian or something, so I couldn't even read it to find out more. I've seen in this thread and another one that not only have you gotten it to work, you understand how it works. Teach me, oh great and powerful Oz!

EDIT-- I should add, I understand I can just use your code, but it does me no good if I don't understand why it does what it does. I'm sure it would get me by, and I might even plug it all in tomorrow just to see if the thing works, but I'd really like to understand it so I can write my own code. I seem to learn better by doing.

Hello xKoldFuzionx, welcome to the electronics world. :slight_smile:

Your questions is a little too broad to cover it up in one reply, so I guess I'm going to start with some basic stuff:

To really understand what's going on here, you will have to give it a lot of time. And you will have to start from the beginning. This module is really hard to get working, and is too complex if you don't even know about C. My first recommendation would be that you start experimenting with simpler circuits.

As you should know by now, Arduino is an experimental board with a microcontroller. Even when the specific microcontroller may vary, as well as its machine code. The Arduino family share an interface for programming it using C or C++. I haven't seen anyone using another language for Arduino, which doesn't mean there isn't. But all the stuff I came across is written in C/C++. So, for the sake of simplicity let's say that you program Ardunio in C/C++.

Here are the terms what I think you should start learning about:

  • Ohm law, diode, transistor (as a switch, at least), power dissipation
  • Binary logic (from the logical and electrical point of view)
  • Logical gates
  • Microcontroller (or microprocessor, or CPU) and DSP
  • Memories
  • Parallel interface
  • Serial interface
  • I2C and SPI interfaces

And then, you will learn about registers when reading about microcontrollers and memories.

Sorry for such a broad question. But, greatly appreciate the input.

I understand ohm's law, the fTransistors e books I started to read drilled it into me, though I don't entirely understand it's use. Let me clarify. I understand the V=IR, I=V/R, R=V/I, but I don't get the power part of it(the Watts).

I understand simple diodes that block current, but zener diodes confuse me as to how they work.

Transistors, I get the idea of them, but they confuse me and no text I've read so far seems to simplify it enough.

By binary logic, you just mean the basic 1 == high, 0 == low? I get that it's like a switch(1 is on, 0 is off), sending a pulse of 5v for high, 0v for low. I was also just reading the math of the base 2 system. Is there more behind the logic?

Logic gates was something I was also just trying to read about, but I felt like it was completely over my head. The problem I have with reading this stuff is I don't see it in action. I'm a very mechanically inclined person. I can usually look at something, watch it function and figure out how it works. Computers/electronics are hidden, so I use EveryCircuit on my phone a lot to simulate circuits to see how they function. I haven't experimented with that stuff on there yet, but I may start today after seeing some of the stuff I was reading.

I don't want to buy another camera module as they're all so dang expensive. I was excited to buy this one for less than $4. I'm unemployed right now, so money is a big issue. But, I was hoping throwing myself into this would help me learn. I don't expect to get it working overnight, but within a year would be great.

As for the other stuff to look up, thanks. I'll be reading up on that stuff very soon.

I guess, I was just really hoping(as I've read so far) that the Arduino language was all I needed to learn, but I guess knowing c/c++ is needed in almost all of Arduino, huh?

In the first place you have to accept that learning electronics isn't easy. Specially if you want to really know what is going on there. A degree in electronics takes 5 or 6 years, at least in Argentina. Being realistic and pragmatic, you have to accept some things as they are given. You won't be able to see a circuit working like a mechanical device. You have to learn what components do under certain circumstances and then apply that knowledge. Having that in mind:

All you mind about power is P = V x I ~~ P [Watt]= V [Volt] x I [Ampere]

And you have to check that your components have a standard power dissipation. If you place the under certain current and voltage, and that multiplication results in more Watts than this component tolerates, you will break it. You can even forget about power dissipation until you start breaking components :slight_smile:

You have to learn about the transistor as a switch [Transistor - Wikipedia]

When you make a small current flow through the base, the collector-emitter juncture behaves like a cable (conducting). When the base current disappears, the collector-emitter is like an open switch (not conducting). You can think of it like a switch controlled by an electrical signal, instead of a human hand. Don't even try to understand why the transistor do this. At least by now.

Yes, logic is implemented in circuits using 5V or zero volt. But that's a convention and depends whether you are using TTL or CMOS, you can use a different value, like 3.3V (very common today). And you can't easily mix this kind of signals, if you connect a 5V output to a 3.3V input you will likely damage the device. Unless otherwise stated in the datasheet.

Logical gates are predecessors to microprocessors, but of course, they are widely used today. Again, you have to learn its behavior as an enclosed unit. You don't need to learn how they work inside. If you have an two-input AND gate, you will get a 1 at the output if and only if you have 1 at the two inputs. A practical use could be: "You have a digital output from arduino and another digital output from a light sensor. You have a 1 from the sensor if there is light detected. And you want to turn a LED on and off according to the sensor BUT, you want to turn the LED off from the Arduni at any given time. If you connect the led to the sensor it will work all the time, and Arduni won't be able to turn the LED off. Then you place a AND gate connecting the sensor and the arduino output to its input and the LED to the gate output. Now, if the Arduino output is 1, the LED will turn on and off according to the sensor. But if Arudino's output is 0, then the LED will be off no matter if the sensor outputs a 1 or a 0".

You can connect the module you bought according to the circuits and code from this post. Making it work isn't easy anyway. And you are working with a 3.3V module, so be careful about the outputs from Arduino going into the camera inputs. You could damage the sensor forever. If money is an issue, I would recommend you start playing with cheaper stuff. So you can understand what you are doing. And you start by breaking cheaper things. It's really unusual you start learning electronics without burning some stuff.

Do you have an oscilloscope?

Ok, I understand that, but with an Arduino, why would I ever need to use a transistor or a gate. Through code, I can program the same actions. For instance:

[quote]
if ((12 == HIGH) && (10 == HIGH))
{
    digitalWrite(13, HIGH);
}
else
{
    digitalWrite(13, LOW);
}
[/quote]

Obviously, you would have to program something to trigger 12 or ten to go high, but you get it.

In essence, isn't that the whole point of having a Microcontroller? One component does the job of many?

No, I don't have an oscilloscope. Used one once, but that's the closest I've gotten. I know it would be invaluable, but just can't swing it right now.

First note that a transistor is not a logical gate, and you can't replace one by another because they have different functionality. Of course, you can build a logical gate using one or more transistors and resistors, but stick to the idea that they aren't the same.

Said that, I placed an example (an excuse) for using a logical gate, it doesn't matter if you can solve it with an Arduino. But if you want to play hard, let's say that you have all I/O pins used in your arduino and you have only one left for the problem I presented before. Will you buy another Arduino for doing something you can solve with a single logical gate of USD 0.50?

And for the transistor as a switch, let's say you have to turn a DC motor on and off with an arduino output. You have two motors A and B. Motor A works with 5V and uses 150mA, and motor B works with 12V and uses 30mA. You can't connect A to an output because Arduino supports 40mA (maximum) current per IO pin. If you connect motor A you will break the IO or the whole Arduino. You can't connect motor B neither because you have to provide it with 12V and IO pin outputs 5V. Both cases can be solved using a transistor suited for the work. Transistor have parameters of maximum current also. So you have to check that.

There is a couple of projects for building a low-budget oscilloscope using an Arduino, you can google that but here is a link: Google Code Archive - Long-term storage for Google Code Project Hosting.

Ok, that makes complete sense. All the example sketches I've worked through so far have just been really basic as far as components. So, say motor A has a transistor hooked up to it(just so I can get this straight) the 5v pin would connect to the base, 12v supply to the collector and motor's positive wire connected to the emitter? Then, when high, it electrically flips the switch allowing the 12v through? Then in that case, would you hook up a 12v supply to a regulator then the Arduino, and and a lead from +12v to the collector?

And yeah, I see what you mean with the gate. It makes a lot more sense to use that rather than buy another Arduino just to do the same thing.

Ok, so one more thing, can you recommend any good beginner's electronics books that are simple but cover everything in a good amount of detail?

You will have to do something like this:

The base resistor limits the base current when there is 5V on it. The base current will be (Vcc - Vbe) / R, in this case (5V - 0.7V) / 1k? = 4.3mA which is enough for 100mA current between collector and emitter. How much current you need in the base for a given collector-emitter current, comes out from figute 3 in this datasheet: Micro Commercial Components 548B datasheet pdf

The diode is a protection which prevents the inverse current generated inside the motor when it's turned on. Such diode is needed when you are switching an inductor/coil on and off (a motor, a relay, etc), to protect the transistor.

Hey all,

I've been using this thread to try and get my OV7670 working, and I seem to have hit a roadblock. Currently, my images mostly look similar to this: http://imgur.com/SoKGYNP

I'm using this to get my 8Mhz clock down to 3.3v https://www.sparkfun.com/products/8745 (generated on pin 10 using fast pwm).

I'm setting reg. 0x11 to 0x03, which is giving me a 250khz PCLK, although I have tried other values - 0x01 to 0x09

I'm using this code to set up the camera for QCIF (176x144) mode with YUYV422 color.

  writeReg(0x15, 32);  // PCLK does not toggle on HBLANK COM10 vsync falling

  writeReg(REG_TSLB, 0x04); // 0D = UYVY, 04 = YUYV
  writeReg(REG_COM13, 0x88); // with REG_TSLB

  writeReg(REG_COM7, 0x08);
  writeReg(REG_COM17, 0x00);
  writeReg(REG_COM15, 0xC0);
  writeReg(REG_COM3, 0x08);

The full test code for image capture I'm using is here:

I should note that at the moment I'm attempting to capture the image and send it over serial using only the 2k sram on the arduino (this is just a proof of concept until I can get ahold of some external ram). Therefore, I have to break the image up into 36 chunks or so, but I don't see any reason why it shouldn't be possible - just really slow.

Any help would be greatly appreciated. I can provide more detail as well if necessary.

In the first place you have to be sure your cam is working. If you have a problem with the clock you are feeding, you will waste a lot of time. In my case, I used the 16MHz clock from Arduino and I feed it right into the camera, because at 16MHz you don't have 5V signal. You should check with an oscilloscope to see what's the real amplitude of your 8MHz clock. To see if the camera is working you have to check the PCLK output.
If you don't have an oscilloscope, I would recommend you check PCLK using a frequency meter. You have to be sure the module is working. After that, capture covering the camera lens to get a frame of a black image. You should see these chain of bytes: 80 00 80 00 80....

Thanks for the response.
I do think the camera is working. I'm able to read and write to registers, and from my oscilloscope it seems like VSYNC is going high at a reasonable rate. I'm also able to see the PCLK output, which is 250khz when reg 0x11 is set to 0x03. Here is a picture of the oscilloscope when measuring the PCLK: http://imgur.com/YQhWI8d

Actually, I just noticed the peak to peak is ~5v, and the min/max are -1.8v/3.6v - is that bad?

Here is the signal going into the OV7670 XCLK: http://imgur.com/syTEAat

When I try to capture with the lens covered I get mostly 00 00 00... and sometimes some garbage.

Out of curiosity, how would I go about getting the 16Mhz arduino clock output? I've never burned a bootloader and I only have a usb connector, can I do it with just that?

Ok, if the module is working, and you are able to read/write registers you are almost done. The next hard-to-do thing is, configuring all the undocumented registers. If you fail to do that, you won't get the camera working. You can be sure about that.

You MUST write all the registers in ov7670_default_regs[] and then those in ov7670_fmt_yuv422[] :

Also, start by getting PCLK as low as possible first. As far as I remember I wasn't able to get a good reading with REG_CLKRC under 20 (decimal). But, I'm feeding 16MHz clock and you have half this clock, which makes you PCLK half mine when using the same divider in REG_CLKRC. So (I'm totally guessing here), you should be able to make it work with REG_CLKRC set at 10. The reading code has to be as quick as possible and you have to use cli() before start reading. Please post the portion of code you are using to read from the camera.

For burning fuses I needed a second Ardunio, with a program called ISP http://arduino.cc/en/Tutorial/ArduinoISP but I wouldn't recommend that approach for this project. Using 8MHz clock is simpler and better. Yet, it's the limit for OV7670, you won't be able to make it work with less than that. As the datasheet says the minimum clock should be 10MHz.

About the 10mhz limit. I don't think that is true I have left the ov7670 on with an 8mhz clock for hours and nothing bad has happened. Also I have looked at other new sensors from omnivision datasheets to see if I can figure out what the undocumented registers mean and most of the newer datasheets say 6mhz is the lower limit for the clock. Usually overclocking is more dangerous than under-clocking.
Actually I made some corrections to the linux driver registers. Also the code I have on my github page uses divider settings is for people with the 8mhz clock. I have posted about the registers on my github page before but I have sense made some changes. Here are the files you need.
arduino-camera-tft/config.h at master · ComputerNerd/arduino-camera-tft · GitHub change #define MT9D111 to #define ov7670
arduino-camera-tft/twicam.c at master · ComputerNerd/arduino-camera-tft · GitHub update the function void errorD(uint8_t err) for your hardware for example send the string error over serial instead of displaying it on the lcd screen or you can just remove that function. Also remove the code that hflips the image. That is specific to the tft screen I am using if you are not sending it to the seeedstudio v1 lcd screen you don't want the image hfliped.
arduino-camera-tft/twicam.h at master · ComputerNerd/arduino-camera-tft · GitHub can be used as is but must be used if you use twicam.c
arduino-camera-tft/captureimage.c at master · ComputerNerd/arduino-camera-tft · GitHub Here is an example of how to capture an image there are many different functions for different resolutions. change PINE&32 to where ever your VSYNC pin is also change PINE&16 to where ever the PCLK output is also change the code that sends the data to the tft screen to were ever you are sending it. Once you have adapted those files to your system you can call the function setRes(); and use the defines in config.h for example setRes(qvga); sets the resolution to 320x240. When calling initCam() You also have a choice of 3 different register presets (0 1 and 2). I would recommend doing initCam(0); that seems to work best. Also you have setColor() I would recommend yuv422 for qvga and qqvga by calling it with setColor(yuv422);. For vga I would recomend bayer call it with setColor(bayerRGB). rgb565 is very low quality only use it if you are sending to a tft screen that uses rgb565 data.

@drkblog

Ok, I'm going to spend some time making sure my register setup is correct. I saw a few tutorials that didn't seem to bother with the defaults (such as this http://embeddedprogrammer.blogspot.com/2012/07/hacking-ov7670-camera-module-sccb-cheat.html ), which is why I didn't spend too much time on it before.

Here is the code I'm using to capture very small chunks from the camera (small enough to fit in arduino SRAM, so ~4 QCIF lines at a time).

void captureChunk(unsigned long wait, unsigned long chunk, uint8_t *pixels) {
  unsigned int n = 0;
  while(!(PIND & 8)) {} // Wait for VSYNC high
  while(PIND & 8) {} // Wait for VSYNC low

  while(wait--) {
    while(!(PIND & 4)) {};
    while(PIND & 4) {};
  }
  while(chunk--) {
    while(!(PIND & 4)) {};
    pixels[n++] = (uint8_t)((PINC & 0x0F) | (PIND & 0xF0));
    while(PIND & 4) {};
  }
 //.... write to serial 
}

@Mr_arduino
I'll look through that, thanks for the link. Is there any particular reason to use custom twi functions instead of the built in Wire library? I'm able to read and write registers using that at the moment. Also, would you happen to have a link for a newer version of the datasheet? I'm using this one right now: http://www.eleparts.co.kr/data/design/product_file/Board/OV7670_CMOS.pdf