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 agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.