Step-By-Step: OV7670 Camera with Arduino: 10FPS Video
You can buy very cheap OV7670 camera modules from Banggood, eBay, or Aliexpress.
Getting them to work with an Arduino can be quite complicated. It requires a lot of connections and precise timing on the software side.
This article is a step-by-step guide for building all the necessary connections on a breadboard. Then you can use my example code to run a 10fps video live stream on a tiny display.
After completing my tutorial, you should end up with something like this:
This video clip is a short demo of the camera in action. In this video, you see a PCB version of the same circuit presented in this article.
To follow this tutorial, you need:
- An Arduino (Uno/Nano) or Arduino compatible board
- The OV7670 camera module (without the FIFO chip)
- The 1.8 inch TFT module
- A breadboard
- Two 10kΩ resistors for the I2C connection to the camera. Six pairs of 650Ω and 1kΩ resistors for signal voltage dividers.
- A bunch of jumper wires: male to male and male to female
A step-by-step guide in video form. It has the same schematics I am using in this article.
1. Preparing the Screen
Short the J1 connector on the back of the screen. Then the VCC pin of the display can be connected to the 3.3V pin of the Arduino board.
When I started experimenting with the 1.8 inch TFT, I had faint vertical stripes going across the screen. By default, the screen is configured to be powered by 5V, but internally it operates at 3.3V levels. I was able to get rid of those ghosting lines by using 3.3V data signals (with voltage dividers) and switching the power input over to 3.3V.
2. Connecting the 1.8 Inch TFT to Arduino
The input pins of the 1.8 inch TFT screen are not 5V tolerant. You have to convert the Arduino 5V signals to 3V. The easiest way to achieve that is to put voltage dividers on the signal wires.
The full schematic for the connections looks like a rat's nest and is a bit hard to follow. I have divided it into steps to make it easier. Click on the buttons to switch between the schematics.
Add a Voltage divider to every connection made in steps 1 to 5.
Step 1. Connect the screen pin 1 (RST) to the Arduino pin 10.
This is the reset pin. It is used by the Adafruit library when initializing the screen.
Step 2. Connect the screen pin 2 (CS) to the Arduino pin 9.
Chip select pin. Signal LOW – the screen is active and listening to the SPI port. Signal HIGH – the screen ignores all the data on the SPI wire.
Step 3. Connect the screen pin 3 (D/C) to the Arduino pin 8.
Data/Configuration pin. You can send either pixel data (image to be displayed) or configuration data (color format, screen orientation, etc.). Input HIGH is for sending pixel data and LOW for sending configuration.
Step 4. Connect the screen pin 4 (DIN) to the Arduino pin 11.
SPI data input pin. The screen is listening to the SPI port if the CS pin is LOW.
Step 5. Connect the screen pin 5 (CLK) to the Arduino pin 13.
SPI clock pin. The screen is listening to the SPI port if the CS pin is LOW.
Step 6. Connect the screen power pins. The pins 6 (VCC) and 7 (BL) to the Arduino 3.3V pin. The screen pin 8 (GND) to the Arduino GND pin.
Pin 7 is the signal to activate the backlight. We connect it to the 3.3V, so the display is always lit. The Arduino could control it, but in this project, we need all the other Arduino pins for the camera connections.
Pins 6 and 8 are power pins for the screen. Since we shorted the J1 connector, we need to use 3.3V input for the VCC.
3. Test the Screen Connections
You should test the screen wiring before continuing with connecting the camera.
1. Download the code of my LiveOV7670 project:
Click on the green "Clone or download" button and then "Download ZIP."
Extract the downloaded ZIP file.
2. Copy the two libraries "LiveOV7670Library" and "Adafruit_GFX_Library" from "src/lib" to your Arduino "libraries" folder
"LiveOV7670Library" contains the code that communicates with the OV7670 camera module.
"Adafruit_GFX_Library" is a dependency of the "Adafruit-ST7735" screen library. In this project, I am using a modified version of the Adafruit's ST7735 library – "Adafruit_ST7735_mod.h" and "Adafruit_ST7735_mod.cpp" in the "src/LiveOV7670" folder. The original was too slow. To get it faster, I had to cut some corners in the method that sends pixel data to the display.
3. Open "src/LiveOV7670/LiveOV7670.ino" and load it into your Arduino.
This project takes advantage of some of the C++11 features. C++11 is enabled by default since Arduino IDE version 1.6.6. If, for some reason, you have an older version, then you should either upgrade or enable C++11 in the Arduino IDE configuration file.
4. If everything is connected correctly, then the screen should flash red.
The solid red color means that the code wasn't able to detect the camera module. But since we see the color, we can be sure that the screen wiring is OK.
If you do not see the red image, then check your wiring, and make sure that you have shorted the J1 connector on the back of the screen.
4. First Part of the Camera Connections – Power It Up
We will do the camera wiring in two phases. In this chapter, we are going to make all the necessary connections to get the camera running and configured by the Arduino.
Step 1. Make a voltage divider from the Arduino pin 3 to the XCLK pin of the camera.
Similarly to the screen, the camera module is not 5V tolerant. This is the only connection that needs a voltage divider on the camera side. It's the single digital output signal from Arduino to the OV7670 module (all the other ones are inputs for the Arduino).
XCLK is the input clock that makes the camera run. The maximum frequency that Arduino can put out is 8Mhz. For full speed, the camera module needs 30Mhz, but eight is enough to display ten frames per second image.
Step 2. Make the I2C connections. Arduino pin A5 to SIOC and Arduino pin A4 to SIOD. Then add a 10k pull-up resistors to 3.3V to both of the wires (A5 to 10k to 3.3V, A4 to 10k to 3.3V).
I2C is necessary for sending configuration data to the camera (resolution, pixel format, etc.).
Step 3. VSYNC to Arduino pin 2.
It's a 3.3V signal from the camera to the Arduino. This connection can be made directly without a voltage divider.
We need vertical sync to know when a new frame begins. Otherwise, it looks to Arduino like a constant pixel stream with no start or end.
Step 4. PCLK to Arduino pin 12.
This is also a 3.3V signal from the camera to the Arduino and can be connected directly.
Pixel cock is necessary for knowing the exact time when to read pixel data.
Step 5. Connect power to the camera. From Arduino 3.3V pin to the camera's 3.3V input and from Arduino GND pin to the camera's GND.
Step 6. Connect the camera's RESET pin to 3.3V and PWDN to GND.
Reset pin could be used to reset the camera module and power down to turn it off. But since we don't have any left-over pins, we let it run all the time.
5. Validate That the Camera is Running
This is the second test before we get to the actual images from the camera.
When you start the Arduino again, then it should flash a green screen. This means that the LiveOV7670 library was able to detect and configure the camera successfully.
You can't see any images yet since the pixel data pins are not connected.
If you still see the red screen, then check the wiring. Make sure that the XCLK wire isn't too long. The square wave of the input clock signal to the camera may become too deformed for it to operate correctly.
6. Second Part of the Camera Connections – Pixel Data Pins
Now we can finish the camera wiring by connecting pixel data inputs. Pixels are streamed from the camera one byte at the time. Each pixel consists of two bytes that are read sequentially.
Step 1. Connect Camera's D0 to D3 to the Arduino pins A0 to A3.
These are the lower four bits of a pixel byte.
Step 2. Connect Camera's D4 to D7 to the Arduino pins 4 to 7.
These are the higher four bits of a pixel byte.
Now you can power up your Arduino again. It starts with a green image like in the previous test. Then you should see a live video streamed from the camera to the display.