I recently started working on an security camera system, with an arduino uno and an OV7670 camera without FIFO memory, and an ESP-8266 to transfer the images to a webserver. Everything is working, except this:

The problem: My camera takes the images (QVGA resolution) twice every time, and collapse them into one image.

My images looks like this:


One (240*320) QVGA image is built by two (120*320) half image. My camera takes the two images AFTER each other, not just duplicates the first part.

(After I got one line of the image ready I send it with SoftwareSerial to ESP8266, and that send it forward...)

I'm trying to changeing the scaling registers with different combinations, without success.

I followed this tutorial at the beginning, and modified its code. https://hkalasua.wordpress.com/2017/09/11/ov7670-arduino-sd/

Arduino code:

#include <Wire.h>
#include <SoftwareSerial.h>

SoftwareSerial ESPserial(10, 11); // RX | TX

void Init_YUV422(){
  WriteOV7670(0x12, 0x00);//COM7
  WriteOV7670(0x8C, 0x00);//RGB444
  WriteOV7670(0x04, 0x00);//COM1
  WriteOV7670(0x40, 0xC0);//COM15
  WriteOV7670(0x14, 0x6A);//COM9
  WriteOV7670(0x3D, 0x40);//COM13

void Init_QVGA(){
  WriteOV7670(0x0C, 0x04);//COM3 - Enable Scaling
  WriteOV7670(0x3E, 0x19);//COM14
  WriteOV7670(0x72, 0x11);//
  WriteOV7670(0x73, 0xF1);//
  WriteOV7670(0x17, 0x16);//HSTART
  WriteOV7670(0x18, 0x04);//HSTOP
  WriteOV7670(0x32, 0xA4);//HREF
  WriteOV7670(0x19, 0x02);//VSTART
  WriteOV7670(0x1A, 0x7A);//VSTOP
  WriteOV7670(0x03, 0x0A);//VREF
  WriteOV7670(0x70, 0x00);//SCALING_YSC


void Init_OV7670() {
  //Reset All Register Values
  WriteOV7670(0x12, 0x80);

  WriteOV7670(0x3A, 0x04); //TSLB

  WriteOV7670(0x13, 0xC0); //COM8
  WriteOV7670(0x00, 0x00); //GAIN
  WriteOV7670(0x10, 0x00); //AECH
  WriteOV7670(0x0D, 0x40); //COM4
  WriteOV7670(0x14, 0x18); //COM9
  WriteOV7670(0x24, 0x95); //AEW
  WriteOV7670(0x25, 0x33); //AEB
  WriteOV7670(0x13, 0xC5); //COM8
  WriteOV7670(0x6A, 0x40); //GGAIN
  WriteOV7670(0x01, 0x40); //BLUE
  WriteOV7670(0x02, 0x60); //RED
  WriteOV7670(0x13, 0xC7); //COM8
  WriteOV7670(0x41, 0x08); //COM16
  WriteOV7670(0x15, 0x20); //COM10 - PCLK does not toggle on HBLANK

void WriteOV7670(byte regID, byte regVal) {
  // Slave 7-bit address is 0x21.
  // R/W bit set automatically by Wire functions
  // dont write 0x42 or 0x43 for slave address
  // Reset all register values


void ReadOV7670(byte regID) {
  // Reading from a register is done in two steps
  // Step 1: Write register address to the slave
  // from which data is to be read.
  Wire.beginTransmission(0x21); // 7-bit Slave address
  Wire.write(regID);  // reading from register 0x11

  // Step 2: Read 1 byte from Slave
  Wire.requestFrom(0x21, 1);
  Serial.print("Read request Status:");
  Serial.print(regID, HEX);
  Serial.println(Wire.read(), HEX);

void XCLK_SETUP(void) {
  pinMode(9, OUTPUT); //Set pin 9 to output

  //Initialize timer 1

  //WGM13, WGM12, WGM11 & WGM10 bits SET- Fast PWM mode
  //COM1A0 SET- Toggle OC1A on compare match
  TCCR1A = (1 << COM1A0) | (1 << WGM11) | (1 << WGM10);
  //SET CS10 bit for clock select with no prescaling
  TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS10);
  //Output Compare Register 1A(OCR1A) = 0
  //This will lead to a match on every clock cycle
  //Toggle OC1A output pin on every match instance
  //Therefore, the generated waveform will have half
  //the frequency of the driving clock i.e. 8Mhz
  //OC1A pin- PB1 (alternate functn) pin i.e. Arduino pin 9
  OCR1A = 0;


// Two Wire Interface Setup
// Sets the frequency of the SCL line
// Default is 100KHz so we won't use this function
void TWI_SETUP(void) {
  //Set prescaler bits in TWI Status Register (TWSR) to 0
  TWSR &= ~3;
  //Set SCL frequency to 100KHz
  //SCLfreq = CPUfreq/(16 + 2(TWBR) - 4^(TWPS))
  //TWBR = 72, TWPS(prescaler) = 0
  TWBR = 72;


void OV7670_PINS(void) {
  //Setup Data input pins and Interrupt pins
  //DDRC bits 3:0 = 0 =>  bits configured as Data Inputs
  //DDRC 3:0 - A3,A2,A1,A0
  DDRC &= ~15;//low d0-d3 camera

  //~(0b11111100) = 0b00000011
  //make DDRD 7:2 = 0 => Inputs
  //d7-d4 as data inputs, d3-INT1 is VSYNC and d2-INT0 is PCLK
  DDRD &= ~252;

void QVGA_Image() {
  int h, w;

  while (!(PIND & 8));//wait for high
  while ((PIND & 8));//wait for low

  byte dataBuffer[320];

  h = 240;
  while (h--) {
    w = 320 ;

    while (w--) {
      while ((PIND & 4));   //wait for low
      dataBuffer[319 - w] = (PINC & 15) | (PIND & 240);
      while (!(PIND & 4));  //wait for high
      while ((PIND & 4));   //wait for low
      while (!(PIND & 4));  //wait for high

    //sendig the line to ESP
    ESPserial.write(dataBuffer, 320);


void setup() {
   noInterrupts(); //Disable all interrupts
  XCLK_SETUP();   //Setup 8MHz clock at pin 11
  OV7670_PINS();  // Setup Data-in and interrupt pins from camera
  TWI_SETUP();    // Setup SCL for 100KHz

  WriteOV7670(0x11, 0x1F); //Range 00-1F
  // noInterrupts();



void loop() {
 /* ..Not relevant for this problem.. */

I'd be very greatful, if you can help!.. ...this is a really annoying problem..

  • and modified its code - what did you change? - besides adding WriteOV7670(0x70, 0x00); – Jaromanda X Dec 23 '18 at 2:12
  • nothing special, I just removed the SD card parts, and inserted the serial commmunication with the ESP. I didn't change the register values except that. – DP19 Dec 23 '18 at 19:10
  • and what does that register do? – Jaromanda X Dec 23 '18 at 22:27

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Browse other questions tagged or ask your own question.