Taking pictures with an OV7670 on Arduino Uno not working correctly

Hello, I am trying to take a picture with my ov7670 camera module. in the first step, I am trying to print out the pixel values via the Serial Terminal. If I then convert the pixel values to an actual picture, the output looks like this:

#include <Wire.h>

#define CAMERA_ADDRESS 0x21

// Definitions of functions for manipulating the Arduino boards pins according to each Arduino board registers, so the code will work for both Arduino UNO and Arduino MEGA:
// The only change is the connections of the SDA/SIOD, SCL/SIOC and MCLK/XCLK pins to each board (see the pins configurations above).
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) // If you are using Arduino MEGA the IDE will automatically define the "__AVR_ATmega1280__" or "__AVR_ATmega2560__" constants.
#define TIMER2_PWM_A_PIN_MODE_OUTPUT() ({ DDRB |= 0b00010000; })
#define PIN2_DIGITAL_READ() ({ (PINE & 0b00010000) == 0 ? LOW : HIGH; })
#define PIN3_DIGITAL_READ() ({ (PINE & 0b00100000) == 0 ? LOW : HIGH; })
#define PIN4_DIGITAL_READ() ({ (PING & 0b00100000) == 0 ? LOW : HIGH; })
#define PIN5_DIGITAL_READ() ({ (PINE & 0b00001000) == 0 ? LOW : HIGH; })
#define PIN6_DIGITAL_READ() ({ (PINH & 0b00001000) == 0 ? LOW : HIGH; })
#define PIN7_DIGITAL_READ() ({ (PINH & 0b00010000) == 0 ? LOW : HIGH; })
#define PIN8_DIGITAL_READ() ({ (PINH & 0b00100000) == 0 ? LOW : HIGH; })
#define PINA0_DIGITAL_READ() ({ (PINF & 0b00000001) == 0 ? LOW : HIGH; })
#define PINA1_DIGITAL_READ() ({ (PINF & 0b00000010) == 0 ? LOW : HIGH; })
#define PINA2_DIGITAL_READ() ({ (PINF & 0b00000100) == 0 ? LOW : HIGH; })
#define PINA3_DIGITAL_READ() ({ (PINF & 0b00001000) == 0 ? LOW : HIGH; })
#elif defined(__AVR_ATmega328P__) // If you are using Arduino UNO the IDE will automatically define the "__AVR_ATmega328P__" constant.
#define TIMER2_PWM_A_PIN_MODE_OUTPUT() ({ DDRB |= 0b00001000; })
#define PIN2_DIGITAL_READ() ({ (PIND & 0b00000100) == 0 ? LOW : HIGH; })
#define PIN3_DIGITAL_READ() ({ (PIND & 0b00001000) == 0 ? LOW : HIGH; })
#define PIN4_DIGITAL_READ() ({ (PIND & 0b00010000) == 0 ? LOW : HIGH; })
#define PIN5_DIGITAL_READ() ({ (PIND & 0b00100000) == 0 ? LOW : HIGH; })
#define PIN6_DIGITAL_READ() ({ (PIND & 0b01000000) == 0 ? LOW : HIGH; })
#define PIN7_DIGITAL_READ() ({ (PIND & 0b10000000) == 0 ? LOW : HIGH; })
#define PIN8_DIGITAL_READ() ({ (PINB & 0b00000001) == 0 ? LOW : HIGH; })
#define PINA0_DIGITAL_READ() ({ (PINC & 0b00000001) == 0 ? LOW : HIGH; })
#define PINA1_DIGITAL_READ() ({ (PINC & 0b00000010) == 0 ? LOW : HIGH; })
#define PINA2_DIGITAL_READ() ({ (PINC & 0b00000100) == 0 ? LOW : HIGH; })
#define PINA3_DIGITAL_READ() ({ (PINC & 0b00001000) == 0 ? LOW : HIGH; })
#endif


void initializePWMTimer() {
  cli();
  TIMER2_PWM_A_PIN_MODE_OUTPUT(); // Set the A PWM pin of TIMER2 to output
  ASSR &= ~(_BV(EXCLK) | _BV(AS2));
  TCCR2A = (1 << COM2A0) | (1 << WGM21) | (1 << WGM20);
  TCCR2B = (1 << WGM22) | (1 << CS20);
  OCR2A = 0;
  sei();
}

byte readCameraRegister(byte registerId) {
  Wire.beginTransmission(CAMERA_ADDRESS);
  Wire.write(registerId);
  Wire.endTransmission();
  Wire.requestFrom(CAMERA_ADDRESS, 1);
  while (Wire.available() <= 0);
  byte registerValue = Wire.read();
  delay(1);
  return registerValue;
}

void writeCameraRegister(byte registerId, byte registerValue) {
  Wire.beginTransmission(CAMERA_ADDRESS);
  Wire.write(registerId);
  Wire.write(registerValue);
  Wire.endTransmission();
  delay(1);
}

void captureFrame(unsigned int frameWidth, unsigned int frameHeight) {
  Serial.print("*RDY*"); // Start of frame message
  delay(1000);
  cli(); // Disable interrupts
  while (PIN3_DIGITAL_READ() == LOW); // Wait for VSYNC
  while (PIN3_DIGITAL_READ() == HIGH); // Wait until VSYNC goes low

  String pixelDataString = ""; // String to hold pixel data
  unsigned int pixelIndex = 0;

  while (frameHeight--) {
    for (unsigned int tempWidth = 0; tempWidth < frameWidth; tempWidth++) {
      while (PIN2_DIGITAL_READ() == LOW); // Wait for PCLK high
      
      // Read two bytes for RGB565
      byte highByte = 0b00000000;
      byte lowByte = 0b00000000;
      
      // Read the 8 data pins
      highByte |= ((PIN7_DIGITAL_READ() == HIGH) << 7);
      highByte |= ((PIN6_DIGITAL_READ() == HIGH) << 6);
      highByte |= ((PIN5_DIGITAL_READ() == HIGH) << 5);
      highByte |= ((PIN4_DIGITAL_READ() == HIGH) << 4);
      lowByte |= ((PINA3_DIGITAL_READ() == HIGH) << 3);
      lowByte |= ((PINA2_DIGITAL_READ() == HIGH) << 2);
      lowByte |= ((PINA1_DIGITAL_READ() == HIGH) << 1);
      lowByte |= (PINA0_DIGITAL_READ() == HIGH);
      
      // Convert RGB565 to RGB888
      byte r = (highByte & 0xF8); // Red 5 bits
      byte g = ((highByte & 0x07) << 5) | ((lowByte & 0xE0) >> 3); // Green 6 bits
      byte b = (lowByte & 0x1F) << 3; // Blue 5 bits


      // Build the string for this pixel
      pixelDataString = "(" + String(r) + "," + String(g) + "," + String(b) + ")";
      
      Serial.println(pixelDataString);
      
      while (PIN2_DIGITAL_READ() == HIGH); // Wait for PCLK low
    }
  }
  sei(); // Enable interrupts

  
  delay(1000);
}



void setup() {
  initializePWMTimer();
  Wire.begin();
  Serial.begin(115200); // Set baud rate for serial communication

  captureFrame(320, 240); // capture a frame at QVGA resolution (320 x 240)
  Serial.println("Done!");

}

My Pin configuration looks like this:

// SDA/SIOD ---> pin A4

// SCL/SIOC ---> pin A5

// MCLK/XCLK --> pin 11

// PCLK -------> pin 2

// VS/VSYNC ---> pin 3

// HS/HREF ----> pin 8

// D0 ---------> pin A0

// D1 ---------> pin A1

// D2 ---------> pin A2

// D3 ---------> pin A3

// D4 ---------> pin 4

// D5 ---------> pin 5

// D6 ---------> pin 6

// D7 ---------> pin 7

Can anyone help me to find the problem here?

I am also using 10kOhm pull up resistors for SDA and SCL and a voltage divider with a 1kOhm GND->XCLK and 680Ohm D3->XCLK

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.